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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

3912閲覧

エッジの2値画像から4連結した画素のみをプロットしたい

Do_you_1isten

総合スコア29

OpenCV

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/07/02 20:00

前提・実現したいこと 

複数枚の写真からガラスなどの反射による映り込みを除去した背景写真を生成する論文からプログラムを実装しようとしています.

この論文内でエッジ画像から4連結した画像のみをプロットする処理を実装したいです.

順を追って説明します.
上記論文ではまず,入力画像からエッジを取得します.このエッジ画像はエッジ部を白,それ以外を黒とする画像です.以下に実際のエッジ画像の例を図1に示します.

図1 エッジ画像例
_            図1 エッジ画像例

このエッジ画像を使って,各画素を探索します.このとき,探索対象画素の周囲の9画素の内,エッジの画素である画素が4画素以上ならば,その探索画素をプロットする処理を実装したいです.

私自身で実装したコードを該当のソースコードに示します.

些細なことでも良いのでアドバイス頂けますと助かります.

発生している問題

該当のソースコードから得られた出力画像を図2に示します.

該当のソースコードの実行例
_        図2 該当のソースコードから得られた出力画像

該当のソースコードから得られた出力画像の問題点として,そもそも,エッジのない画素にエッジをプロットしているという問題が起こっています.以下に具体的な例の図3,図4,図5,図6に示します.

入力注目画像
_         図3 エッジ画像での赤枠の範囲が図4

入力拡大画像
_         図4 エッジ画像での図3の赤枠の拡大画像

出力注目画像
_         図5 出力画像での赤枠の範囲が図6

出力拡大画像
_         図6 出力画像での図5の赤枠の拡大画像

図4,図6を比較すると,図4のエッジ画像で存在していたエッジが図6では消えていることがわかります.

該当のソースコード

Python

1import cv2 2import numpy as np 3 4def count_neibor(binary_image): 5 image_thinned = binary_image.copy() 6 #画像の縦と横のサイズを取得 7 rows, columns = image_thinned.shape 8 #プロットする画像を宣言 9 dist_image = np.zeros(image_thinned.shape,dtype=np.uint8) 10 11 #各画素を探索 12 for x in range(1, rows - 1): 13 for y in range(1, columns -1): 14 15 #探索画素から近傍画素を設定 16 neighbour_points = neighbours(x, y, image_thinned) 17 #近傍画素にエッジが4以上あるならdist_imageに探索画素をプロット 18 if(255*4 <= sum(neighbour_points)): 19 dist_image[x,y] = 255 20 21 return dist_image 22 23def neighbours(x, y, image): 24 return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 25 image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]] 26 27def main(): 28 29 #エッジ画像をグレースケールで取得 30 image = cv2.imread("canny1.png",0) 31 32 #エッジ画像から4連結した画素のみを生成 33 dist_image = count_neibor(image) 34 35 cv2.imwrite("count_neibourhood.png", dist_image) 36 cv2.imshow('input',image) 37 cv2.imshow('dist_image',dist_image) 38 cv2.waitKey(0) 39 cv2.destroyAllWindows() 40 41if __name__ == "__main__": 42 main()

補足情報(FW/ツールのバージョンなど)

numpy 1.14.0
opencv 3.4.1
python 3.6.4

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

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

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

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

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

guest

回答2

0

ベストアンサー

質問には『探索対象画素の周囲の9画素の内』と説明されていますが、コード中のneighbours関数は周囲の8画素のリストを返しています(基準となる画素(x,y)がリストに入っていません)

def neighbours(x, y, image): return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]]

def neighbours(x, y, image): return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1], image[x],[y]]

と修正すべきだと思われます。

投稿2018/07/03 00:45

coco_bauer

総合スコア6915

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

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

Do_you_1isten

2018/07/03 03:22

ご解答ありがとうございます! 早速修正します!
guest

0

coco_bauerさんの解答を参考にコードを修正致しました.
また,私の記述ミスで,『探索対象画素の周囲の9画素の内』は正しくは『探索対象画素の周囲の8画素の内』でした.

私のソースコードでは,エッジでない画素を注目している場合があったため,それが原因で,エッジの存在しない画素にプロットしていました.
問題が発生する例を以下の図1に示します.

_          イメージ説明
_      図1 間違ってプロットする場合

図1では,中央の画素を探索画素としたとき,白をエッジ画像,灰色をエッジ以外の画像としています.この場合,修正前のソースコードでは,中央がエッジ以外の画像にも関わらず,処理が通るので,エッジのない画素にもプロットしていました.

修正後のソースコードを以下に示します.

Python3.6.4

1import cv2 2import numpy as np 3 4def count_neibor(binary_image): 5 image_thinned = binary_image.copy() 6 #画像の縦と横のサイズを取得 7 rows, columns = image_thinned.shape 8 #プロットする画像を宣言 9 dist_image = np.zeros(image_thinned.shape,dtype=np.uint8) 10 11 #各画素を探索 12 for x in range(1, rows - 1): 13 for y in range(1, columns -1): 14 15 #探索画素からエッジの画素のみを処理 16 if(image_thinned[x,y] == 255): 17 neighbour_points = neighbours(x, y, image_thinned) 18 #近傍画素にエッジが3個のみならdist_imageに探索画素をプロット 19 if(255*3 == sum(neighbour_points)): 20 dist_image[x,y] = 255 21 22 return dist_image 23 24def neighbours(x, y, image): 25 return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 26 image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]] 27 28def main(): 29 30 #エッジ画像をグレースケールで取得 31 image = cv2.imread("canny1.png",0) 32 33 #エッジ画像から4連結した画素のみを生成 34 dist_image = count_neibor(image) 35 36 cv2.imwrite("count_neibourhood.png", dist_image) 37 cv2.imshow('input',image) 38 cv2.imshow('dist_image',dist_image) 39 cv2.waitKey(0) 40 cv2.destroyAllWindows() 41 42if __name__ == "__main__": 43 main()

とすることで,無事に解決致しました.coco_bauerさん,多大なご助力ありがとうございました!

投稿2018/07/03 06:34

編集2018/07/03 06:37
Do_you_1isten

総合スコア29

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問