如何在Tkinter框架中同时显示源视频及多个视频副本
在同一Tkinter窗口显示源视频+多个副本的实现方案
你现在的代码已经能单帧播放视频了,要加多个副本很简单,核心就是把读出来的同一帧,在画布的不同位置重复绘制即可,下面给你两种可行的修改方案:
方案1:直接在画布不同位置重复绘制单帧
这种方式改动少,快速实现多副本显示,适合基础布局需求:
from tkinter import * from PIL import Image, ImageTk import cv2 root = Tk() root.title("多视频窗口") # 换成本地MP4就把0改成"vid1.mp4" vid = cv2.VideoCapture(0) width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 设置显示的行列数,比如2行2列,共4个视频窗口(含源视频) rows = 2 cols = 2 # 画布尺寸要适配所有窗口 canvas_width = width * cols canvas_height = height * rows def get_frame(): ret, frame = vid.read() if ret: return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) else: return (ret, None) def update(): ret, frame = get_frame() if ret: img = Image.fromarray(frame) photo = ImageTk.PhotoImage(image=img) # 清空画布旧内容,避免画面重叠 canvas.delete("all") # 循环在不同坐标绘制相同帧 for i in range(rows): for j in range(cols): x_pos = j * width y_pos = i * height canvas.create_image(x_pos, y_pos, image=photo, anchor=NW) # 必须保留图片引用,防止被垃圾回收导致画面消失 canvas.image = photo # 定时更新画面,维持视频流畅度 root.after(delay, update) canvas = Canvas(root, width=canvas_width, height=canvas_height) canvas.pack() delay = 15 update() root.mainloop() vid.release()
方案2:将多帧拼接成大图后显示
这种方式先把多个相同帧拼成一张完整大图,再整体绘制到画布,适合需要自定义布局(比如不同大小副本)的场景:
from tkinter import * from PIL import Image, ImageTk import cv2 import numpy as np root = Tk() root.title("拼接式多视频窗口") vid = cv2.VideoCapture(0) width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)) rows = 2 cols = 2 combined_width = width * cols combined_height = height * rows def get_frame(): ret, frame = vid.read() if ret: return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) else: return (ret, None) def update(): ret, frame = get_frame() if ret: # 创建空的大图容器 combined_img = np.zeros((combined_height, combined_width, 3), dtype=np.uint8) # 将源帧填充到大图的各个区域 for i in range(rows): for j in range(cols): y_start = i * height x_start = j * width combined_img[y_start:y_start+height, x_start:x_start+width] = frame # 转换为Tkinter支持的图像格式 img = Image.fromarray(combined_img) photo = ImageTk.PhotoImage(image=img) canvas.create_image(0, 0, image=photo, anchor=NW) canvas.image = photo root.after(delay, update) canvas = Canvas(root, width=combined_width, height=combined_height) canvas.pack() delay = 15 update() root.mainloop() vid.release()
关键注意点
- 修改
rows和cols数值可以调整显示的副本数量,比如3行3列就是9个窗口 - 若使用本地MP4文件,替换
cv2.VideoCapture(0)中的0为视频文件路径即可 - 必须保留
canvas.image = photo这行代码,否则Tkinter的垃圾回收机制会销毁图片对象,导致画面消失
内容的提问来源于stack exchange,提问作者Enthusiast
相关产品推荐
相关产品推荐

