0

我正在尝试使用 tkinter 显示视频帧(不是来自流)。下一步是允许用户在视频中向后或向前获取帧的按钮。我不得不说我在使用 python 编程方面还很陌生。所以首先我阅读了以下文章:

Python 片段:将视频转换为图像http://srand.fr/blog/python%20import%20video.html

Tkinter PhotoImage 类:http ://effbot.org/tkinterbook/photoimage.htm

问题是我不能使用用 imageio 或 VideoFileClip 转换的图像来用 tkinter photoimage 显示它。我收到以下错误:

_tkinter.TclError: image "[[  …(some numbers)…   ]]" doesn't exist

这是我的简单代码。我希望你能帮帮我 :)

from moviepy.editor import VideoFileClip
from tkinter import *
import pylab

vid =VideoFileClip("example.mp4")

window = Tk()
window.title("Choose Frame")
window.geometry ("900x600")

count =20

photo = vid.get_frame(count)
label =Label(window, image = photo)
label.pack()

其他代码,同样的问题:

import imageio
from tkinter import *
import pylab

filename = './example.mp4'
vid = imageio.get_reader(filename,  'ffmpeg')

window = Tk()
window.title("Choose Frame")
window.geometry ("900x600")

count =20

photo = vid.get_data(count)
label =Label(window, image = photo)
label.pack()
4

2 回答 2

4

这有点晚了,但迟到总比没有好。

这是我找到并稍作修改的一个工作示例,它适用于“.mp4”,视频但不适用于“.flv”,不知道为什么。

笔记:

python 2.7 导入 Tkinter

python 3 导入 tkinter

import Tkinter as tk
import threading
import imageio
from PIL import Image, ImageTk

video_name = "test_video.mp4" #This is your video file path
video = imageio.get_reader(video_name)

def stream(label):

    frame = 0
    for image in video.iter_data():
        frame += 1                                    #counter to save new frame number
        image_frame = Image.fromarray(image)          
        image_frame.save('FRAMES/frame_%d.png' % frame)      #if you need the frame you can save each frame to hd
        frame_image = ImageTk.PhotoImage(image_frame)
        label.config(image=frame_image)
        label.image = frame_image
        if frame == 40: break                         #after 40 frames stop, or remove this line for the entire video

if __name__ == "__main__":

    root = tk.Tk()
    my_label = tk.Label(root)
    my_label.pack()
    thread = threading.Thread(target=stream, args=(my_label,))
    thread.daemon = 1
    thread.start()
    root.mainloop()
于 2017-03-30T04:13:52.047 回答
0

这是我试图用 Tkinter 制作的播放器的另一个很好的工作示例,以及一些带有 Opencv 模块的示例代码。这只是一个示例想法,绝不是完成代码。

import cv2
from Tkinter import *
from PIL import Image, ImageTk
import io
import threading
import os, sys

def resize(image):
    im = image
    new_siz = siz
    im.thumbnail(new_siz, Image.ANTIALIAS)
    return im

def size(event):
    global siz
    if siz == screenWH:
        siz = (200, 200)
    else:
        siz = screenWH
        win.state('zoomed')
    print 'size is: ', siz

def view_frame_video():
    vc = cv2.VideoCapture('test_video.flv')
    if vc.isOpened():
        rval , frame = vc.read()
    else:
        rval = False

    while rval:
        rval, frame = vc.read()
        img =Image.fromarray(frame)
        img = resize(img)
        imgtk = ImageTk.PhotoImage(img)
        lbl.config(image=imgtk)
        lbl.img = imgtk
        if stop == True: 
            vc.release()
            break      #stop the loop thus stops updating the label and reading imagge frames
        cv2.waitKey(1)
    vc.release()

def stop_():
    global stop
    stop = True

def play():
    stop = False
    t = threading.Thread(target=view_frame_video)
    t.start()



win = Tk()

stop = None
screenWH = (win.winfo_screenwidth(), win.winfo_screenheight())
siz = (200, 200)

Label(text='Press Play Button').pack()
frm_ = Frame(bg='black')
frm_.pack()
lbl = Label(frm_, bg='black')
lbl.pack(expand=True)
lbl.bind('<Double-Button-1>', size)

frm = Frame()
frm.pack()
Button(text='Play', command = play).pack(side=LEFT)
Button(text='Stop', command = stop_).pack(side=LEFT)

win.mainloop()
于 2017-03-30T04:43:01.997 回答