You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter集成OpenCV播放视频时灰度直方图无法动态更新问题求助

问题排查与修复方案

核心错误原因

  • 变量名冲突:初始化时你先将self.canvas_hist定义为Matplotlib嵌入Tkinter的画布实例(FigureCanvasTkAgg类型),后续调用ax.plot()生成折线时,又将折线对象覆盖赋值给了self.canvas_hist,导致无法调用画布的重绘方法,这也是你之前调用draw()触发参数缺失报错的原因——你实际是在调用折线对象的draw方法,该方法要求传入renderer参数,而画布对象的draw方法不需要。
  • 更新数据后未触发重绘:调用set_ydata仅修改了折线的内存数据,没有触发画布刷新操作,界面上的直方图自然不会更新。

修正后的核心代码

仅需要修改App类中直方图初始化和calc_hist方法即可:

import tkinter
import cv2
import PIL.Image, PIL.ImageTk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import matplotlib.pyplot as plt

class App:
    def __init__(self, window, window_title, video_source=0):
        self.window = window
        self.window.title(window_title)
        self.video_source = video_source
        
        self.vid = MyVideoCapture(self.video_source)
        
        # 视频画布
        self.canvas = tkinter.Canvas(window, width = 640, height = 480)
        self.canvas.grid(row=0, column = 0)

        # 直方图区域
        self.frame_hist = tkinter.Frame(window)
        self.frame_hist.grid(row=0, column = 1)
        self.figure = plt.Figure(figsize=(5,4), dpi = 100)
        self.ax = self.figure.add_subplot()
        # 重命名画布变量,避免和后续折线对象冲突
        self.hist_canvas = FigureCanvasTkAgg(self.figure, self.frame_hist)
        self.hist_canvas.get_tk_widget().pack(fill = tkinter.BOTH, side = tkinter.TOP)
        self.ax = self.figure.gca()
        x = np.linspace(0, 255, 256)
        y = np.linspace(10, 100000, 256)
        # 折线对象单独命名
        self.line_hist, = self.ax.plot(x,y)
        self.ax.set_ylabel('Nombre pixel', fontsize = 15)
        self.ax.set_xlabel('Valeur pixel', fontsize = 15)
        self.ax.set_yscale('log')
        
        self.delay = 15
        self.update()
        
        self.window.mainloop()
     
    def update(self):
        ret, frame = self.vid.get_frame()
        if ret :
            self.gris = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            self.smaller_image = cv2.resize(self.gris,(640,480))
            self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(self.smaller_image))
            self.canvas.create_image(0, 0, image = self.photo, anchor = tkinter.NW)
            
            self.calc_hist(self.gris)
            
            self.window.after(self.delay, self.update)
    
    def calc_hist(self, gris) :
        self.histogram = cv2.calcHist([gris], [0], None, [256], [0, 256])
        self.line_hist.set_ydata(self.histogram)
        # 触发画布重绘,draw_idle适配Tkinter事件循环,不会出现卡顿
        self.hist_canvas.draw_idle()

MyVideoCapture类无需修改,按你原有代码保留即可。修改后直方图会随视频帧同步更新,也不会再出现draw_wrapper参数缺失的报错。

内容的提问来源于stack exchange,提问作者lapasq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:15:05