質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2294閲覧

Python-Opencvを用いた画像処理で処理対象範囲を限定したい

panpanda

総合スコア1

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/11/05 08:06

編集2021/11/08 02:26

前提・実現したいこと

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

簡素な方法としては,①のマスクを適当にモルフォロジで加工することが挙げられます.
(「モルフォロジ クロージング」とかで検索すれば処理例の絵を見ることができるでしょう)

投稿2021/11/05 08:25

fana

総合スコア11708

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

panpanda

2021/11/08 02:24

教えていただいた手法で想定していたマスク処理ができそうです。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問