Image Thresholding
จาก Morange Wiki
เนื้อหา
Image Thresholding
วัตถุประสงค์
- เนื้อหาในบทนี้ จะเรียนรู้เกี่ยวกับ แบ่งเส้น แบบง่ายๆ (Simple thresholding) ,การแบ่งแบบ Adaptive,การแบ่งแบบ Otsu's
- คุณจะได้เรียนรู้ฟังก์ชั่นเหล่านี้: cv2.threshold, cv2.adaptiveThreshold ฯลฯ
Simple Thresholding การแบ่งแบบง่ายๆ
- ฟังก์ชั่นที่ใช้มีชื่อว่า cv2.threshold ในอาร์กิวเมนต์แรก จะเป็นภาพต้นฉบับ ซึ่งควรจะเป็นภาพสีเทา (Grayscale)
- อาร์กิวเมนต์ที่สองคือค่าเกณฑ์ที่ใช้ในการจำแนกค่าพิกเซล
- อาร์กิวเมนต์ที่สามเป็น maxVal ซึ่งหมายถึงค่าที่จะได้รับถ้าค่าพิกเซลเป็นมากกว่า (บางครั้งน้อยกว่า) มูลค่าเกณฑ์ โดย OpenCV จะทำให้รูปแบบที่แตกต่างกันของ thresholding และจะตัดสินใจโดยพารามิเตอร์ที่สี่ของการทำงาน ชนิดที่แตกต่างกัน มีคำสั่งอื่นๆดังนี้ :
- cv2.THRESH_BINARY
- cv2.THRESH_BINARY_INV
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2.THRESH_TOZERO_INV
ทดลองเขียน Code
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('gradient.png',0) ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV) ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC) ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO) ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV) titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV'] images = [img, thresh1, thresh2, thresh3, thresh4, thresh5] for i in xrange(6): plt.subplot(2,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
ผลลัพธ์
Adaptive Thresholding
- Adaptive Method- มันตัดสินใจว่าค่ากำหนดเกณฑ์ขั้นต่ำที่มีการคำนวณ
- cv2.ADAPTIVE_THRESH_MEAN_C: ค่าเกณฑ์เป็นค่าเฉลี่ยของพื้นที่เขต
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C: ค่าเกณฑ์เป็นน้ำหนักรวมของค่าเขตที่น้ำหนักหน้าต่าง Gaussian
- Block Size - มันตัดสินใจที่ขนาดของพื้นที่บริเวณใกล้เคียง
- C - เป็นเพียงค่าคงที่ซึ่งถูกหักออกจากค่าเฉลี่ยหรือจากการคำนวณค่าเฉลี่ยถ่วงน้ำหนัก
ทดลองเขียน Code
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('dave.jpg',0) img = cv2.medianBlur(img,5) ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\ cv2.THRESH_BINARY,11,2) th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ cv2.THRESH_BINARY,11,2) titles = ['Original Image', 'Global Thresholding (v = 127)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] images = [img, th1, th2, th3] for i in xrange(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
ผลลัพธ์
Otsu’s Binarization
- Otsu’s Binarization คืออะไร?
- ใน Thresholding เราใช้ค่าที่กำหนดเองสำหรับค่าเกณฑ์เอง ดังนั้นวิธีการที่เราสามารถรู้ค่าที่เราเลือกนั้นเป็นสิ่งที่ดีหรือไม่? คำตอบคือหาจากการทดลองและความผิดพลาด แต่พิจารณาภาพ bimodal สำหรับภาพที่เราสามารถใช้เวลาประมาณค่าในช่วงกลางของยอดเขาเหล่านั้นเป็นค่าเกณฑ์ใช่มั้ย? นั่นคือสิ่งที่ Otsu Binarization ไม่ ดังนั้นในคำง่ายโดยจะคำนวณค่าเกณฑ์จาก histogram ที่ภาพเพื่อดูภาพ bimodal (สำหรับภาพที่ไม่ได้ bimodal, Binarization จะไม่ถูกต้อง
- สำหรับเรื่องนี้คำสั่งที่จะใช้คือ cv2.threshold() cv2.THRESH_OTSU
- สามารถทำตัวอย่าง และ ตรวจสอบตัวอย่างว่า ภาพที่นำเข้าเป็นภาพที่มีการแตหรือไม่ ในกรณีแรกที่นำมาใช้กำหนดเกณฑ์ขั้นต่ำ Global ไว้ที่ 127 ในกรณีที่สองใช้ thresholding Otsu โดยตรง ในกรณีที่สามผมกรองภาพที่มีเคอร์เนล Gaussian 5x5 เพื่อลบสี่งรบกวนจากนั้นนำไปใช้ใน Otsu Thresholding ดูวิธีการกรองสิ่งรบกวนแบบดีขึ้น
Code ตัวอย่าง Otsu's Binarization
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('noisy2.png',0) # global thresholding ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) # Otsu's thresholding ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # Otsu's thresholding after Gaussian filtering blur = cv2.GaussianBlur(img,(5,5),0) ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # plot all the images and their histograms images = [img, 0, th1, img, 0, th2, blur, 0, th3] titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)', 'Original Noisy Image','Histogram',"Otsu's Thresholding", 'Gaussian filtered Image','Histogram',"Otsu's Thresholding"] for i in xrange(3): plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray') plt.title(titles[i*3]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256) plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray') plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([]) plt.show()
ผลลัพธ์
ทำยังไง Otsu's Binarization ถึงเวิร์ค ?
- ในส่วนนี้จะแสดงให้เห็นว่าภาษา Python สามารถใช้งาน Otsu's Binarization เพื่อแสดงให้เห็นวิธีการใช้งาน
- เนื่องจากมีการทำงานกับภาพที่เป็น algorithm bimodal โดยจะพยายามหาค่า (T) ซึ่งจะช่วยลดการถ่วงน้ำหนักการแปรปรวนในชั้นที่มีความสัมพันธ์
และมีสูตรทางคณิตศาสตร์ดังนี้