サムネがコーヒーの記事は書きかけです。

一定面積以下のオブジェクトを削除する

以下の記事で紹介したように、輪郭を検出することによって、その輪郭の重心や面積等の情報を扱うことができるようになります。

解析対象

せっかくなので、解析対象をサムネイルと同じ画像にして位置から検出を行なっていきたいと思います。

グレースケール

まずは画像をグレースケールにします。

import cv2
import numpy as np 
import matplotlib.pyplot as plt
img_gray = cv2.cvtColor(cv2.imread('1.png'),cv2.COLOR_BGR2GRAY)
cv2.imwrite('img_gray.png',img_gray)

二値化

ヒストグラムは作成していませんが、なんとなく閾値を指定しました。

upper_th = 255
lower_th = 110
ret, img_th = cv2.threshold(img_gray, lower_th,upper_th, cv2.THRESH_BINARY)
cv2.imwrite('img_binary.png',img_th)

綺麗に出ていますね。

輪郭の検出

1チャンネルの画像が得られたので、輪郭を検出していきます。

contours, hierarchy = cv2.findContours((img_th), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
img_result = cv2.drawContours(cv2.imread('1.png'), contours, -1, color=(0, 255, 0),thickness=2)
cv2.imwrite('result.png',img_result)

無事、輪郭が検出されていますね。

輪郭から面積を算出

どれがどの図形というのは面積の値だけ見ても直感的にはわかりませんが、全ての図形の情報が格納されている変数から、面積情報をループで取り出してみます。

for i in range(len(contours)):
    print('Shape_{}'.format(i),'area', cv2.contourArea(contours[i]))

出力結果

Shape_0 area 35904.0
Shape_1 area 50335.0
Shape_2 area 50212.0
Shape_3 area 32159.0
Shape_4 area 12566.5
Shape_5 area 12128.5
Shape_6 area 27510.0

35000くらいが境界線になりそうですね。

面積によるフィルター

輪郭情報が入ったリスト型変数(ndarray)を面積によるフィルターをかけて更新します。

ラムダ式はpython公式には推奨されていませんが、他にやり方がわかりません。

contours = list(filter(lambda x: cv2.contourArea(x) <= 30000 , contours))
img_result = cv2.drawContours(cv2.imread('1.png'), contours, -1, color=(0, 255, 0),thickness=2)
cv2.imwrite('result.png',img_result)

スクリーニングの結果です。

これらが面積30000以下の図形ということになります。

図形の塗りつぶし

消したい図形が面積により特定できたので、次は塗りつぶしによって削除していきます。

そのための条件として、背景色のBGR情報が必要となります。

pythonでのやり方がわからないので、ネットから拾ってきます。

対象の色は黄色っぽいカスタードクリームみたいなやつです。

rgb(255,224,129)

OpenCVでは色情報をBGRで扱うので戻しておきます。

bgr(129,224,255)

ネットで調べると、OpenCVの標準機能で塗りつぶす方法がありましたが、めんどくさいのでフィルターの考え方を使用して、新たなスクリーニングされた輪郭情報を作成することにしました。

new_contours=[]
color =(129,224,255)
area_th = 30000
for c in contours:
    s=abs(cv2.contourArea(c))
    if s <= area_th:
        new_contours.append(c)
img_result = cv2.drawContours(cv2.imread('1.png'), new_contours, -1,color,-1)
cv2.imwrite('result.png',img_result)

無事一定面積以下の図形を削除(塗りつぶし)することに成功しました。

色々と応用できそうですね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です