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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

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

Q&A

解決済

2回答

4946閲覧

floodFillを用いた二値画像の中空部分穴埋めがうまくいきません

Royce

総合スコア16

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

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

0グッド

0クリップ

投稿2020/01/18 09:09

編集2020/01/19 23:40

###実現したいこと
以下、
実験系研究者のための画像処理技術(その2)~OpenCVで粒子の形状分布を測定する~
を参考に、
・粒子画像の二値化
・穴埋め処理
・境界検出と描画
・粒子の形状測定
を実行したいと考えています。

<追記>
二値化は実行できており、現在穴埋め処理でつまづいています。
穴埋めで実現したいのはつぎのとおりです。

***粒子の中空(黒)部分の穴埋め***
白黒反転した状態の二値画像

粒子の中空(黒)部分の穴埋め
***その後、境界を検出させて描画***

イメージ説明
######実行環境
Windows10
Python3.6.5
openCV4.1.2
###発生している問題
穴埋め処理を行う際に、問題が発生しています。
まず、二値化処理には適応的閾値処理(cv2.adaptiveThreshold)を用いました。
その後、穴埋め処理を実行したいのですが、自身の処理用画像では、参照文献と白黒が逆転している状態のため、穴埋め処理前に白黒の反転作業を行うことにしました。(↓参考URL)
Filling holes in an image using OpenCV ( Python / C++ )
しかし、この反転作業が上手くいかないため、穴埋め処理後の画像では全面にわたって真っ白な状況です。

###該当のソースコード

Python

1import cv2 2import numpy as np 3 4#Step1.画像の読み込み('filename',0(gray scale) or 1(BGR)) 5img = cv2.imread('test_1.tif', 0) 6 #読み込んだ画像は、img_rawの中に[高さ, 幅, (blue, green, red)]のnumpy_arrayとして読み込まれている。 7 8#Step2.二値画像を取得(適応的しきい値処理) 9th = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ 10 cv2.THRESH_BINARY,11,2) 11 12# Copy the thresholded image. 13im_floodfill = th.copy() 14 15# Mask used to flood filling. 16# Notice the size needs to be 2 pixels than the image. 17h, w = th.shape[:2] 18mask = np.zeros((h+2, w+2), np.uint8) 19 20#Step3. Floodfill処理 21cv2.floodFill(im_floodfill, mask, (0,0), 255) 22 23#Step4. 塗りつぶした画像を反転 24im_floodfill_inv = cv2.bitwise_not(im_floodfill) 25 26#Step5. Combine the two images to get the foreground. 27im_out = th | im_floodfill_inv 28 29#画像の表示 30cv2.imshow('Thresholded Image', th) 31cv2.imshow('Floodfilled Image', im_floodfill) 32cv2.imshow('Inverted Floodfilled Image',im_floodfill_inv) 33cv2.imshow('Foreground', im_out)

###出力結果
Thresholded Image
イメージ説明

Floodfilled Image
イメージ説明

Inverted Floodfilled Image
イメージ説明

Foreground
イメージ説明

上図のとおり、途中で確かに白黒反転まではしてくれるのですが、最終的には中心部の黒部分意外にも全体を白く塗りつぶしてしまうようです。

###自分なりの考察
二値化処理と、その後のFloodfill処理で大して変化がないと言う点で、 cv2.floodFill(im_floodfill, mask, (0,0), 255)内のいずれかの引数に問題があるのでは?
と考えています。
しかし、当方画像処理やopenCVの知識に乏しく、原因を解明できない状況です。次の境界検出・描画へ移行できるよう、なんとか解決したいと思っております。

どなた様かお力添え頂きますと、大変助かります。

###【更新】現在までの試行錯誤結果
ソースコード上では、
画像の読み込み → 二値化 → 穴埋め → 白黒反転
の順番でしたが、これを
画像の読み込み → 二値化 → 白黒反転 → 穴埋め
に変更し、
cv2.floodFill(im_floodfill, mask, (100,30), 255)と穴埋め対象部分を座標指定すると、穴埋めできました。
イメージ説明
あとは、周りのノイジーな白色部分を削除or無視し、真ん中の大きい物体のみに常に(こちらで座標指定せずとも)穴埋めしてくれるとうれしいものです。

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

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

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

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

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

guest

回答2

0

最後に輪郭が欲しいだけなら,OpenCVの findContours は輪郭間の内外関係まで見てくれるから,それだけで解決できるのかもしれませんが…
とりあえずここでは中を塗りつぶす方法を考えます.

質問内の一番上の画像について,外側の黒い背景領域のどこかを出発点としてfloodFillを行うことで,この背景領域を検出できるのだとすれば,
最初の画像の黒い画素群のうち,この背景領域検出結果に含まれない画素が「穴」であると判断することができそうです.→そこを白に変えればよいという話になりませんでしょうか.

投稿2020/01/19 01:15

fana

総合スコア11654

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

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

Royce

2020/01/19 23:49

コメントありがとうございます。そして、お返事遅れ申し訳ございません。findContoursで、内部の面積意外に等価直径も算出可能なのでしょうか... 私は、対象物の穴埋めまで行ったあとに、境界検出→面積算出などと進むものと思っておりました(TT)。 現在までの試行錯誤結果を質問欄にアップしましたが、今のところ、対象物の中空黒色部分を座標指定すると、穴埋めすることができました。fana様の"「穴」であると判断する"までの道のりとしては、「外側の黒色領域を検出」→「それ以外の黒領域(つまり穴部分)を検出、穴埋め」という理解でよろしいでしょうか。
fana

2020/01/20 01:51

「等価直径」の詳細は知りませんが…… 面積に関しては,ある図形の輪郭が求まったならばその面積は(内側の画素値とは無関係に)定まるのではないでしょうか.(CVならcontourAreaとかもありますし) (どうしても画像データとして穴を埋めたいなら,その輪郭の内側を問答無用で塗りつぶせばよいように思います) > 「外側の黒色領域を検出」→「それ以外の黒領域(つまり穴部分)を検出、穴埋め」 その通りです.
Royce

2020/01/20 02:12

fana様 お返事ありがとうございます。なるほどです。私の求めている出力結果からすると、おっしゃる通り穴埋めなくfindContourのみで輪郭検出や面積算出などには十分そうですね。やってみます!
guest

0

ベストアンサー

floodfillの基準点が(0,0)なので画像左上の画素に繋がる黒い領域のみが白く塗りつぶされるだけで終わっている。
リンク左記の例は塗り潰す領域とそうでない領域がはっきり分かれているのに対し、質問の画像はそうでないので、単純にパラメータで解決できる問題かどうかは疑問。

ところで最終的にどういう画像がほしいのかいまいち分からないのですが、真ん中のおにぎりみたいなのを残す感じですか?
それによって色々変わると思うのですが理想的な出力の手書き画像とかは無いでしょうか?

投稿2020/01/18 09:36

編集2020/01/18 09:37
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Royce

2020/01/18 10:21

コメントありがとうございます。 基準点に問題があるのですね。私の撮影した画像ですと、二値化でどうしても不均一な領域分布になってしまうようです。。。 最終的にほしい画像につきましては、真ん中のおにぎりの中空部分を埋めて、そのおにぎりの輪郭を抽出したいと思っています。質問欄の実現したいことに<追記>で画像補足いたしました。よろしくお願いします。
退会済みユーザー

退会済みユーザー

2020/01/18 10:43

この画像だけが対象なら、シンプルに海苔の部分を座標指定してfillすれば良いんでしょうけど多分汎用性求められますよね? となると何かしら前提がないとどうにもならないと思うのですがどうでしょう? (ex. 抽出対象は他のノイズより必ず大きい、オニギリには必ず海苔がある、など)
Royce

2020/01/19 23:42

お返事遅れて申し訳ありません。cv2.floodFill()第4引数を(100,30)で海苔の部分を指定しましたら、確かにfillできました。そうですね。汎用性はほしいです。 前提条件の宣言みたいなコードには、例えばどのような書き方があるかご存じでしょうか? 現在までに解決している部分を質問欄にアップしました。 処理したい内容を進めながら、解決したいです。
退会済みユーザー

退会済みユーザー

2020/01/20 09:07

他の質問見ると次のステップに進めたようですが一応コメント。 >周りのノイジーな白色部分を削除or無視し、真ん中の大きい物体のみに常に(こちらで座標指定せずとも)穴埋めしてくれると ブロブ解析をして特徴量を使って扱いべきブロブ(おにぎり)を選ぶと汎用性は上がると思います。 私は画像処理はしているもののOpenCVはあまり使わないので該当する機能の有無は分かりませんが、ラベリングという処理を適用したあと面積や外接矩形のサイズを調べればよい感じの答えが出るかもしれません。 周りのノイズについては穴埋め後にOpening処理をかけると綺麗になると思います。 ただしオニギリが画像の上端下端にくっついてたり、大きなノイズがあったりすると上手く行かない可能性もありますが、そのあたりは対象画像を見て調整・判断しないと分からないです。 【汎用性について】 >前提条件の宣言みたいなコードには、例えばどのような書き方があるかご存じでしょうか? コードというか単純に「どういう画像を対象にしているか」なので別に特殊な書き方とかはないです。 Royceさんは恐らくこの手の画像データを沢山持っていて、それらを見比べて共通して使える処理を適用しようと質問のようなアルゴリズムを考えてらっしゃると思うのですが、我々回答者はその画像データを見ることができないのである程度推測にならざるを得ません。 今回に限らずその点を埋める情報があった方が的確な回答が返ってきやすいと思います。
fana

2020/01/20 10:57

問題なければ,2値化前の元画像も質問時に示した方がよかったですね. 今回示された2値化結果で穴が開いているのは(特定の処理パラメタでの)adaptiveThresholdの結果であって,他の処理なりパラメタなりであれば穴は開かなかったかもしれない→元画像の具合に見合った2値化処理に関するコメントなり回答なりが得られた可能性も考えられますので.
Royce

2020/01/21 00:14

NotionaKettle様 画像解析含め、未だ知らないことがたくさんあるため、 今一度順序立てて整理しようと思います。 最終的に綺麗な状態になるよう、調整していきたいです。 また、質問方法についてご指摘ありがとうございます。 確かに、私の実験データはかなりの数があり、 まずは1枚の画像を処理できた後に、他画像に反映させるつもりでした。 私の頭の中で「こういう処理がしたいな」ということを、 皆様に具体性に欠けた状態で伝えしてしまったと思います。 的確な回答を得るために、現状説明の仕方を改善して参ります。
Royce

2020/01/21 00:15

fana様 研究活動で使用している内容のため、元画像の提示を躊躇しておりました。 そもそも、二値化の時点で結果が変わっていたかもしれないですよね。 プログラミング、画像解析など不慣れな点があり、 質問時にどこを聞いて何を提示すれば良いか、想像・思考力に欠ける感覚があります。 学びながら改善していきたいと思います。至らぬ点がありましたらご指摘頂きたいです。
退会済みユーザー

退会済みユーザー

2020/01/21 03:13

多分元画像提示できないだろうなーってのは大体察してますので大丈夫ですよ。 画像の傾向が分かると話進めやすいなってだけで別に憤りを覚えてるとかではないのでお気にせず。 (勝手な想像ですがこの手の分野の人はこういうやりとりも慣れてるんじゃないかと)
Royce

2020/01/21 03:52

もちろん、貴重なご意見として受け止めております。まだまだ道半ば故、今後とも何卒よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問