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

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

ただいまの
回答率

89.11%

OpenCVを用いた画像処理の範囲指定について教えてください

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 132

noooooooob

score 2

環境

Python 3.7
Raspberry Pi 3 B
OpenCV インストール済
NumPy インストール済

はじめに

先月からパイソンを学習し始めたばかりです。まだまだ初心者で分からないことばかりですので、温かい目でご教授ください。
正直、Python言語もNumPyについても、理解しきれていない状況ですがよろしくお願いします。

やりたいこと

「入力した角度に応じて、画像処理を行う範囲を変える」ということをしたいです。

画像処理に関して調べていたところ、私がやりたいことと類似しているサイト様を見つけましたので、URLを貼らせていただきます。

https://non-it-engineer.com/?p=603

こちらのサイトに記載されていますコードを引用させていただきます。

import cv2

#認識範囲
xmin,xmax = 240,440
ymin,ymax = 120,360

# 動画読み込みの設定
#movie = cv2.VideoCapture('motion_in.mp4')
movie = cv2.VideoCapture(0)

# 背景差分の設定
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()              # 背景オブジェクト

# ファイルからフレームを1枚ずつ取得して動画処理後に保存する
while True:
    ret, frame = movie.read()                                  # フレーム取得
 # フレームが取得できない場合はループを抜ける 
    if not ret: 
        break
    detframe = frame[ymin:ymax,xmin:xmax]                      # 背景差分する範囲を指定
    cv2.rectangle(frame,(xmin,ymin),(xmax,ymax),(0,0,255),2)   # 指定範囲に赤枠

    fgmask = fgbg.apply(detframe)                              # 前景領域のマスクを取得
    moment = cv2.countNonZero(fgmask)                          # 動体検知した画素数を取得
    text = 'Motion:' + str(moment)
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(frame,text,(20,400),font,1,(0,255,0),2,cv2.LINE_AA)  #フレームに表示

    cv2.imshow('frame',frame)
    cv2.waitKey(1)

# 撮影用オブジェクトとウィンドウの解放
movie.release()

質問

Q1:上のコードでまず、疑問に感じていることを教えてください
(1)20行目の“detframe”で画像処理を行う範囲を指定しているのでしょうか?
(2)21行目は、画像処理を行う範囲を見やすいように赤枠で囲んでいるだけでしょうか?

Q2:本題ですが、私は入力角に応じて画像処理範囲を変えたいです。そこで、下の画像(写真)のように、範囲を変えることは可能でしょうか?(ついでに、処理をしている範囲を赤枠で囲みたいのですが、これも可能でしょうか?)
1
各座標の求め方は
入力角=φとすると、
θA1=∠COA1
θB1=∠COB1
任意の点A=(r1cos(90+θA1+φ)+a, r1sin(90+θA1+φ)+b))
任意の点B=(r2sin(90-θB1+φ)+a, r2sin(90-θB1+φ)+b))
で求まると思います。

Q3:Q2が可能だった場合、フレームからはみ出した画像処理範囲はどうなるのでしょうか?きちんと、フレームの中のみ処理を行ってくれるのでしょうか?
それとも、エラーになってしまうのでしょうか?
2

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

Q1:上のコードでまず、疑問に感じていることを教えてください
(1)20行目の“detframe”で画像処理を行う範囲を指定しているのでしょうか?

画像を対象の領域で切り抜いて、その後の処理を行うことで実質的に範囲指定と同じことをやっています。

(2)21行目は、画像処理を行う範囲を見やすいように赤枠で囲んでいるだけでしょうか?

はい

Q2:本題ですが、私は入力角に応じて画像処理範囲を変えたいです。そこで、下の画像(写真)のように、範囲を変えることは可能でしょうか?(ついでに、処理をしている範囲を赤枠で囲みたいのですが、これも可能でしょうか?)
(ついでに、処理をしている範囲を赤枠で囲みたいのですが、これも可能でしょうか?)

背景差分のアルゴリズム自体には範囲を指定する機能はありません。
対象範囲が長方形であれば、画像を切り抜けばいいですが、質問の場合はそうはいかないので、対象範囲以外を黒で塗りつぶしてからその後の処理に移行すればいいと思います。

以下はイメージです。
質問に記載されている式で画像のうち、検出したい範囲のピクセルとそれ以外のピクセルを判定できると思いますので、それで検出対象以外の画素を塗りつぶします。

イメージ説明

Q3:Q2が可能だった場合、フレームからはみ出した画像処理範囲はどうなるのでしょうか?きちんと、フレームの中のみ処理を行ってくれるのでしょうか?

ピクセル単位で検出対象の画素とそうでない画素を定義するので、Q3の問題は発生しません。

サンプル

参考 OpenCV - 背景差分で物体を検出する方法について - pystyle

今回は簡単な例として、検出範囲を円とした場合のサンプルを記載しました。
「検出対象の画素が255、そうでない画素は0のマスクを作成する」部分は質問者さんのほうで適宜変更してください。

import cv2
import numpy as np

cap = cv2.VideoCapture("vtest.avi")
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
wait_secs = int(1000 / cap.get(cv2.CAP_PROP_FPS))

model = cv2.bgsegm.createBackgroundSubtractorMOG()

# 検出対象の画素が255、そうでない画素は0の roi を定義する。
roi = np.zeros((height, width), dtype=np.uint8)
cx, cy = width // 2, height // 2
cv2.circle(roi, (cx, cy), 200, 255, -1)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # roi に基づき、検出対象外の画素を黒にする
    masked_frame = frame.copy()
    masked_frame[roi == 0] = 0
    # 背景差分結果
    fgmask = model.apply(masked_frame)

    # 検出領域をわかりやすいように可視化
    cv2.circle(frame, (cx, cy), 200, (0, 0, 255), 2)
    cv2.circle(masked_frame, (cx, cy), 200, (0, 0, 255), 2)
    cv2.circle(fgmask, (cx, cy), 200, 255, 2)

    cv2.imshow("fgmask", frame)
    cv2.imshow("frame", fgmask)
    cv2.imshow("masked_frame", masked_frame)
    cv2.waitKey(wait_secs)

cap.release()
cv2.destroyAllWindows()

イメージ説明

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/01 16:59

    回答ありがとうございます。

    Q2に関しまして、もう少し詳しく状況を説明いたしますと、「カメラの傾きによって生じる画像処理範囲の誤差を減らす」ということがしたいです。
    例えばカメラが斜めに傾いてしまう場合、見えてくる画像も当然違って見えます。
    また、実際には物体検出をしたいわけではなく、道路の白線の上を移動できる小型の自動走行ロボットを作成したいわけです。両サイドの黒(アスファルト)を検出して黒と黒の間を走行するということを行いたいです。(ここで、白を検出して白の上を走行するという案は諸事情のため省かせていただきます)

    そういった場合、(申し訳ありません。質問内容と異なる解決方法案になってしまいます)
    カメラから取得したフレーム自体をカメラが傾いただけ逆方向に傾け、画像処理を行うとすればよさそうだと感じました。今、思い付いた案ですので、フレームの傾け方は改めて学習します。

    今考えると、当初の質問でさせていただいた案ですと、仮にできたとしても処理範囲が斜めですので、またおかしなことになってくるのかなと感じました。

    サンプルまで作成していただき誠に有難うございます。ぜひ、参考材料の一つとさせていただきます。

    キャンセル

  • 2020/07/01 17:08 編集

    質問で引用されてる背景差分はそもそもカメラが固定されている状況で、画像の変化した部分を検出するアルゴリズムなので、今回のようにカメラが動くという状況では使えないのではないでしょうか。

    > 両サイドの黒(アスファルト)を検出して黒と黒の間を走行するということを行いたいです

    これが最終目標なのであれば、最初から自動運転で使われるレーン検出のようなことができる手法を探したほうがいいのではないでしょうか。
    わりと研究されている分野なので、「白線検出 画像処理」「レーン検出 画像処理」などのキーワード (英語で検索したほうがよい) で検索すれば、論文や Github の実装例が出てくると思います。

    キャンセル

  • 2020/07/01 18:32

    参考にさせていただいたサイトのように、画像処理の範囲指定を行えば、私のやりたいことが行えるのではないかと思い、参考にさせていただきました。しかし、実現できそうにないので私のコメントの案でまた再度少しだけ模索してみようと思います。
    また、tiitoi様のアドバイスの通り、レーン検出の論文などを探し、参考にしていきたいと思います。

    今回は、誠に有難うございました。

    キャンセル

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

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