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

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

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

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

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

1回答

16148閲覧

Tkinterのウインドウ内にwebカメラから取得した動画を表示したい

2ckD

総合スコア305

OpenCV

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

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

4クリップ

投稿2019/05/04 14:37

編集2023/04/10 07:50

前提

  • Python
  • Tkinter
  • OpenCV
  • webカメラ

実現したいこと

OpenCVでwebカメラから取得した画像(動画)をウインドウ内に表示したいです。

発生している問題

  1. cv2.imshowならスムーズに画像が切り替わりますが、別ウインドウを開く必要があります。そうすることなく動画を表示したいです。
  2. canvas.itemconfig()で画像を切り替えようとすると、「画像が消える(一瞬canvasの背景色のみが表示される)→画像が表示される」というプロセスを経るためにスムーズに画像を切り替えることができません。

該当のソースコード

Python

1import tkinter as tk 2import threading as th 3import cv2 4from PIL import Image,ImageTk 5import numpy as np 6 7root=tk.Tk() 8root.title("camera") 9root.geometry("720x480") 10canvas=tk.Canvas(root, width=640, height=480) 11canvas.pack() 12 13def camera(): 14 try: 15 c=cv2.VideoCapture(0) 16 h=c.get(cv2.CAP_PROP_FRAME_HEIGHT) 17 w=c.get(cv2.CAP_PROP_FRAME_WIDTH) 18 i=0 19 while(True): 20 ret, frame =c.read() 21 if (not ret): 22 break 23 if cv2.waitKey(1)&0xFF==ord('q'): 24 canvas.delete("all") 25 break 26 cv2.imshow('camera', frame) 27 image=ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))) 28 if not i:#初回起動時の処理 29 i=1 30 canvas.create_image(w/2,h/2,image=image,tag="img") 31 continue 32 canvas.itemconfig("img", image=image) 33 c.release() 34 cv2.destroyAllWindows() 35 except: 36 import sys 37 print(sys.exec_info()[0]) 38 print(sys.exec_info()[1]) 39 40t1=th.Thread(target=camera) 41t1.start() 42root.mainloop() 43

試したこと

labelで画像を表示する場合も同じ結果に終わりました。

label.configure(image=image)

回答をもとにできたもの

python

1import tkinter as tk 2import cv2 3from PIL import Image,ImageTk 4import numpy as np 5 6root=tk.Tk() 7root.title("camera") 8root.geometry("720x480") 9root.resizable(width=False, height=False) 10canvas=tk.Canvas(root, width=640, height=480, bg="white") 11canvas.pack() 12 13def capStart(): 14 print('camera-ON') 15 try: 16 global c, w, h, img 17 c=cv2.VideoCapture(0) 18 w, h= c.get(cv2.CAP_PROP_FRAME_WIDTH), c.get(cv2.CAP_PROP_FRAME_HEIGHT) 19 print('w:'+str(w)+'px+h:'+str(h)+'px') 20 except: 21 import sys 22 print("error-----") 23 print(sys.exec_info()[0]) 24 print(sys.exec_info()[1]) 25 '''終了時の処理はここでは省略します。 26 c.release() 27 cv2.destroyAllWindows()''' 28 29def u():#update 30 global img 31 ret, frame =c.read() 32 if ret: 33 img=ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))) 34 canvas.create_image(w/2,h/2,image=img) 35 else: 36 print("u-Fail") 37 root.after(1,u) 38 39capStart() 40u() 41root.mainloop()

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

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

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

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

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

guest

回答1

0

ベストアンサー

自分では試していなくて申し訳ないのですが、こちらのサンプル では、window.after() を使って指定時間(ms)ごとに canvas.create_image() で frame を更新する例が示されています。これの App.update() 関数を見ると、canvas.create_image() しか使っていませんが、それだけだと画像が切り替わらないのでしょうか?

投稿2019/05/04 19:40

cugel

総合スコア220

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

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

2ckD

2019/05/05 19:25

実はそのサイトはすでに見ていたのですが、 whileの中に「canvas.create_image() 」を入れる方法で失敗したあとだったのでやっても無駄だと読み飛ばしちゃっていました。 回答を頂いてから、コピペして実行したらimshow()した時と同じようにスムーズに再生することができました。 ありがとうございました。 今回、クラスを作成せずに作りたかったので、 参考にしたものとはちょっと違う修正版も今後誰かの役に立つかもしれないので残しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問