今回はOpenCVを用いて画像の輪郭を抽出する際の検出手法の違いについて紹介したい。
前回紹介したように輪郭検出方法は次の4種類:cv2.RETR_EXTERNAL,
cv2.RETR_LIST
, cv2.RETR_CCOMP
, cv2.RETR_TREE
があり、前回はcv2.RETR_TREE
を使用した。
今回は他の輪郭検出手法を用いて輪郭抽出したときの結果の違いを調べる。
画像はOpenCVのモノクロロゴをグレーで読み込むところまでは前回と同じ。
ret,thresh = cv2.threshold(gray,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt_img = np.zeros_like(gray, dtype=np.uint8) cnt_img_tree = cv2.drawContours(cnt_img, contours, -1, 255, 2) contours_ex, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cnt_img = np.zeros_like(gray, dtype=np.uint8) cnt_img_ex = cv2.drawContours(cnt_img, contours, -1, 255, 2) contours_list, hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) cnt_img = np.zeros_like(gray, dtype=np.uint8) cnt_img_list = cv2.drawContours(cnt_img, contours, -1, 255, 2) contours_comp, hierarchy = cv2.findContours(thresh,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) cnt_img = np.zeros_like(gray, dtype=np.uint8) cnt_img_comp = cv2.drawContours(cnt_img, contours, -1, 255, 2) plt.figure(figsize=(15,25)) plt.subplot(1,4,1) plt.imshow(cnt_img_tree,cmap='gray') plt.title('RETR_TREE') plt.subplot(1,4,2) plt.imshow(cnt_img_ex,cmap='gray') plt.title('RETR_EXTERNAL') plt.subplot(1,4,3) plt.imshow(cnt_img_list,cmap='gray') plt.title('RETR_LIST') plt.subplot(1,4,4) plt.imshow(cnt_img_comp,cmap='gray') plt.title('RETR_CCOMP')
RETR_EXTERNALは外側の輪郭のみを抽出するためO,P,eの内側が輪郭として抽出されない。RETR_EXTERNAL以外はすべて同じ結果になる。
RETR_EXERNALで抽出した輪郭を輪郭リストの番号で示すと以下のようになる。
n=len(contours_ex) plt.figure(figsize=(12,12)) for i in np.arange(n): cnt_img = np.zeros_like(thresh, dtype=np.uint8) cnt_img = cv2.drawContours(cnt_img, contours_ex,i, 255, 2) plt.subplot(3,4,i+1) plt.imshow(cnt_img,cmap='gray') plt.title('Cont Num'+str(i))
cv2.RETR_LIST
, cv2.RETR_CCOMP
, cv2.RETR_TREE
は輪郭抽出については差がなかったが、内側の輪郭の階層構成について差がある。
抽出した輪郭をさらに処理するときに違いを理解しておくことが必要になる。