画像を二値化して輪郭抽出、輪郭の個数を表示する
やること
- ファイル名を指定して画像ファイル読み出す
- ファイル名を指定して画像ファイルをグレースケールで読み出す
- グレースケール画像を平均化(ぼかし)処理する
- ぼかした画像を二値化する
- 二値化画像から輪郭抽出し、輪郭の個数を表示。元画像に輪郭を緑で重ね書きし別ウィンドウで表示する
- キー入力で表示用ウィンドウを破棄し終了
使った関数
- cv2.imread : 画像ファイルの読み出し
第2引数にcv2.IMREAD_GRAYSCALE(または0)を指定することでグレースケール変換し読み出す - cv2.blur : 画像の平均化(ぼかし)処理。周囲の画素との輝度平均化処理がされる。
- cv2.threshold : 画像の閾値処理
- cv2.findContours:輪郭抽出処理
- cv2.drawContours:輪郭描画処理
- cv2.imshow : 画像を別ウィンドウに表示する
- len:コンテナ型オブジェクトのサイズを取得する
環境
- windows10 home
- Anaconda 3/ jupyter notebook 5.6.0
- Python 3.7.0
- OpenCV 4.0.0
準備
画像ファイルはフリー写真素材ぱくたそからダウンロードさせていただき、"bricks.jpg"というファイル名で、jupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。
コード
※cv2.findContoursの戻り値はこのブログで使っているOpenCV 4では2つですが、前バージョンOpenCV 3では3つで書式が異なります
import cv2 #OpenCVのインポート fname="bricks.jpg" #開く画像ファイル名 threshold=127 #二値化閾値 img_color= cv2.imread(fname) #画像を読み出しオブジェクトimg_colorに代入 img_gray = cv2.imread(fname,cv2.IMREAD_GRAYSCALE) #画像をグレースケールで読み出しオブジェクトimg_grayに代入 img_blur = cv2.blur(img_gray,(9,9)) #img_grayを平均化領域9x9で平均化処理しimg_blurに代入 ret, img_binary= cv2.threshold(img_blur, threshold, 255, cv2.THRESH_BINARY) #オブジェクトimg_blurを閾値threshold(127)で二値化しimg_binaryに代入 contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #img_binaryを輪郭抽出 cv2.drawContours(img_color, contours, -1, (0,255,0), 2) #抽出した輪郭を緑色でimg_colorに重ね書き print(len(contours)) #抽出した輪郭の個数を表示する cv2.imshow("contours",img_color) #別ウィンドウを開き(ウィンドウ名 "contours")オブジェクトimg_colorを表示 cv2.waitKey(0) #キー入力待ち cv2.destroyAllWindows() #ウインドウを閉じる
cv2.findContoursの戻り値contoursには各輪郭の座標データがNumpyのarray形式で収められています。コンテナ型オブジェクトのサイズを求めるlen関数で求めたcontoursのサイズが輪郭の個数になります
実行結果
抽出された輪郭の個数が表示されます
42
別ウィンドウが開き、緑で輪郭抽出した元画像が表示されます