我已經成功繪制了視頻的灰度直方圖:對于視頻的每個影像,直方圖已更新為對應于當前影像。對于這個程式,我使用了經典的方式,使用函式 subplots、plot、set_ydata 等。我只有 2 個視窗:一個帶有視頻,一個帶有直方圖,現在我想做的是只有一個帶有視頻和直方圖的視窗,并添加“暫停”、“播放”或“重新啟動”等按鈕。通過研究,我發現 Tkinter 可能是一種方法,所以我開始使用它。
我配置了我所有的視窗(帶有按鈕,顯示視頻和直方圖)并且視頻正常顯示,但我無法更新我的直方圖,我的程式只是繪制第一個直方圖(第一張影像的)而沒有別的。我已經嘗試了幾件事,比如 tkinter 影片,或者在我的函式 calc_hist() 中放置一個 ax clear 和一個 draw() (使用函式 draw() 我有一個錯誤“draw_wrapper() 缺少 1 個必需的位置引數:'renderer'",我沒有找到它對應的內容),但它不起作用。也許我誤用了這些函式,所以也許你可以找到我的代碼出了什么問題。
這是我的類 App,它配置視窗并應該顯示直方圖(我洗掉了我的問題的無用部分,如函式和按鈕宣告以減少代碼):
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)
#Video
self.canvas = tkinter.Canvas(window, width = 640, height = 480)
self.canvas.grid(row=0, column = 0)
#Histogram
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.canvas_hist = FigureCanvasTkAgg(self.figure, self.frame_hist)
self.canvas_hist.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.canvas_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.canvas_hist.set_ydata(self.histogram)
這是我的代碼的第二部分,用視頻類來初始化它,我把代碼放在你身上以防萬一,但我認為看它沒用,我的問題無關緊要:
class MyVideoCapture:
def __init__(self, video_source=0):
# Open the video source
self.vid = cv2.VideoCapture(video_source)
if not self.vid.isOpened():
raise ValueError("Unable to open video source", video_source)
# Get video source width and height
self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
def get_frame(self):
if self.vid.isOpened():
ret, frame = self.vid.read()
if ret:
# Return a boolean success flag and the current frame converted to BGR
return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
else:
return (ret, None)
else:
return (ret, None)
# Release the video source when the object is destroyed
def __del__(self):
if self.vid.isOpened():
self.vid.release()
# Create a window and pass it to the Application object
App(tkinter.Tk(), "Tkinter and OpenCV", "output.avi")
這是我的最終界面:

uj5u.com熱心網友回復:
更新y資料時,需要使用 重繪 圖形self.canvas_hist.draw()。
但是self.canvas_hist( 的實體FigureCanvasTkAgg())被以下行覆寫:
self.canvas_hist, = self.ax.plot(x, y)
所以建議將上面的行更改為:
self.graph, = self.ax.plot(x, y)
然后self.canvas_hist.draw()在末尾添加calc_hist():
def calc_hist(self, gris):
histogram = cv2.calcHist([gris], [0], None, [256], [0, 256])
self.graph.set_ydata(histogram)
self.canvas_hist.draw()
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/355916.html
標籤:Python matplotlib 特金特 直方图
