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

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

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

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

Python 3.x

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

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Q&A

解決済

1回答

11028閲覧

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

noooooooob

総合スコア16

OpenCV

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

Python 3.x

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

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

0グッド

0クリップ

投稿2020/07/01 05:55

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

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

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

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

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

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

python

1import cv2 2 3#認識範囲 4xmin,xmax = 240,440 5ymin,ymax = 120,360 6 7# 動画読み込みの設定 8#movie = cv2.VideoCapture('motion_in.mp4') 9movie = cv2.VideoCapture(0) 10 11# 背景差分の設定 12fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() # 背景オブジェクト 13 14# ファイルからフレームを1枚ずつ取得して動画処理後に保存する 15while True: 16 ret, frame = movie.read() # フレーム取得 17 # フレームが取得できない場合はループを抜ける 18 if not ret: 19 break 20 detframe = frame[ymin:ymax,xmin:xmax] # 背景差分する範囲を指定 21 cv2.rectangle(frame,(xmin,ymin),(xmax,ymax),(0,0,255),2) # 指定範囲に赤枠 22 23 fgmask = fgbg.apply(detframe) # 前景領域のマスクを取得 24 moment = cv2.countNonZero(fgmask) # 動体検知した画素数を取得 25 text = 'Motion:' + str(moment) 26 font = cv2.FONT_HERSHEY_SIMPLEX 27 cv2.putText(frame,text,(20,400),font,1,(0,255,0),2,cv2.LINE_AA) #フレームに表示 28 29 cv2.imshow('frame',frame) 30 cv2.waitKey(1) 31 32# 撮影用オブジェクトとウィンドウの解放 33movie.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

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

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

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

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

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

guest

回答1

0

ベストアンサー

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

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

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

はい

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

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

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

イメージ説明

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

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

サンプル

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

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

python

1import cv2 2import numpy as np 3 4cap = cv2.VideoCapture("vtest.avi") 5width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) 6height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) 7wait_secs = int(1000 / cap.get(cv2.CAP_PROP_FPS)) 8 9model = cv2.bgsegm.createBackgroundSubtractorMOG() 10 11# 検出対象の画素が255、そうでない画素は0の roi を定義する。 12roi = np.zeros((height, width), dtype=np.uint8) 13cx, cy = width // 2, height // 2 14cv2.circle(roi, (cx, cy), 200, 255, -1) 15 16while True: 17 ret, frame = cap.read() 18 if not ret: 19 break 20 21 # roi に基づき、検出対象外の画素を黒にする 22 masked_frame = frame.copy() 23 masked_frame[roi == 0] = 0 24 # 背景差分結果 25 fgmask = model.apply(masked_frame) 26 27 # 検出領域をわかりやすいように可視化 28 cv2.circle(frame, (cx, cy), 200, (0, 0, 255), 2) 29 cv2.circle(masked_frame, (cx, cy), 200, (0, 0, 255), 2) 30 cv2.circle(fgmask, (cx, cy), 200, 255, 2) 31 32 cv2.imshow("fgmask", frame) 33 cv2.imshow("frame", fgmask) 34 cv2.imshow("masked_frame", masked_frame) 35 cv2.waitKey(wait_secs) 36 37cap.release() 38cv2.destroyAllWindows() 39

イメージ説明

投稿2020/07/01 06:39

編集2020/07/01 07:13
tiitoi

総合スコア21956

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

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

noooooooob

2020/07/01 07:59

回答ありがとうございます。 Q2に関しまして、もう少し詳しく状況を説明いたしますと、「カメラの傾きによって生じる画像処理範囲の誤差を減らす」ということがしたいです。 例えばカメラが斜めに傾いてしまう場合、見えてくる画像も当然違って見えます。 また、実際には物体検出をしたいわけではなく、道路の白線の上を移動できる小型の自動走行ロボットを作成したいわけです。両サイドの黒(アスファルト)を検出して黒と黒の間を走行するということを行いたいです。(ここで、白を検出して白の上を走行するという案は諸事情のため省かせていただきます) そういった場合、(申し訳ありません。質問内容と異なる解決方法案になってしまいます) カメラから取得したフレーム自体をカメラが傾いただけ逆方向に傾け、画像処理を行うとすればよさそうだと感じました。今、思い付いた案ですので、フレームの傾け方は改めて学習します。 今考えると、当初の質問でさせていただいた案ですと、仮にできたとしても処理範囲が斜めですので、またおかしなことになってくるのかなと感じました。 サンプルまで作成していただき誠に有難うございます。ぜひ、参考材料の一つとさせていただきます。
tiitoi

2020/07/01 08:09 編集

質問で引用されてる背景差分はそもそもカメラが固定されている状況で、画像の変化した部分を検出するアルゴリズムなので、今回のようにカメラが動くという状況では使えないのではないでしょうか。 > 両サイドの黒(アスファルト)を検出して黒と黒の間を走行するということを行いたいです これが最終目標なのであれば、最初から自動運転で使われるレーン検出のようなことができる手法を探したほうがいいのではないでしょうか。 わりと研究されている分野なので、「白線検出 画像処理」「レーン検出 画像処理」などのキーワード (英語で検索したほうがよい) で検索すれば、論文や Github の実装例が出てくると思います。
noooooooob

2020/07/01 09:32

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問