実現したいこと
- cv2で画像を表示したい.
cv2.setMouseCallback
を用いて直接画像に描画したい
前提
- cv2.imshowを使って画像を表示させようとしたところウィンドウが開きません.
- エラーが出るわけではなくずっと実行されているようで
^c
でも実行を止めることができず,毎回ターミナルを消して止めなければならない状況となっています.
こちらの方のコードを参考にしました
環境:
MacBook Pro(13インチ、M2、2022)
conda環境
発生している問題・
該当のソースコード
python
1import cv2 2import numpy as np 3 4 5def draw_circle(event,x,y,flags,param): 6 if event == cv2.EVENT_LBUTTONDOWN: 7 cv2.circle(img,(x,y),100,(0,255,0),-1) 8 9print('test_1') 10img = np.zeros((600,600,3), np.uint8) 11print('test_2') 12 13cv2.imshow('test', img) 14cv2.waitKey(0) 15cv2.destroyAllWindows() 16print('test_3') 17cv2.namedWindow('mouse_drawing', cv2.WINDOW_NORMAL) 18print('test_4') 19 20cv2.setMouseCallback('mouse_drawing',draw_circle) 21print('test_5') 22while True: 23 cv2.imshow('mouse_drawing',img) 24 if cv2.waitKey(20) & 0xFF == 27: 25 break 26cv2.destroyAllWindows()
result
1>>> 2test1 3test2
試したこと
他の方の質問を参考にして
cv2.waitKey(0) cv2.destroyAllWindows()
を挿入しましたが変わりませんでした.
補足
cv2.imwrite()
などの他のメソッドは正しく動きますが cv2.imshow()
といったウィンドウ表示のメソッドがうまく動きません.
よろしくお願いします.
お使いのopencvのバージョンはいくつでしょうか?
以前起きた時は、4.5.1.48で直ったらしいです
https://github.com/opencv/opencv-python/issues/376
version 4.6.0でした
> MacBook Pro(13インチ、M2、2022)
conda環境
> version 4.6.0
m1 mac+anaconda+opencv 4.6.0で、不具合が報告されてます
https://github.com/opencv/opencv/issues/22561
上記報告の現象は質問のとは違いますが、もしかすると関連してるかもしれないので、試しに4.7.0を使ってみたらいかがでしょうか
次のWhileのループに入る前に「cv2.waitKey(20)」を入れて試してください。
少なくともUbuntuだと「cv2.waitKey(20)」をするまでWindowの枠だけ表示されて中身が更新されない(=運が悪いとフリーズ)が起きます。
> if cv2.waitKey(20) & 0xFF == 27:
これだとどうなんでしょうね、waitKeyされるんでしょうか。
私なら
key = cv2.waitKey(20)
if key == 27:
# 以下略
のようにします。
fourteenlengthさん
> 次のWhileのループに入る前に
質問者さんが実行すると「test2」までしか表示されないので、「print('test_2')」と「print('test_3')」の間のところから先に進んでないので、whileループまで到達してないはずです
「print('test_2')」と「print('test_3')」の間は
cv2.imshow('test', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
ですから、上記を実行したら、質問者さんの環境では
・ウィンドウが開きません
・^cでも実行を止めることができず,毎回ターミナルを消して止めなければならない状況
になるのです
fourteenlengthさん
> Ubuntuだと「cv2.waitKey(20)」をするまでWindowの枠だけ表示されて中身が更新されない(=運が悪いとフリーズ)
当方のmac(インテルcpu)のpythonのopencv(pipで入れた4.6.0.66)で、質問のコードをそのまま実行したら、下記のようになり、正常に実行できてるようです
test_1
test_2
と表示され、真っ黒なウインドウ(test)が開く
↓
ウインドウ(test)を選択(クリック)してからキーボードで何かを入力したら、ウインドウ(test)が消えて、
test_3
test_4
test_5
と表示され、真っ黒なウインドウ(mouse_drawing)が開く
↓
ウインドウ(mouse_drawing)の真っ黒な部分のどこかをクリックすると、クリックした場所に緑色の円が表示される
↓
ウインドウ(mouse_drawing)を選択(クリック)してから「esc」キーを入力したら、ウインドウ(mouse_drawing)が消える
osによって違いがあるのですかね
jbpb0さん:
ご指摘ありがとうございます。
> 「print('test_2')」と「print('test_3')」の間のところから先に進んでないので、whileループまで到達してないはず
これが質問のエッセンスですね。
nakaさん:
手元にMACがないので現象の詳細が不明ですが、「cv2.destroyAllWindows()」をプログラムの最後以外で使った記憶がめったにありません。
もしかしたらOSによっては、
cv2.destroyAllWindows()をした後にcv2.imshowをするとおかしなことになるのかも?
bpb0さん, fourteenlengthさん
ご意見をいただきありがとうございます.
当方の環境で condaではなくpipでopencv(4.5.1.48)を動かしたところ正常に動かすことができました.
ありがとうございます.
またこれは追加での話なのですが,jupyterとcv2は相性が悪いのでしょうか.
pythonスクリプトとして実行できたを確認した後にjupter notebook形式で実行すると
ウィンドウは開く
クリックしてもイベントが起こらない, カーネルと終了しないとウィンドウが閉じない
と言う現象が起こります.
別件として質問するべきことな気もするのですが,何か意見がありましたらコメントいただけると幸いです.
> またこれは追加での話なのですが,jupyterとcv2は相性が悪いのでしょうか.
Jupyter notebookはサーバー側で動かしてGUIをWEBページとして提供するモジュールです。ですのでOpenCV自体は対応していてもcv2.imshow()みたいなGUIの関数とは相性が悪い(動かない?)と思います。そのためか何なのか、Jupyter notebookが要求するOpenCVはHeadless(GUI機能をバッサリ切ったOpenCV、GUIがいらない=サーバー向け)だったと思います。HeadlessではないOpenCVでも動くのかもしれませんが、先に掲載頂いたようなエラーの温床なのかも?と感じました。
――根拠はありません:)
そもそもjupyter notebook自体がguiを用いないopencv-headlessが適していること自体初めて知りました.
plt.imshow()が用いられていることも納得できました.
ありがとうございます.
> jupter notebook形式で実行すると
ウィンドウは開く
クリックしてもイベントが起こらない, カーネルと終了しないとウィンドウが閉じない
当方のmac(インテルcpu)のpython(anaconda)のopencv(pipで入れた4.6.0.66)で、質問のコードをそのまま実行したら、下記のようになり、最後の「esc」キーのところ以外は正常に実行できてるようです
test_1
test_2
と表示され、真っ黒なウインドウ(test)が開く
↓
ウインドウ(test)を選択(クリック)してからキーボードで何かを入力したら、ウインドウ(test)が消えて、
test_3
test_4
test_5
と表示され、真っ黒なウインドウ(mouse_drawing)が開く
↓
ウインドウ(mouse_drawing)の真っ黒な部分のどこかをクリックすると、クリックした場所に緑色の円が表示される
↓
ウインドウ(mouse_drawing)を選択(クリック)してから「esc」キーを入力しても、ウインドウ(mouse_drawing)は消えず、虹色がくるくる回る
jupyterのカーネルを止めたら、ウインドウ(mouse_drawing)が消える
なお、opencvのウインドウで虹色がくるくる回ってる状態でも、jupyter自体はハングアップしてるわけではなく、使えます
ウインドウを選択(クリック)してから「esc」キーを入力した直後は、jupyterを表示してるwebブラウザでも虹色がくるくる回りますが、しばらくすると虹色は消えて、jupyterが使えるようになります
その状態で、質問のコードを再度実行すると、面白いことにウインドウ(mouse_drawing)が消えて、ウインドウ(test)が現れて、その後も継続できます
つまり、opencvのウインドウで虹色がくるくる回ってる状態が、次の「cv2.imshow('test', img)」の実行で「正気に戻る」ようなのです
(「正気に戻る」としても、opencvのウインドウで虹色がくるくる回ること自体がなくならないと、使う気にはなりませんが)
【追記】
https://qiita.com/kemako/items/fd72c65ca964a1b74fef
を参考にコードを修正したら、当方のmacではターミナルでの実行と同様に、最後の「esc」キーのところも含めてjupyterでも正常に実行できてるようです
インデントが消えないように、コードは回答に書きました
【追記2】
過去の質問にもありました
https://teratail.com/questions/107002
回答2件