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

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

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

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

Python

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

Q&A

解決済

2回答

4146閲覧

tkinterでopencvで読み込んだ動画を再生したい

ADATER

総合スコア2

Tkinter

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

Python

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

0グッド

0クリップ

投稿2021/05/23 05:31

実現したいこと

tkinterのcanvas上でopencvで読み込んだmp4ファイルを再生したいです。
しかし、エラーなどは一切ないのに、ウィンドウが表示されるだけで、動画は再生されません。というか、表示すらされません。画像をcanvas上で表示させることは別のプログラムでできたのですが、動画になるとできなくなります。opencv初心者なので、初歩的なところで詰まっているのかもしれませんが、どうか回答よろしくお願いいたします。下のソースコードは、tkinterで動画を再生しようとしたときのソースコードです。拙いものですが、参考にしていただければ幸いです。
フレームレートなどはいったん無視して、動画が再生されることだけを焦点に質問させていただきます。

該当するソースコード

python

1# -*- coding: utf-8 -*- 2 3 4import cv2 5import tkinter as tk 6from PIL import Image,ImageTk 7 8video1_path = "ここは自由に変えてください" 9 10 11cap1 = cv2.VideoCapture(video1_path) 12 13 14width = 600 15height = 400 16 17root = None 18canvas1 = None 19 20def start(): 21 global root,canvas1 22 root = tk.Tk() 23 root.geometry("800x600") 24 root.title("test002") 25 canvas1 = tk.Canvas(root,width = 600,height = 400, 26 bg = "white") 27 canvas1.place(x = 0,y = 0) 28 29 30 31def play1(): 32 global cap1 33 34 ret1, frame1 = cap1.read() 35 if not ret1: 36 37 return 38 39 40 frame1 = cv2.resize(frame1, (600, 400)) 41 42 image01 = cv2.cvtColor(frame1,cv2.COLOR_BGR2RGB) 43 44 image_pil01 = Image.fromarray(image01) 45 46 image_tk= ImageTk.PhotoImage(image_pil01,master=root) 47 48 canvas1.create_image(0,0,image=image_tk) 49 root.after(10,play1) 50 51 52start() 53play1() 54root.mainloop() 55

問題点

play1関数が下まで実行されていることは、printで確認できたが、canvasに動画が表示されない。

###エラー
特になし

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

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

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

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

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

guest

回答2

0

ベストアンサー

問題点: 変数 image_tk (PhotoImage オブジェクト) のスコープ

tkinter の非ウィジェットのオブジェクトは、
デストラクタで破棄されるようになっているので、
ローカル変数の場合は、play1() 関数が終わった時点で破棄されてしまい、
描画に反映されません。

解決策: 簡易的には、変数を global 宣言することで解消できます。

python

1def play1(): 2 global image_tk 3 4 ...

他の解決策は、クラスを作りインスタンス変数(self.image_tkのように)にする。
尚、global cap1 は不要です。global宣言は変数に代入する場合にのみ使います。


他の問題点。表示されない問題ではありませんが、

create_image を delete なしに、呼び続けるのはメモリリークになるので、
create_image は一度のみにして、戻り値を控えておいて、
タイマーで呼ぶ関数内では itemconfig メソッドにより
imageを更新するようにします。

python

1# NOTE: anchor 未指定の場合、image の中心座標が 0, 0 になるので、左上起点に指定 2image_item = canvas.create_image(0, 0, anchor=tk.NW) 3 4# play1 関数内 5 canvas.itemconfig(image_item, image=image_tk)

追記

画像をcanvas上で表示させることは別のプログラムでできたのですが、動画になるとできなくなります。

PhotoImage変数の生存期間の問題なので、「動画」である事が直接の原因ではないはずです。

問題の再現・検証用のコード

python

1import tkinter as tk 2 3root = tk.Tk() 4canvas = tk.Canvas(root, width=600, height=600) 5canvas.pack() 6 7def load_image(): 8 # global image_tk 9 image_tk = tk.PhotoImage(file="a.png") 10 canvas.create_image(0, 0, image=image_tk, anchor=tk.NW) 11 12root.after_idle(load_image) 13root.mainloop()

投稿2021/05/23 20:53

編集2021/05/23 21:17
teamikl

総合スコア8760

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

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

ADATER

2021/05/23 22:58

本当にありがとうございました。 上手くいきそうです!
guest

0

こんばんは。

問題文読ませていただきました。

こちらの記事のベストアンサーを確認すると良さそうです。
https://teratail.com/questions/316474

投稿2021/05/23 09:27

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問