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

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

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

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

Python

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

Q&A

解決済

4回答

13872閲覧

opencvで一定の範囲のサイズのみを矩形で抽出

uriuri

総合スコア47

OpenCV

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

Python

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

0グッド

1クリップ

投稿2018/07/23 07:59

編集2018/08/06 05:43

カメラを用いて白線のリアルタイムの検出を行いました。
しかし影から日差しが写る際に二値化しているため影と日差しの境界を誤検出したり余計な部分しまいます。
イメージ説明
イメージ説明

輪郭抽出と矩形検出の部分です。

img, contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1) for i in range(0, len(contours)): area = cv2.contourArea(contours[i]) if area < 50 or 0 < area: continue if len(contours[i]) > 0: rect = contours[i] x, y, w, h = cv2.boundingRect(rect) cv2.rectangle(c_frame, (x, y), (x + w, y + h), (0, 255, 0), 3) ``` プログラム初心者であってこのようなノイズのとり方をまだ理解できていません。 cv2.boundingRectで座標を取得し、その後x,y,x+w,y+hについて辺のサイズを絞ってあげればよいのでしょうか。 参考サイト  http://mtail3x.wpblog.jp/2015/11/06/opencvsharp%E3%81%A7%E5%8F%B0%E5%BD%A2%E8%A3%9C%E6%AD%A3/ この場合、 x, y, w, h = cv2.boundingRect(rect) のあとに if 100 < w and w < 500 continue if 30 < h and h < 200 continue のようにすることで大きな矩形や小さな矩形を取り除くことはできますか。 ほかにいい方法があればアドバイスお願いします。

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

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

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

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

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

t_obara

2018/07/23 09:34

ご提示されている方法が適切なのか否かは要求される条件に依存する部分ですので判断しかねますが、オブジェクト認識で光を扱うのは難しいです。予めその範囲に対象が存在しないという条件があるのであれば、排除してから認識させるのが一番良いです。
guest

回答4

0

別の質問
opencvで直線近似
にて,「白線」の特徴を用いる案にちらっと触れましたが,ダメでしょうか.
(白線と同じような形状の日向(やその他の物体等)が存在すれば除去しきれませんが.)
面積に閾値判定をかけれるということは,撮影状況に関してある程度の前提が設けられている(でなければ対象の像サイズに前提を設けることは不可能)と思われるので,白線像の太さに閾値を設けることも可能に思うのですが,実際どうなのでしょう?

「2値化」は情報の損失が大きく,また,偽の輪郭を生じる(2枚目の画像の,日向の何もない個所にたくさん矩形が出ているのはこのためかな?)ので,可能ならば処理アルゴリズムの前側に置くことは避ける方がよいと思います.

投稿2018/07/24 02:44

fana

総合スコア11654

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

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

uriuri

2018/07/24 12:52

以前の処理では線分がたくさんあったのですが、適応的しきい値処理から二値化に変え、エッジ抽出して輪郭点から直線検出すると白線の周りを一本の線分で囲う形になってしまったため、太さに対しては一定のサイズでの処理となっています。 光の処理に対して二値化は向いてないのでしょうか。 輝度勾配などのほうがよいのでしょうか。
fana

2018/07/25 00:01

適応的に決めていた閾値を,画像全体一律の閾値で2値化する処理に変更したということであれば,割と思い切った変更に思えますが(多くの場合,一律閾値だと具合が悪いから適応的処理を試みる方向にを試すという,逆方向に行く思うので),リアルタイム性との兼ね合いなのでしょうか. 前述の2枚目の画像の誤検出が2値化に由来するものなのであれば,そこらへんの処理がうまくやれていないように思います. 2値化から出発するのでしたら,一度(処理時間を度外視して)cvAdaptiveThresh()の処理半径をでかく(画像幅の1/4とか1/3とかに)して2値化とかしてみたらどうでしょう. 「幅」というのは検出したエッジの幅とかではなくて,白線の像の幅ですよ.撮影画像上で白い部分の幅. 面積も1つの指標でしょうが,形状を表現しない値なので,それだけでは良い結果を得るのは難いと思います.
uriuri

2018/07/25 00:50

適応的二値化で線分が複数あり輪郭抽出と矩形検出がうまく行えず二値化にしてしまいました。 二値化にしたらうまくいったので行ってしまったという形です。 幅というのは if len(contours[i]) > 0: rect = contours[i] x, y, w, h = cv2.boundingRect(rect)    if h>=30: cv2.rectangle(c_frame, (x, y), (x + w, y + h), (0, 255, 0), 2) ですと白い部分の幅をしっかりと求めることはできないでしょうか。 幅の求め方がいまいち思い浮かばずすみません。
fana

2018/07/26 04:36

boundingRect()で得られるのは "up-right bounding box" なので,その記述で求められるのはContourのup-rightな(辺が画像のX,Y軸と並行な)外接矩形であり,白線像の幅を求めていることにはなりませんよね. ところで,そもそもの話として, 「検出対象としたい白線というのはこれこれこういうものだけであって,撮影環境がこれこれこういう状況に制約されているから,  画像上ではこのくらい幅とか長さに写るよね」みたいな前提を持てる話なのであれば,それを記した方が良いのではないでしょうか. (逆に,そういう条件を一切設けれないのだとしても,やはりその旨を記した方が良いかと)
guest

0

ベストアンサー

ノイズ

ノイズの除去は、平滑化(ガウシアンフィルタ)やメディアンフィルタで検索すると出てきますよ。画像を見てそれっぽいのを試してください。

白線

t_obaraさんの言う通り、光は難しいです。

その画像のように、白線とアスファルト(影)とアスファルト(日向)だけの条件の場合、以下の方法がうまく行くかもしれません。

  • 2値化してラベリングしたのち、写真の枠に重なるものは除く。

ラベリングの参考

  • 2値化してラベリングしたのち、面積(ピクセル数)で閾値を設け除く。(画像の10%以上の面積は日向とするとか)

  • そのプログラムで得た矩形で少し大きめに切り取って、2値化した時に一色か(日向or日陰)、上下に分かれるか(影の境目)、内部にオブジェクトがあるか(白線)の3択から検出する

などでしょうか。

ただ、白線とアスファルト(日向)が重なった場合難しいです。

投稿2018/07/23 12:52

編集2018/07/23 14:31
suzu6

総合スコア168

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

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

uriuri

2018/07/24 12:34

面積でしきい値をわけるというのは height, width, channels = c_frame.shape image_size = height * width if 0.1*image_size <= area: print(hinata) elif area <= 0.09*image_size: print(hakusen) といった形でいいのでしょうか。 参考にしたラベリングではランダムな色ですがこの面積のしきい値を用いる場合、先ほどの条件文の下にそれぞれの面積に対してどのような処理を行いそれぞれを分類するのでしょうか。 さらに各矩形の切り取りなど複数なものに対する処理になれていなく、こんがらがってしまいます。 知識不足でごめんなさい。
guest

0

検出した白線の領域に対してヒストグラムを算出して、閾値を超えた領域のみを求めれば白線のみを出力できると思います。

投稿2018/07/23 12:20

crimnut

総合スコア380

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

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

uriuri

2018/07/24 12:01

ヒストグラムを用いるとあるのですが、以前ヒストグラムを用いた時画像全体を処理した形になってしまったのですがある一定の領域だけを処理するにはこの場合どうすればよいのでしょうか。 知識不足ですみません。
guest

0

まずは明確な差を認識しましょう。
画像処理は数理的な処理ですが、基本は’目に見えている事’。
意外と人間の目も’閾値’的にはいい加減。しかし画像処理では律義に分離。

質問にある映像から、背景の色の違いが人間の目からもはっきりと。
ノイズの処理って言い換えれば’要らないものを取り除く’と解釈しましょう。

実際に私も現場では’要らないもの除去’と個別案件の対応。

’何が違って、何が要らないか?’です。

投稿2018/07/23 12:16

MasahikoHirata

総合スコア3747

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

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

uriuri

2018/07/24 14:38

質問の回答ありがとうございます。 これからどのようなことをしていいかの認識について気をつけて考えていきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問