python : 輪郭の抽出 Opencv
Opencvを使った輪郭(面積、領域)の抽出についてです。
使う画像は、前に色の抽出で使った、下記画像の
赤丸を抽出する方法でやります。
まずはモジュールのimport
import cv2 #opencvのインポート
import numpy as np #色フィルターで使うのでこのインポート
色フィルタで赤丸の抽出
frame=cv2.imread('lena_color.jpg')
#赤のフィルター
redLower = np.array([0, 0, 200]) # 抽出する色の下限(BGR)
redUpper = np.array([100, 100, 255]) # 抽出する色の上限(BGR)
red_mask = cv2.inRange(frame, redLower, redUpper) # BGRからマスクを作成
result_red = cv2.bitwise_and(frame, frame, mask=red_mask) # 元画像とマスクを合成
ここの説明は前に一度説明しているので、このリンクをご参照ください。
輪郭の抽出を行う際は通常1チャンネルの画像(白黒画像)で行うため、
grayの処理をして、その後、二極化を行います。
gray画像を作成
gray_red = cv2.cvtColor(result_red, cv2.COLOR_BGR2GRAY)
二極化画像を作成
ret2,th_red = cv2.threshold(gray_red,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cimg = th_red
輪郭抽出の関数はこれ
contours, hierarchy =cv2.findContours(cimg,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
ついでに何個抽出できたか見ておきます(この場合は2個)
print(len(contours))
#for文でfindContoursの関数で取得したものを一つずつ見ていきます
enumerateというのを使うとインデックスを1つずつ見ていきます。
for i, cnt in enumerate(contours):
# 輪郭の面積を計算する。
area = cv2.contourArea(cnt)
#範囲を決めてやらないと、ドット1つのものでも抽出してしまうので、
if area > 100 and area < 10000:
#drawContoursで下記のように指定(書き込む画像、インデックス、インデックス数、色、太さ)
cv2.drawContours(frame, contours, i, (255,255,255), 2)
print('contour: {}, area: {}'.format(i, area))
cv2.imwrite('lena_contour.jpg',frame)
全プログラムは下記です。
import cv2
import numpy as np
frame=cv2.imread('lena_color.jpg')
#青のフィルター BGRのBlueのフィルター
blueLower = np.array([150, 0, 0]) # 抽出する色の下限(BGR)
blueUpper = np.array([255, 100, 100]) # 抽出する色の上限(BGR)
blue_mask = cv2.inRange(frame, blueLower, blueUpper) # BGRからマスクを作成
result_blue = cv2.bitwise_and(frame, frame, mask=blue_mask) # 元画像とマスクを合成
#緑のフィルター BGRのGreenのフィルター
greenLower = np.array([0, 150, 0]) # 抽出する色の下限(BGR)
greenUpper = np.array([100, 255, 100]) # 抽出する色の上限(BGR)
green_mask = cv2.inRange(frame, greenLower, greenUpper) # BGRからマスクを作成
result_green = cv2.bitwise_and(frame, frame, mask=green_mask) # 元画像とマスクを合成
#赤のフィルター
redLower = np.array([0, 0, 200]) # 抽出する色の下限(BGR)
redUpper = np.array([100, 100, 255]) # 抽出する色の上限(BGR)
red_mask = cv2.inRange(frame, redLower, redUpper) # BGRからマスクを作成
result_red = cv2.bitwise_and(frame, frame, mask=red_mask) # 元画像とマスクを合成
#gray画像を作成
gray_red = cv2.cvtColor(result_red, cv2.COLOR_BGR2GRAY)
#二極化
ret2,th_red = cv2.threshold(gray_red,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cimg = th_red
contours, hierarchy = cv2.findContours(cimg,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
for i, cnt in enumerate(contours):
# 輪郭の面積を計算する。
area = cv2.contourArea(cnt)
# 抽出する範囲を指定
if area > 100 and area < 10000:
#frme画像に書き込む
cv2.drawContours(frame, contours, i, (255,255,255), 2)
#インデックスNoと面積を確認
print('contour: {}, area: {}'.format(i, area))
cv2.imshow('lena_red',result_red)
cv2.imshow('th_red',th_red)
cv2.imshow('frame',frame)
cv2.imwrite('lena_th_red.jpg',th_red)
cv2.imwrite('lena_contour.jpg',frame)
#キー入力を待つ
cv2.waitKey(0)
#全ての開いたウインドウ閉じる
cv2.destroyAllWindows()
今までにpythonについて書いた記事はここにリンク を貼ってあります。
興味があればぜひご覧ください。