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

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

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

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

Python

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

Q&A

解決済

1回答

2940閲覧

SaliencyMapの動画を保存したい

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

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

Python

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

0グッド

1クリップ

投稿2017/10/26 03:49

###前提・実現したいこと
こんにちは。
https://github.com/akisato-/pySaliencyMap/blob/master/main_webcam.py
上記のサイトで公開されている、
入力した映像をSaliencyMap化するソースコードに関して質問させていただきます。

以下のエラーが発生し、実行することができません。
おそらく、out.writeは3チャンネルの情報が必要なことから発生するエラーではないかと思います。
どうしたら、正しく動画を実行することができますか?

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

OpenCV Error: Assertion failed (img.cols == width && img.rows == height*3) in cv::mjpeg::MotionJpegWriter::write, file D:\Build\OpenCV\opencv-3.3.0\modules\videoio\src\cap_mjpeg_encoder.cpp, line 842 Traceback (most recent call last): File "testsa.py", line 37, in <module> out.write(saliency_map) cv2.error: D:\Build\OpenCV\opencv-3.3.0\modules\videoio\src\cap_mjpeg_encoder.cpp:842: error: (-215) img.cols == width && img.rows == height*3 in function cv::mjpeg::MotionJpegWriter::write

###該当のソースコード

python

1import cv2 2import matplotlib.pyplot as plt 3import pySaliencyMap 4 5t=0  6fourcc = cv2.VideoWriter_fourcc(*'MJPG') 7out = cv2.VideoWriter('output.avi',fourcc, 20.0, (1280,720)) 8 9# main 10if __name__ == '__main__': 11 # set up webcams 12 capture = cv2.VideoCapture('tennis.mp4') 13 # repeat until pressing a key "q" 14 while(True): 15 # capture 16 retval, frame = capture.read() 17 18 if t==183: ##動画の長さ 19 break 20 21 # initialize 22 frame_size = frame.shape 23 frame_width = frame_size[1] 24 frame_height = frame_size[0] 25 sm = pySaliencyMap.pySaliencyMap(frame_width, frame_height) 26 # computation 27 saliency_map = sm.SMGetSM(frame) 28 29 # visualize 30 31 cv2.imshow('Saliency map', cv2.flip(saliency_map, 1)) 32 33 # 追加を試みた文↓ 34 #saliency_map = cv2.merge((saliency_map, saliency_map, saliency_map)) 35 out.write(saliency_map) 36 t = t+1 37 38 if cv2.waitKey(1) & 0xFF == ord('q'): 39 break 40 41 cv2.destroyAllWindows()

###試したこと
saliency_map = cv2.merge((saliency_map, saliency_map, saliency_map))
の文を追加して3チャンネルとした所、実行はしましたが、
保存された動画は以下のように激しく乱れたものでした。
https://youtu.be/-iwhwFfWjbQ

###補足情報(言語/FW/ツール等のバージョンなど)
Python 3.6.1
OpenCV 3.3.0
を使用しております。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/10/26 12:55 編集

cv2.imshow('Saliency map', cv2.flip(saliency_map, 1))の画像と、print(saliency_map.shape)の結果を教えていただけますか?
退会済みユーザー

退会済みユーザー

2017/10/26 13:57

ご回答ありがとうございます。cv2.imshow('Saliency map', cv2.flip(saliency_map, 1))の画像に関しては、 https://www.dropbox.com/s/okw5ddkveyp7ona/saliency.png?dl=0 のように正しい画像が出力されています。また、print(saliency_map.shape)を行うと、(720, 1280, 3)と出力されました。
退会済みユーザー

退会済みユーザー

2017/10/26 15:01 編集

補足です。  saliency_map = cv2.merge((saliency_map, saliency_map, saliency_map))の文を追加した場合は、 (720, 1280, 3)と表示されましたが、 文がない場合は(720, 1280)と出力されました。  これはRGB情報がすべて失われ、0チャンネルとなっているという事でしょうか。
退会済みユーザー

退会済みユーザー

2017/10/26 16:12

実際にまだ走らせてないのがいけませんが…まず、dropboxの画像を見る限り、正しい画像かは分かりませんがグレースケール画像のように見えます。これが(720, 1280, 3)、つまり720x1280xBGR(3ch)ということですね。だとするとmergeすると9chになってうまくいかない気がします。もしこれが1chでしたら、まがいなりにも3chになってそれなりにアウトプットできそうです。次に、 >文がない場合は(720, 1280)これはグレースケールです。つまり、BGRではなく2^8=256:実際には0~255の256階調のデータが720*1280コ並んでいるイメージです。たぶんですが、merge云々をなしにして、画像を保存するときの設定をグレースケール用にすれば保存できます。あとは、カラーでやるとすれば、saliency_mapをmatplotlib的なもので青~赤のような表示に変更して、元のもとのframeにかぶせて3chで保存でしょうか。時間のある時に触りますね。
退会済みユーザー

退会済みユーザー

2017/10/28 00:01

問題が複数あります。1.Pythonのコード中に全角スペースは入れたらいけません。2.MJPGが最新のOpenCVかPythonでは使えないのでXVIDか何かにしないといけません。3.mapのデータがfloat32なのでuintにしてください。これでもまだバグがあるみたいです。
guest

回答1

0

ベストアンサー

同じ動画ファイルがありませんでしたので、こちらでとりあえず適当な動画で確認できたコードを貼り付けます。

確認できた問題

  • 動画に保存するには、floatではなくinteger

saliency_mapの実態は、float32のnumpy arrayです。浮動小数点は小さい値も大きい値も扱えますが、走らせて確認したところ、saliency_mapの中では0~1の範囲で、しかもグレースケールのように(シングルチャンネルで)動くことが確認できました。ここで、動画を保存するOpenCVの話に戻ります。OpenCVで扱う画像は、0~255の整数で表されます。グレースケールなら[255]、カラー(BGR)なら[255,255,255]という感じです。そこで、float-->integerなら「なんだfloat255をしてroundしたらいいじゃない」と思い、やってみましたがコケました。理由は、Numpyのint8は符号付だからなのですね。なので、**saliency_mapを255をした後にuint8に変換する**必要があります。実際には以下の表のようになります。

中身最小最大
float3232bit浮動小数点数0.000...1.000...
int8符号付き整数-128127
uint8符号なし整数0255
  • MJPGの指定は無効

インターネット上の情報が錯綜していますが、最新のPythonかOpenCVでは、 fourccの指定が*'MJPG'でも'M','J','P','G'でもうまく動きません。代わりに、*'XVID'を使ってください。

  • 画像サイズが巨大だとコケる

私の環境において、生の動画をグレースケールに変換してそのままaviとして保存することはできました。しかし、saliency_mapを通してHD画質のような大きいサイズで保存しようとするとうまくいきませんでした。恐らくsaliency_mapの内部処理で「画像が大きすぎる場合は受け付けない」のようなことがあるのだと思います。saliency_map突っ込む画像を事前に小さくしておいてください。

  • Python中の全角文字

恐らく悪意はなく、編集上の問題で入ったのだと思いますが、Pythonのコード中に全角文字(特に全角スペース )がまぎれているとうまく動きません。teratailに投稿する際には気を付けてくださいね。

*確認できた環境
Python 3.5.3
OpenCV 3.2.0.7

Python

1# -*- coding: utf-8 -*- 2import cv2 3import matplotlib.pyplot as plt 4import pySaliencyMap 5import numpy as np 6 7fps = 20 8width = 480 9height = 320 10 11t=0 12fourcc = cv2.VideoWriter_fourcc(*'XVID') 13out = cv2.VideoWriter("output.avi", fourcc,fps,(width, height),False) 14 15# main 16if __name__ == '__main__': 17 # set up webcams 18 capture = cv2.VideoCapture('tennis.mp4') 19 retval, frame = capture.read() 20 while(retval==True): 21 # capture 22 frame = cv2.resize(frame,(width,height)) 23 24 if t==183: ##動画の長さ 25 break 26 27 # initialize 28 frame_size = frame.shape 29 frame_width = frame_size[1] 30 frame_height = frame_size[0] 31 sm = pySaliencyMap.pySaliencyMap(frame_width, frame_height) 32 33 # computation 34 saliency_map = sm.SMGetSM(frame) 35 36 # visualize 37 saliency_map = saliency_map * 255 38 saliency_map = saliency_map.astype(np.uint8) 39 cv2.imshow('Saliency map',saliency_map ) 40 out.write(saliency_map) 41 42 t = t+1 43 44 if cv2.waitKey(1) & 0xFF == ord('q'): 45 break 46 47 retval, frame = capture.read() 48 49 cv2.destroyAllWindows() 50 out.release() 51 capture.release()

投稿2017/10/28 00:36

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2017/10/28 03:32

ご回答ありがとうございます。 前回の問題から引き続き解決していただき大変感謝しております。 当方でも正しく動作したことを確認できました。 画像サイズに関しては、1280×720の動画を保存したいと考えていたため、問題なくできたので嬉しいです。 floatの説明も表を用いて説明してくださり、型の勉強もはかどりました。 C言語を学んだ際の初心に帰り、一から勉強をしております。 全角文字に関しては、申し訳ございませんでした。 回答してくださる方に対して失礼だと感じましたので、以後注意して投稿を行います。 長文失礼しました。 ご指導いただき、本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問