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

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

ただいまの
回答率

90.34%

  • Python

    9149questions

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

  • OpenCV

    1227questions

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

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,063

uriuri

score 39

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

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

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

のようにすることで大きな矩形や小さな矩形を取り除くことはできますか。
ほかにいい方法があればアドバイスお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • t_obara

    2018/07/23 18:34

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

    キャンセル

回答 4

checkベストアンサー

+1

 ノイズ

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

 白線

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

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

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

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

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

などでしょうか。

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 21: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)
    といった形でいいのでしょうか。
    参考にしたラベリングではランダムな色ですがこの面積のしきい値を用いる場合、先ほどの条件文の下にそれぞれの面積に対してどのような処理を行いそれぞれを分類するのでしょうか。
    さらに各矩形の切り取りなど複数なものに対する処理になれていなく、こんがらがってしまいます。
    知識不足でごめんなさい。

    キャンセル

+1

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 23:38

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

    キャンセル

+1

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 21:01

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

    キャンセル

+1

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 21:52

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

    キャンセル

  • 2018/07/25 09:01

    適応的に決めていた閾値を,画像全体一律の閾値で2値化する処理に変更したということであれば,割と思い切った変更に思えますが(多くの場合,一律閾値だと具合が悪いから適応的処理を試みる方向にを試すという,逆方向に行く思うので),リアルタイム性との兼ね合いなのでしょうか.
    前述の2枚目の画像の誤検出が2値化に由来するものなのであれば,そこらへんの処理がうまくやれていないように思います.
    2値化から出発するのでしたら,一度(処理時間を度外視して)cvAdaptiveThresh()の処理半径をでかく(画像幅の1/4とか1/3とかに)して2値化とかしてみたらどうでしょう.

    「幅」というのは検出したエッジの幅とかではなくて,白線の像の幅ですよ.撮影画像上で白い部分の幅.

    面積も1つの指標でしょうが,形状を表現しない値なので,それだけでは良い結果を得るのは難いと思います.

    キャンセル

  • 2018/07/25 09: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)
    ですと白い部分の幅をしっかりと求めることはできないでしょうか。
    幅の求め方がいまいち思い浮かばずすみません。

    キャンセル

  • 2018/07/26 13:36

    boundingRect()で得られるのは "up-right bounding box" なので,その記述で求められるのはContourのup-rightな(辺が画像のX,Y軸と並行な)外接矩形であり,白線像の幅を求めていることにはなりませんよね.

    ところで,そもそもの話として,
    「検出対象としたい白線というのはこれこれこういうものだけであって,撮影環境がこれこれこういう状況に制約されているから,
     画像上ではこのくらい幅とか長さに写るよね」みたいな前提を持てる話なのであれば,それを記した方が良いのではないでしょうか.
    (逆に,そういう条件を一切設けれないのだとしても,やはりその旨を記した方が良いかと)

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python

    9149questions

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

  • OpenCV

    1227questions

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