前提・実現したいこと
Python, Opencvを用いて、最も明るい範囲のみを対象として、割れ(=対象領域内の暗い部分)の検出を行いたいです。
発生している問題・エラーメッセージ
最も明るい範囲のみを検出対象としたいため、それ以外の領域を除外するために2つの方法を考えました。
①対象外の領域を塗りつぶす(マスク処理?)
②座標を用いて処理時に範囲指定して除外する
(除外する領域の輪郭を取り、内側or外側を指定して除外領域を処理対象外にするイメージです)
しかし、
①は
・検出対象範囲に含まれる「割れ」まで塗り潰してしまう
・面積で「割れ」は除外しようとしたが、下画像の様に輪郭同士がつながってしまうせいで上手く行かない。
②は
・関心領域の指定は(x0, x1)(y0, y1)のようなものしか使えないため、どのようにすれば「多数の座標に囲まれている範囲の内側or外側」に対して処理を行うような指定ができるのかわからない。
該当のソースコード
Python
1class CrackDetector: 2 def __init__(self, image_path, image_array=False): 3 # パスが渡されればパス、画像が渡されれば画像 4 self.original_image = cv2.imread(image_path) if image_path else image_array 5 self.vertical, self.horizon , self.ch = self.original_image.shape # shape = (824, 1294, 3) 6 7 @staticmethod 8 def image_show(image): 9 cv2.namedWindow("window", cv2.WINDOW_NORMAL) 10 cv2.imshow('window', image) 11 cv2.waitKey(0) 12 cv2.destroyAllWindows() 13 14 def binarizing_threshold(self, thresh_value=110, method=cv2.THRESH_BINARY_INV): 15 """ 16 Thresholdによる2値化 17 """ 18 copy_image = self.original_image.copy() 19 image_gray = cv2.cvtColor(copy_image, cv2.COLOR_BGR2GRAY) 20 ret, threshold_binary_image = cv2.threshold(image_gray, thresh_value, 255, method) 21 return threshold_binary_image 22 23 def detect_contours(self, binary_image) 24 contours, hierarchy = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 25 return contours 26 27 def draw_square_center_line(self, contours): 28 """ 29 四角形(輪郭)の中心を通る線を引く 30 """ 31 calculator = Calculator() # 別で定義したクラス 32 copy_image = self.original_image.copy() 33 for contour in contours: 34 rect = cv2.minAreaRect(contour) # contour1つを引数に取り、中心座標/縦幅横幅/回転角度を返す 35 rect_points = cv2.boxPoints(rect) # minAreaRectの返り値rectから回転した四角形4点の座標を得る 36 37 start_p, finish_p = calculator.get_square_center_line(rect_points) # 四角形4点の座標から始点、終点を求める関数 38 line_draw_image = cv2.line(copy_image, start_p, finish_p, (0, 0, 255), 1, lineType=cv2.LINE_AA) 39 self.image_show(line_draw_image) 40 41# # # - - - - - - - 42"割れ部分の描画" 43# # # - - - - - - - 44image = CrackDetector(IMAGE_PATH) 45# 2値化 46binary_image = image.binarizing_threshold(thresh_value) 47# 輪郭検出 48contours = image.detect_contours(binary_image) 49# 検出した割れの描画 50image.draw_square_center_line(contours)
試したこと
・面積を用いて割れを除外する
・除外する領域を座標によって指定(しようとした)
・しきい値の調整
など試しましたが、どれも期待通りの動きはしませんでした。
・△型であることは確定しているので、形状を検知すればうまくいくかと思い調べてみました。しかし、どのようにすればいいかわかりませんでした。
・①の割れ部分が大きい輪郭とつながってしまう問題は、細い部分(つながってしまっている部分)をどうにか分離すれば解決できるのではと考えましたが、こちらもどのようにすればいいかわかりませんでした。
私が上げた方法以外でも領域を指定する方法があれば教えていただきたいです。
また、割れの検出等におかしな点があればご指摘お願いします。
補足情報(FW/ツールのバージョンなど)
環境
Windows10
Python 3.8
Opencv-python 4.5.3.56
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/08 02:24