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

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

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

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

Python

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

Q&A

解決済

2回答

22875閲覧

cvtColorのエラー!_src.empty() in function 'cv::cvtColor'

mk_taro5

総合スコア5

OpenCV

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

Python

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

0グッド

0クリップ

投稿2020/09/29 00:52

前提・実現したいこと

フレーム間差分を行おうとしていたら,while文内でフレームを更新しようとcvtColor関数でフレームをグレイスケールにしようとした際に以下のようなエラーが出ました.
こちらのエラーの解決方法を教えていただきたいです.よろしくお願いいたします.

発生している問題・エラーメッセージ

--------------------------------------------------------------------------- error Traceback (most recent call last) <ipython-input-1-6c4502620fce> in <module> 48 frame1 = frame2 49 frame2 = frame3 ---> 50 frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) 51 52 # 待機(0.03sec) error: OpenCV(3.4.5) C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:181: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'

該当のソースコード

# -*- coding: utf-8 -*- import cv2 import numpy as np import time # フレーム差分の計算 def frame_sub(img1, img2, img3, th): # フレームの絶対差分 diff1 = cv2.absdiff(img1, img2) diff2 = cv2.absdiff(img2, img3) # 2つの差分画像の論理積 diff = cv2.bitwise_and(diff1, diff2) # 二値化処理 diff[diff < th] = 0 diff[diff >= th] = 255 # メディアンフィルタ処理(ゴマ塩ノイズ除去) mask = cv2.medianBlur(diff, 3) return mask # 動画ファイルのキャプチャ cap = cv2.VideoCapture("D:/github/sample/python/opencv/video/test2.avi") width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # フレームを3枚取得してグレースケール変換 frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) while(cap.isOpened()): # フレーム間差分を計算 mask = frame_sub(frame1, frame2, frame3, th=30) # 結果を表示 frame22 = cv2.resize(frame2 , (int(width*0.5), int(height*0.5))) cv2.imshow("Frame2", frame22) cv2.moveWindow('Frame2', 0, 0) mask22 = cv2.resize(mask , (int(width*0.5), int(height*0.5))) cv2.imshow("Mask", mask22) cv2.moveWindow('Mask', 200,0 ) # 3枚のフレームを更新 frame1 = frame2 frame2 = frame3 frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) # 待機(0.03sec) time.sleep(0.03) # qキーが押されたら途中終了 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

試したこと

エラーについて調べましたが,パスに間違いがある・日本語が含まれる問題は,cap.read()で読み込んだフレームをそのままcvtColorに入れているので,問題ないと思っています.

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

whileループ内の

frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)

ここで,cap.read()が失敗した結果でしょう.
(例えば,前回が最後のフレームだった場合とか.)

投稿2020/09/29 01:00

fana

総合スコア11996

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

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

mk_taro5

2020/09/29 01:12

回答ありがとうございます. while(cap.isOpened()): 上記の条件でwhileループを回す場合,最終フレームまで読み込み終わった後は,cap.isOpened()がFalseを返すため,ループが終わりフレームが存在しない場合はループしない,という認識だったのですが間違いでしょうか?
fana

2020/09/29 01:29

私の手元のマニュアルでは,isOpened()は, > Returns true if video capturing has been initialized already. > If the previous call to VideoCapture constructor or VideoCapture::open() succeeded, the method returns true. としか書かれていません. オープンできたことを示すのであって,最終フレームを読んだかどうかを示すものではないように読めます.
mk_taro5

2020/09/29 02:33

cap.read()の失敗を防ぐために,最終フレームまで読み込んだらループ終了とするように,if文を挿入し,また,確認のためにprint()でread()の値を確かめるべく以下のように修正しました. while(cap.isOpened()): print(cap.read()[0]) if cap.read()[0] is False: break 結果は,すべてTrueであり,全く同じエラーが出てしまいました. cap.release() cv2.destroyAllWindows() までたどり着くためにはどうしたら良いのでしょうか? よろしくお願いいたします.
fana

2020/09/29 03:00 編集

実際に何をされたのか全貌がわかりませんが,その print と if を質問コードに「追加」したのであれば,それはよろしくないでしょう. (cap.read()をコールする度に,動画からフレームがgrabされるのでしょうから.) whileループ内の最初らへんで cap.read() の結果を変数に取得しておき, print() や if ではその変数を見るべきでしょう. ※当方,Pythonを知らないので具体的にどう書くのかまでは示せませんが,要は, ・cap.read()で次のフレームのgrabを試みる.  (マニュアルの雰囲気的に,{結果の成否,画像}の2つが返ってくると思うので,その2つを変数に受ける.) ・前記「結果の成否」の値,あるいは「画像」が空かどうか を確認して,ダメならbreakでループから抜ける といった形.(とりあえずループ内がこれだけのコードみたいなのを試してみては?)
fana

2020/09/29 03:03

(python固有の実装の話が必要になる場合には,pythonでopencvな人に回答依頼を投げてみるとか)
guest

0

やはり,whileループ内のcap.read()エラーの原因でした.
以下のように修正した場合に,エラーがなくなりました.このとき修正後も最初にエラーが出ていたのは,余計な場所にprint()を残したままだったのが良くなかったみたいです.

while(cap.isOpened()): print(cap.read()[0]) if cap.read()[0] is False: break

以下修正後コード

# -*- coding: utf-8 -*- import cv2 import numpy as np import time # フレーム差分の計算 def frame_sub(img1, img2, img3, th): # フレームの絶対差分 diff1 = cv2.absdiff(img1, img2) diff2 = cv2.absdiff(img2, img3) # 2つの差分画像の論理積 diff = cv2.bitwise_and(diff1, diff2) # 二値化処理 diff[diff < th] = 0 diff[diff >= th] = 255 # メディアンフィルタ処理(ゴマ塩ノイズ除去) mask = cv2.medianBlur(diff, 3) return mask # 動画ファイルのキャプチャ cap = cv2.VideoCapture("D:/github/sample/python/opencv/video/test2.avi") width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # フレームを3枚取得してグレースケール変換 frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) while(cap.isOpened()): print(cap.read()[0]) if cap.read()[0] is False: break # フレーム間差分を計算 mask = frame_sub(frame1, frame2, frame3, th=30) # 結果を表示 frame22 = cv2.resize(frame2 , (int(width*0.5), int(height*0.5))) cv2.imshow("Frame2", frame22) cv2.moveWindow('Frame2', 0, 0) mask22 = cv2.resize(mask , (int(width*0.5), int(height*0.5))) cv2.imshow("Mask", mask22) cv2.moveWindow('Mask', 200,0 ) # 3枚のフレームを更新 frame1 = frame2 frame2 = frame3 frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) # 待機(0.03sec) time.sleep(0.03) # qキーが押されたら途中終了 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

投稿2020/09/29 07:55

mk_taro5

総合スコア5

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

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

fana

2020/09/29 08:12

> 修正後コード これって,ループ内にて,フレームを3回grabしているのではないでしょうか. ・print(cap.read()[0]) ・if cap.read()[0] is False: ・frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) であれば,動画の長さ(フレーム数)次第で問題を起こすように思いますが,どうなんでしょう.
mk_taro5

2020/09/29 08:57

プログラミング初学のため,回答になるか分かりませんが,,, cap.read()[0]は「結果の成否」の値,trueかfalseを返すので,最終フレームまでループを繰り返すという処理になっています. また,ループ内では連続する3枚の画像frame1,frame2,frame3を次の処理では,frame1にframe2,frame2にframe3を代入し,新しいframe3には次のフレーム(前のループのframe3の次のフレーム)を代入します.なので,ループ内でフレームをgrabしているのはframe3に代入するための1回だと思っています. フレーム数次第で問題を起こすのはなぜでしょう?そのような問題が起きた場合に解決したいので教えていただけたら幸いです.
fana

2020/09/29 09:10

私の疑問は… "cap.read()" が前記の三カ所に記載されていることによって, cap.read()の呼び出しが3回になっているのではないか? ということです. もしそうであれば,「3回目」の cap.read() の実行結果はノーチェックになってしまいます. で,その場合,「2回目」のチェックでbreakできるかどうかはフレーム数次第となるのではないか, …ということです. で,私の回答の方のコメント(2020/09/29 12:00)の話というのは, (pythonでどう書くのが正しいのかはわかりませんが)ループ内でgrabが1回であるコードというのは,例えば,grab処理を XXX = cap.read() みたくして cap.read() の結果を変数に保持し,チェックコードはこのXXXを用いて print( XXX[0] ) if( XXX[0] ) is False: break みたく書き,frame3 = ... のところでも frame3 = cv2.cvtColor(XXX[1], cv2.COLOR_RGB2GRAY) と書くのではないか? と「思う/想像する」,ということです.
fana

2020/09/29 09:15

(フレーム数が既知の動画に対してループが何回目で抜けるかを確認してみる等すれば明確になるのではないかと思います.)
mk_taro5

2020/10/07 03:53

おっしゃる通りですね. 変数を用意し.ループ内で1回だけgrab処理をするように修正しました. ありがとうございます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問