OpenCV-Python Tutorials (3) ~Image Processing in OpenCV~
OpenCV-Python Tutorialsã®è¨äºï¼Image Processing in OpenCV ã®ç« ã«å ¥ãã¾ãï¼
å ¬å¼ï¼Image Processing in OpenCV — OpenCV-Python Tutorials 1 documentation
è²ç©ºéã®å¤æ
ç®æ¨
- ãã®ãã¥ã¼ããªã¢ã«ã§ã¯ï¼BGR Grayï¼BGR HSV ãªã©ã®ç»åãããè²ç©ºéããä»ã®è²ç©ºéã¸å¤æããæ¹æ³ãå¦ã¶ï¼
- å ãã¦ï¼åç»ã®ä¸ã§è²ã®ã¤ããç©ä½ãæ½åºããã¢ããªã±ã¼ã·ã§ã³ãä½ã
- 次ã®é¢æ°ãå¦ã¶ï¼cv2.cvtColor()ï¼cv2.inRange()ãªã©
è²ç©ºéã®å¤æ
OpenCV ã§ã¯ï¼150以ä¸ã®è²ç©ºéã®å¤æææ³ãå©ç¨å¯è½ã ï¼ãããä»åã¯æãåºã使ããã¦ããï¼BGR Grayï¼BGR HSVï¼ã®2ã¤ã ããè¦ã¦ããï¼
è²ã®å¤æã§ã¯ï¼cv2.cvtColor(input_image, flag)
ã¨ããé¢æ°ã使ãï¼flag
ã§å¤æã®ç¨®é¡ã決ããï¼
BGR Gray ã®å¤æã§ã¯ï¼cv2.COLOR_BGR2GRAY
ãï¼BGR HSV ã§ã¯ä¼¼ããããªï¼cv2.COLOR_BGR2HSV
ã使ãï¼ä»ã®flagãå¾ãããã«ã¯ï¼Pythonã®ã¿ã¼ããã«ã§æ¬¡ã®ã³ãã³ããå©ãã ãã§è¯ãï¼
>>> import cv2 >>> flags = [i for i in dir(cv2) if i.startswith('COLOR_')] >>> print(flags)
ã¡ã¢
HSV ã§ã¯ï¼è²ç¸ (Hue) ã®ç¯å²ã¯[0,179]ï¼å½©åº¦ (Saturation) ã®ç¯å²ã¯[0,255]ï¼æ度 (Value) ã®ç¯å²ã¯[0,255] ã¨ãªã£ã¦ããï¼éãã½ããã¦ã§ã¢ã§ã¯éãã¹ã±ã¼ã«ã使ãããããï¼ãããã§åºããå¤ã¨OpenCVã§åºããå¤ã¨ãæ¯è¼ããå ´åã¯ï¼ãã®ç¯å²ã«çµ±ä¸ããå¿ è¦ãããï¼
ç©ä½ã®ãã©ããã³ã°
ã㦠BGR ç»åãã HSV ã«å¤æããæ¹æ³ãããã£ãã®ã§ï¼ãããè²ã®ã¤ããç©ä½ãæ½åºããã®ã«ä½¿ããï¼HSV ã§ã¯ RGB è²ç©ºéããè²ã表ç¾ããã®ãç°¡åã ï¼ããããä½ãã¢ããªã±ã¼ã·ã§ã³ã§ã¯ï¼éè²ã®ç©ä½ãæ½åºã試ã¿ãï¼æ¬¡ã«ç¤ºãã®ããã®ããæ¹ã ï¼
- åç»ã®ããããã®ãã¬ã¼ã ãåå¾ãã
- BGR ãã HSV è²ç©ºéã«å¤æãã
- éè²ã®ç¯å²ã§ HSV ç»åãé¾å¤ã§å¤å®ãã
- ããã§éãç©ä½ã®ã¿ãæ½åºã§ããã®ã§ï¼ãã®ç»åã好ããªããã«ã§ãã
以ä¸ãã³ã¼ãï¼
import cv2 import numpy as np cap = cv2.VideoCapture(0) while(1): # ããããã®ãã¬ã¼ã ãåå¾ _, frame = cap.read() # BGR ãã HSV ã«å¤æ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # HSV ã§ã®éè²ã®ç¯å²ãå®ç¾© lower_blue = np.array([110, 50, 50]) upper_blue = np.array([130, 255, 255]) # HSVã®ç»åãäºå¤åãã¦éè²ã®ç©ä½ã ããåå¾ mask = cv2.inRange(hsv, lower_blue, upper_blue) # ãã¹ã¯ã¨å ç»åã® AND ãã¨ã res = cv2.bitwise_and(frame, frame, mask= mask) cv2.imshow('frame',frame) cv2.imshow('mask', mask) cv2.imshow('res', res) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows()
ã¡ã¢
ç»åä¸ã«ãããããã¤ãºãã®ã£ã¦ããï¼å¾ã®ç« ã§ï¼ããããã©ããã£ã¦åãé¤ãããè¦ã¦ããï¼
ã¡ã¢
ãããç©ä½ã®ãã©ããã³ã°ã®æãåç´ãªæ¹æ³ã ï¼è¼ªéãåå¾ããé¢æ°ãå¦ã¹ã°ï¼ç©ä½ã®éå¿ãè¦ã¤ãã¦ãããå ã«ç©ä½ããã©ããã³ã°ããï¼ã«ã¡ã©ã®åã§æãåãããªã©ã«ãã£ã¦å³å½¢ãæãã¨ãããããªããããã®ãã¨ãã§ããï¼
ãã©ããã³ã°ã®ããã® HSV ã®å¤ã®æ¢ãæ¹
ãã㯠stackoverflow.comã§ä¸çªãããã質åã ï¼ããã¯ã¨ã¦ãã·ã³ãã«ã§åãé¢æ° cv2.cvtColor() ã使ããï¼ç»åã渡ã代ããã«ï¼æ¬²ãã BGR å¤ã渡ãï¼ä¾ãã°ï¼ç·è²ã® HSV å¤ãç¥ãããå ´åï¼Pythonã®ã¿ã¼ããã«ã§ä»¥ä¸ã®ãããªã³ãã³ããå©ãã°è¯ãï¼
>>> green = np.uint8([[[0,255,0 ]]]) >>> hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV) >>> print(hsv_green) [[[ 60 255 255]]]
ããã§ï¼æå°å¤ã¨æ大å¤ã [H-10, 100,100] 㨠[H+10, 255, 255] ã«ãããã決ããããï¼ãã®ææ³ããé¢ãã¦ï¼ GIMP ãå¤ãè¦ã¤ããããã®ãªã³ã©ã¤ã³ã§ã®ã³ã³ãã¼ã¿ã®ãããªç»åç·¨éãã¼ã«ã使ããã¨ãã§ãããï¼HSV ã®ç¯å²ã«èª¿æ´ãããã¨ããå¿ããªãï¼
追å è³æ
ç·´ç¿
- 2è²ä»¥ä¸ã®ç©ä½ãæ½åºããæ¹æ³ãæ¢ãã¦ã¿ããï¼
ç»åã®å¹¾ä½å¦çå¤æ
ç®æ¨
- 移åï¼å転ï¼ã¢ãã£ã³å¤æãªã©ã®ç°ãªãå¹¾ä½å¦çå¤æã®ç»åã¸ã®é©ç¨ãå¦ã¶
- cv2.getPerspectiveTransform ã¨ãã£ãé¢æ°ã使ã
å¤æ
OpenCVã¯2ã¤ã®å¤æã®é¢æ°ãæä¾ãã¦ããï¼cv2.warpAffine and cv2.warpPerspectiveã®2ã¤ã ãï¼ããã§ãã¹ã¦ã®ç¨®é¡ã®ç§»åãã§ããï¼å ¥åã¨ãã¦ï¼cv2.warpAffine 㯠2x3 ã®å¤æè¡åã使ãï¼cv2.warpPerspective 㯠3x3 ã®å¤æè¡åã使ãï¼
æ¡å¤§ç¸®å°
æ¡å¤§ç¸®å°ã¯ç»åããªãµã¤ãºããã ãã ï¼OpenCVã§ã¯ cv2.resize() é¢æ°ããã®ç®çã«å¯¾å¿ãããã®ã ï¼ç»åã®ãµã¤ãºãæåã§æ±ºãããï¼æ¡å¤§ç¸®å°ã®è¦ç´ ãè¨å®ããã°è¯ãï¼ä»ã®è£å®ææ³ã使ãããï¼ç¸®å°ã«å¯¾ãã¦ã¯ cv2.INTER_AREAï¼æ¡å¤§ã«å¯¾ãã¦ã¯ cv2.INTER_CUBIC (é ã) 㨠cv2.INTER_LINEAR ãããæã¾ããè£å®ææ³ã ï¼ããã©ã«ãã§ã¯ï¼è£å®ææ³ã¯ãã¹ã¦ã®æ¡å¤§ã»ç¸®å°ã®ç®çã«å¯¾ã㦠cv2.INTER_LINEAR ã使ããã¦ããï¼å ¥åç»åã以ä¸ã®ããããã®æ¹æ³ã§æ¡å¤§ã»ç¸®å°ã§ããï¼
In [2]: import cv2 In [3]: import numpy as np In [4]: img = cv2.imread('messi.jpg') In [5]: res = cv2.resize(img, None, fx=2, fy=2, interpolation = cv2.INTER_CUBIC) # ã¾ã㯠In [7]: height, width = img.shape[:2] In [8]: res = cv2.resize(img, (2*width, 2*height), interpolation = cv2.INTER_CUBIC)
移å
移å(Translation)ã¯å¯¾è±¡ç©ã®ä½ç½®ãåããå¦çã ï¼ æ¹åã®ç§»åãããã£ã¦ããå ´åï¼ããã ã¨ç½®ãã¨ï¼æ¬¡ã®ãããªå¤æè¡å ãä½ããï¼
ãããnp.float32
åã®Numpyã®arrayã«å
¥ãã¦ï¼cv2.warpAffine() é¢æ°ã«æ¸¡ãï¼ä»¥ä¸ã (100, 50) 移åã®å ´åã®ã³ã¼ãã ï¼
In [3]: import cv2 In [4]: import numpy as np In [5]: img = cv2.imread('mess') messi.jpg messi.png In [5]: img = cv2.imread('messi.jpg', 0) In [6]: rows, cols = img.shape In [7]: M = np.float32([[1,0,100],[0,1,50]]) In [8]: dst = cv2.warpAffine(img,M,(cols,rows)) In [9]: cv2.imshow('img',dst) In [10]: cv2.waitKey(0) Out[10]: 46 In [11]: cv2.destroyAllWindows()
注æ
cv2.warpAffine() é¢æ°ã®3ã¤ç®ã®å¼æ°ã¯åºåç»åã®ãµã¤ãºã§ï¼(width, height) ã®å½¢ãã¨ãï¼
çµæã¯ä¸ã®ããã«ãªã£ãï¼
å転
è§åº¦ã®å転ã¯æ¬¡ã®å¤æè¡åã§ã§ãã
ãããï¼OpenCVã¯ã©ã®ä½ç½®ã«ãã£ã¦ãå転ã§ããããã«å転ä¸å¿ã調æ´ããå転ãæä¾ãã¦ããï¼ãã®å¤æè¡åã¯æ¬¡ã®ããã«ãªãï¼
ãã ãï¼
å¤æè¡åãæ¢ãããã«ã¯ï¼OpenCVã¯cv2.getRotationMatrix2Dã¨ããé¢æ°ãæä¾ãã¦ããï¼æ¬¡ã®ä¾ã¯æ¡å¤§ã»ç¸®å°ãªãã§ç»åã90度å転ããããã®ã ï¼
In [14]: img = cv2.imread('messi.jpg', 0) In [15]: rows, cols = img.shape In [16]: M = cv2.getRotationMatrix2D((cols/2,rows/2), 90, 1) In [17]: dst = cv2.warpAffine(img, M, (cols, rows)) In [18]: cv2.imshow('img',dst) In [19]: cv2.waitKey(0)
çµæã¯æ¬¡ã®ããã«ãªã£ãï¼
ã¢ãã£ã³å¤æ
ã¢ãã£ã³å¤æã§ã¯ï¼å ç»åã§å¹³è¡ãªç·ã¯åºåç»åã§ãå¹³è¡ã®ã¾ã¾ã¨ãªãï¼å¤æè¡åã決ããããã«ï¼å ¥åç»åä¸ã®3ç¹ã¨åºåç»åã«å¯¾å¿ããä½ç½®ãå¿ è¦ã ï¼cv2.getAffineTransform ã¯cv2.warpAffineã«æ¸¡ã 2x3 ã®è¡åãä½æããï¼
ä¸ã®ä¾ãè¦ã¦ã¿ããï¼ããã¦ï¼é¸æãããï¼ç·ã§å°ãä»ãããã¦ããï¼ç¹ãè¦ã¦ã¿ããï¼
In [1]: import cv2 In [2]: import numpy as np In [3]: import matplotlib.pyplot as plt In [4]: img = cv2.imread('image.png') In [5]: rows, cols, ch = img.shape In [6]: pts1 = np.float32([[30,30],[100,30],[30,100]]) In [7]: pts2 = np.float32([[10,70],[100,30],[70,150]]) In [8]: M = cv2.getAffineTransform(pts1,pts2) In [9]: dst = cv2.warpAffine(img,M,(cols,rows)) #é¸æãããç¹ã«å°ãã¤ãã In [10]: img = cv2.circle(img,(30,30), 3, (0,255,0), -1) In [11]: img = cv2.circle(img,(100,30), 3, (0,255,0), -1) In [12]: img = cv2.circle(img,(30,100), 3, (0,255,0), -1) In [13]: dst = cv2.circle(dst,(10,70), 3, (0,255,0), -1) In [14]: dst = cv2.circle(dst,(100,30), 3, (0,255,0), -1) In [15]: dst = cv2.circle(dst,(70,150), 3, (0,255,0), -1) In [16]: plt.subplot(121),plt.imshow(img),plt.title('Input') Out[16]: (<matplotlib.axes._subplots.AxesSubplot at 0x10778c0f0>, <matplotlib.image.AxesImage at 0x10a929518>, <matplotlib.text.Text at 0x10a909320>) In [17]: plt.subplot(122),plt.imshow(dst),plt.title('Output') Out[17]: (<matplotlib.axes._subplots.AxesSubplot at 0x10a93ec18>, <matplotlib.image.AxesImage at 0x10a987be0>, <matplotlib.text.Text at 0x10a96b7f0>) In [18]: plt.show()
çµæã¯æ¬¡ã®ããã«ãªã£ãï¼
éè¦å¤æ
éè¦å¤æã«ã¯ï¼3x3ã®å¤æè¡åãå¿ è¦ã ï¼ãã®å¤æã§ã¯ç´ç·ã¯ç´ç·ã®ã¾ã¾æ®ãï¼ãã®å¤æè¡åã決ããããã«ã¯ï¼å ¥åç»åä¸ã®4ç¹ã¨å¯¾å¿ããåºåç»åä¸ã®ç¹ãå¿ è¦ã¨ãªãï¼ããã4ç¹ã®ãã¡ï¼3ç¹ã¯å ±ç·ï¼3ç¹ãåä¸ç´ç·ä¸ã«ãããã¨ï¼ã§ãã£ã¦ã¯ãªããªãï¼ããã¦ï¼cv2.getPerspectiveTransformé¢æ°ã«ãã£ã¦å¤æè¡åã決ãããï¼cv2.warpPerspectiveã«æ¸¡ãï¼
以ä¸ã®ã³ã¼ããè¦ã¦ã¿ããï¼
In [1]: import cv2 In [2]: import numpy as np In [3]: import matplotlib.pyplot as plt In [4]: img = cv2.imread('goBoard.jpg') In [5]: rows, cols. ch = img.shape # 4ç¹ã¨ä¸å¿ç·ãæã In [8]: img = cv2.circle(img,(67,35),5,(0,255,0),-1) In [9]: img = cv2.circle(img,(430,36),5,(0,255,0),-1) In [10]: img = cv2.circle(img,(14,416),5,(0,255,0),-1) In [11]: img = cv2.circle(img,(482,417),5,(0,255,0),-1) In [12]: img = cv2.line(img,(0,250), (513,250),(0,255,0),2) In [13]: img = cv2.line(img,(256,0), (256,500),(0,255,0),2) In [14]: pts1 = np.float32([[67,35],[430,36],[14,416],[482,417]]) In [15]: pts2 = np.float32([[0,0],[513,0],[0,500],[513,500]]) In [16]: M = cv2.getPerspectiveTransform(pts1,pts2) In [17]: dst = cv2.warpPerspective(img,M,(513,500)) In [18]: plt.subplo plt.subplot plt.subplot2grid plt.subplot_tool plt.subplots plt.subplots_adjust In [18]: plt.subplot(121),plt.imshow(img),plt.title('Input') Out[18]: (<matplotlib.axes._subplots.AxesSubplot at 0x10b1450b8>, <matplotlib.image.AxesImage at 0x10e1679b0>, <matplotlib.text.Text at 0x10e13de10>) In [19]: plt.subplot(122),plt.imshow(dst),plt.title('Output') Out[19]: (<matplotlib.axes._subplots.AxesSubplot at 0x10e179160>, <matplotlib.image.AxesImage at 0x110295748>, <matplotlib.text.Text at 0x110270da0>) In [20]: plt.show()
çµæï¼
ãªãã ãã®è²ã¯â¦
ãã¾ã
ãªããå¤ãªè²ã«ãªã£ãã®ã§inputã®ç»åãåºãã¦ã¿ã
In [21]: cv2.imwrite('input.jpg',im) image.png img import In [21]: cv2.imwrite('input.jpg',img) Out[21]: True
ã©ãã§å¤ãã£ããã ããâ¦
追å è³æ
- âComputer Vision: Algorithms and Applicationsâ, Richard Szeliski
ç»åã®äºå¤å
ç®æ¨
ãã®ãã¥ã¼ããªã¢ã«ã§ã¯ï¼Simple thresholdingï¼Adaptive thresholdingï¼Otsuâs thresholding ãå¦ã¶
次ã®é¢æ°ãå¦ã¶ï¼cv2.thresholdï¼cv2.adaptiveThreshold
Simple Thresholding
ãã¯ã»ã«å¤ãé¾å¤ä»¥ä¸ã§ããã°1ï¼ããã§ãªããã°0ãå²ãå½ã¦ãï¼ä½¿ãããé¢æ°ã¯ cv2.threshold ã§ï¼æåã®å¼æ°ã¯ã½ã¼ã¹ã®ç»åï¼2çªç®ã®å¼æ°ã¯ãã¯ã»ã«å¤ãåé¡ããããã®é¾å¤ï¼3çªç®ã®å¼æ°ã¯ãã¯ã»ã«å¤ãé¾å¤ãã大ããï¼ã¾ãã¯å°ããï¼å¤ã«ãªãæã«ä¸ããããå¤ã表ãæ大å¤ã ï¼OpneCVã¯ç°ãªã種é¡ã®äºå¤åãæä¾ãã¦ãã¦ï¼ãã®ã©ãã§ãããã¯é¢æ°ã®4çªç®ã®ãã©ã¡ã¼ã¿ã«ãã£ã¦æ±ºã¾ãï¼ãã®ç¨®é¡ã¯ï¼
- cv2.THRESH_BINARY
- cv2.THRESH_BINARY_INV
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2.THRESH_TOZERO_INV
ããã¥ã¡ã³ãã¯æ確ã«ããããã®ã¿ã¤ãã«ã©ããªæå³ããããã説æãã¦ããï¼ããã¥ã¡ã³ããåç §ãããï¼
2ã¤ã®åºåãå«ã¾ãã¦ããï¼1ã¤ç®ã¯å¾ã«èª¬æããæ»ãå¤ã ï¼2ã¤ç®ã¯äºå¤åãããç»åã ï¼
ã³ã¼ãï¼
#!/usr/bin/python # _*_ coding: utf-8 -*- 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 range(6): plt.subplot(2, 3, i+1),plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
ã¡ã¢
å¤æ°ã®ç»åãããããããããã«ï¼é¢æ° plt.subplot() ã使ã£ãï¼è©³ç´°ã¯ï¼ Matplotlib ã®ããã¥ã¡ã³ããåç §ãããï¼
çµæã¯æ¬¡ã®ããã«ãªãï¼
Adaptive Thresholding
åã®ç¯ã§ã¯ï¼äºå¤åã®é¾å¤ã¨ãã¦ã°ãã¼ãã«å¤ãç¨ããï¼ãããï¼å¥ã®ã¨ãªã¢ã§ã¯ç»åã¯ç°ãªãç §ææ¡ä»¶ãæã¤ãããªå ¨ã¦ã®ç¶æ³ã§ãã®ããæ¹ã¯è¯ããªããããããªãï¼ãã®å ´åï¼adaptive thresholding ã使ããï¼ãã®æ¹æ³ã§ã¯ã¢ã«ã´ãªãºã ãç»åã®å°é åã¸äºå¤åãã¦ãããï¼å¾ã£ã¦åãç»åã®ç°ãªãé åã«ç°ãªã£ãäºå¤åããã¦ããï¼ç §åº¦ãå¤åãã¦ããç»åã§ãããè¯ãçµæãå¾ããã¨ãã§ããï¼
3ã¤ã®ç¹å¥ãªå ¥åãã©ã¡ã¼ã¿ã¨1ã¤ã®åºåå¼æ°ãæã¤ï¼
Adaptive Method - é¾å¤ãã©ã®ããã«è¨ç®ãããã決ãã
- cv2.ADAPTIVE_THRESH_MEAN_C : é¾å¤ã¯è¿ãã®ã¨ãªã¢ã®å¹³åï¼
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C : é¾å¤ã¯ã¬ã¦ã¹çªã«ãã£ã¦éã¿ä»ããããè¿ãã®å¤ã®åè¨ã§éã¿ä»ããããå¤ã§ããï¼
Block Size - è¿ãã®ã¨ãªã¢ã®å¤§ããã決ãã
C - å¹³åãéã¿ä»ããããå¹³åããå¼ãããå®æ°
次ã®ã³ã¼ãã§ç §åº¦ãå¤åãã¦ããç»åã«å¯¾ã㦠global thresholding 㨠adaptive thresholding ãæ¯ã¹ãï¼
#!/usr/bin/python # _*_ coding: utf-8 -*- 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 range(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
æåã®èª¬ã§ï¼2ã¤ç®ã®ãã©ã¡ã¼ã¿ retVal ãããã¨è¿°ã¹ãï¼ãã㯠Otsu's Binarization ã®æã«ä½¿ãï¼
ã°ãã¼ãã«ãªäºå¤åã§ã¯ï¼é¾å¤ã¨ãã¦ä»»æã®å¤ã使ã£ãï¼ããããã®é¸ã°ãããã®ãè¯ãå¤ãæªãå¤ãã¯ã©ããã£ã¦ç¥ãã®ã ããï¼çãã¯ï¼è©¦è¡é¯èª¤ã«ããããæ¹ã ï¼ãããï¼bimodel imageï¼ç°¡åã«è¨ãã¨ï¼bimodel image ã¯2ã¤ã®å³°ãæã£ãç»åã ï¼ã«ã¤ãã¦èãã¦ã¿ããï¼ãã®ç»åã§ã¯ï¼ãããã®å³°ã®ä¸éå¤ãé¾å¤ã¨ãã¦å¤§ã¾ãã«åãããã§ã¯ãªããï¼ããã Otsu binarization ããããã¨ã ï¼å¾ã£ã¦ç°¡åã«è¨ãã¨ï¼ãã㯠bimodel image ã«å¯¾ãã¦ç»åã®ãã¹ãã°ã©ã ããé¾å¤ã大ã¾ãã«è¨ç®ããï¼ï¼bimodel image ã§ãªãç»åã«å¯¾ãã¦ã¯ï¼äºå¤åã¯æ£ç¢ºã§ãªãã ããï¼ï¼
ãã®ããã«é¢æ° cv2.threshold() ã¯ä½¿ããããï¼cv2.THRESH_OTSU ã¨ãã追å ã®ãã©ã°ã渡ãï¼é¾å¤ã¨ãã¦ã¯åç´ã«0ã渡ãï¼ããããã¨ã¢ã«ã´ãªãºã ãæé©ãªé¾å¤ãè¦ã¤ãã¦2ã¤ç®ã®åºåretVal
ã¨ãã¦è¿ãã¦ãããï¼
次ã®ä¾ãè¦ã¦ã¿ããï¼å ¥åç»åã¯éé³ç»åã ï¼1ã¤ç®ã¯ï¼é¾å¤ã127ã¨ãã¦ã°ãã¼ãã«ãªäºå¤åã使ã£ãï¼2ã¤ç®ã¯ï¼Otsu's thresholding ãç´æ¥ä½¿ã£ãï¼3ã¤ç®ã¯ï¼5x5ã®ã¬ã¦ã¹ã«ã¼ãã«ï¼gaussian kernelï¼ã§ç»åã«ãã£ã«ã¿ã¼ããããå¾ï¼Otsu's thresholding ã使ã£ãï¼ãã¤ãºãã£ã«ã¿ãªã³ã°ãã©ããããçµæãè¯ãããããè¦ã¦ã¿ããï¼
#!/usr/bin/python # _*_ coding: utf-8 -*- import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('noisy.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) # plt all the images and their histgrams images = [img, 0, th1, img, 0, th2, blur, 0, th3] titles = ['Original Noisy Image', 'Histgram', 'Global Thresholding (v=127)', 'Original Noisy Image', 'Histgram', "Otsu's Thresholding", 'Gaussian filterd Image', 'Histgram', "Otsu's Thresholding"] for i in range(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 ã®ä»çµã¿
ãã®ç¯ã§ã¯ Otsu's binarization ã®Pythonã®å®è¡ã§å®éã«ã©ããã£ã¦åãã¦ãããã説æããï¼èå³ããªããªãã¹ããããã¦ã大ä¸å¤«ï¼
äºå¤åç»åãæ±ã£ã¦ããã®ã§ï¼Otsu's algorithm ã¯æ¬¡ã®å¼ã§ä¸ããããéã¿ä»ããããç´å åæ£ãæå°ã«ããé¾å¤ãè¦ã¤ãããã®ã ï¼
ããã§ï¼
ã&ã
ã&ã
ããã«ãã£ã¦ä¸¡æ¹ã®ã¯ã©ã¹ã®åæ£ãæå°ã¨ãªããããªäºã¤ã®ãã¼ã¯ã®éã«ãããããªå¤ãè¦ã¤ããï¼ããã¯Pythonã§æ¬¡ã®ããã«ç°¡åã«å®è¡ã§ããï¼
img = cv2.imread('noisy2.png',0) blur = cv2.GaussianBlur(img,(5,5),0) # find normalized_histogram, and its cumulative distribution function hist = cv2.calcHist([blur],[0],None,[256],[0,256]) hist_norm = hist.ravel()/hist.max() Q = hist_norm.cumsum() bins = np.arange(256) fn_min = np.inf thresh = -1 for i in range(1,256): p1,p2 = np.hsplit(hist_norm,[i]) # probabilities q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes b1,b2 = np.hsplit(bins,[i]) # weights # finding means and variances m1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2 v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2 # calculates the minimization function fn = v1*q1 + v2*q2 if fn < fn_min: fn_min = fn thresh = i # find otsu's threshold value with OpenCV function ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) print thresh,ret
ï¼ããã§ããã¤ãæ°ããåºã¦ããé¢æ°ããããï¼ãããã¯ããããã®ç« ã§èª¬æããï¼
追å è³æ
- Digital Image Processing, Rafael C. Gonzalez
ç·´ç¿
- Otsuâs binarization ã§ã®æé©åãããã¤ãåå¨ããï¼èª¿ã¹ã¦å®è¡ãã¦ã¿ããï¼