January 14, 2019
ก่อนจะรู้จัก Simple Thresholding เรามาดูความหมายของคำว่า Threshold กันก่อน
Threshold ก็คือเกณฑ์ที่ใช้แบ่งสิ่งใดสิ่งหนึ่ง เช่น
มีรถอยู่ 5 คัน ขับด้วยความเร็ว ดังนี้ 60, 156, 120, 80 และ 180 กม.ต่อชม. แล้วเราก็เถียงกับเพื่อนว่า คันไหนขับเร็ว คันไหนขับช้า เราเลยต้องมีเกณฑ์มาแบ่ง
สมมติเราให้ รถที่ขับเร็วกว่า 90 กม.ต่อชม. เป็นรถที่ขับเร็ว เราเรียกค่านี้ว่า Threshold Value
ภาพที่จะพูดถึงในบทความจะมีความลึกของสีอยู่ที่ 8-bit หรือมีค่า intensity อยู่ระหว่าง 0 - 255
คือ การนำภาพ 1 Channel (หรือ Grayscale Image) มาแปลงค่า intesity ของแต่ละ Pixel ให้เหลือเพียง 2 ค่า คือ 0(ดำ) กับ 255(ขาว) เราเรียกภาพที่มีค่า intensity เพียง 2 ค่า ว่า “Binary Image” โดยเราจะใช้ Threshold Value ในการแบ่งว่า Pixel ที่มี intensity XX ควรมีค่าเท่าไหร่ ดังนี้
สมมติ เรามีภาพอยู่หนึ่งภาพ แล้วอยากลบพื้นหลังออก (บางภาพก็อาจจะใช้วิธีนี้ไม่ได้)
โดยการแปลงเป็น Grayscale ก่อน
แล้วดู Histogram (ใครไม่รู้ว่า histogram คืออะไร ลองอ่านอันนี้ดูนะครับ) ว่ามีค่าสีไปกองอยู่ตรงไหนเยอะ เพราะ ถ้าเราลองสังเกตดู background ส่วนใหญ่จะเป็นสีฟ้าโทนเดียวกันหมดเลย แล้วก็มีจำนวน pixel เกินครึ่งนึงของรูปภาพ
ก็แสดงว่าบริเวณที่ ค่า intensity มีจำนวน pixel เยอะ หรือพูดง่ายๆก็คือ บริเวณที่กราฟสูงๆฐานกว้างกว่าจุดอื่นนั้นแหละ คือ background
ถ้าเป็นภาพนี้ก็จะเห็นว่าค่าสีส่วนใหญ่ มากกว่า 160 เราจึงใช้ 160 เป็น Threshold Value จะได้ผลลัพธ์ดังนี้
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('00.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([gray], [0], None, [256], [0, 256])
_, th = cv2.threshold(gray,160,255,cv2.THRESH_BINARY)
cv2.imshow('images', img)
cv2.imshow('Simple Thresholding', th)
cv2.imshow('Grayscale', gray)
plt.plot(hist, color='blue')
plt.title('Histogram of Grayscale')
plt.show()
จากผลลัพธ์ Pixel ที่เป็นสีดำจะมีค่าเป็น 0 ส่วนสีขาวจะมีค่าเป็น 255 ซึ่งเพิ่งเท่านี้เรายังไม่สามารถลบ พื้นหลัง ออกได้เดี๋ยวคราวหน้าจะมาสอนสร้าง mask ไว้คุมตัวโคนันแล้วลบพื้นหลังทิ้ง
มาดูฟังก์ชั่นที่เราใช้หา Threshold กัน
ฟังก์ชั่นที่ใช้ก็จะเป็น
cv2.threshold(Grayscale, th_value, max_value, style)
parameter | ความหมาย |
---|---|
Grayscale | ภาพขาวดำ ที่จริงมันก็คือ ภาพที่มี 1 Channel เราอาจจะไม่ต้องแปลงเป็น Grayscale แต่เอา Channel R, G หรือ B มาใช้เลยก็ได้ด้วยการใช้ Function cv2.split() |
th_value | Threshold value นั้นแหละครับ |
max_value | ค่าสีที่ใช้แสดง เมื่อ Pixel นั้นมีค่ามากกว่า th_value เช่น ถ้าเราลดจาก 255 เป็น 200 ภาพผลลัพธ์ที่ได้จากสีขาวก็จะกลายเป็นสีออกเทาๆ |
style | ลักษณะผลลัพธ์ แบบที่เราใช้ก็เป็นแบบธรรมดา ถ้าเติม _INV ไปก็จะ invert สีผลลัพธ์ให้ตรงกันข้าม ลองไปเล่นกันดูมีทั้งหมด 5 แบบ ตามด้านล้างเลย |
cv2.THRESHOLD_BINARY
cv2.THRESHOLD_BINARY_INV
cv2.THRESHOLD_TRUNC
cv2.THRESHOLD_TOZERO
cv2.THRESHOLD_TOZERO_INV
บทความนี้ก็จบเพียงเท่านี้ คราวหน้าเราจะมาคุยกันเรื่อง Adaptive Thresholding นะครับ