首页 > 解决方案 > 使用 OpenCV 将 RTSP 视频流式传输到 Tkinter 帧

问题描述

我有一些提供 RTSP 视频源的 IP 摄像机,而且我知道 OpenCV 可以cv2.imshow()通过使用cv2.videoCapture()类似cap.read(). 现在我正在尝试将该视频显示到 TKinter GUI 窗口上。下面是来自 OpenCV 网站的 RTSP 示例代码,它在独立窗口上运行良好:

import cv2
cap = cv2.VideoCapture('rtsp://192.168.0.169:554/mpeg4')
while True:
    ret, img = cap.read()
    if ret == True:  #lines below may not be necessary
        cv2.imshow('video output', img)
        k = cv2.waitKey(10)& 0xff
        if k == 27:
            break
cap.release()
cv2.destroyAllWindows()

如何将视频提要应用于 aTKinter.Frame()或类似的东西?此外,我将在同一个界面窗口上总共使用 3 个摄像头,并添加按钮以将摄像头馈送切换到不同的TKinter.Frame().

先感谢您!

标签: pythonopencvtkinterrtsprtsp-client

解决方案


我设法使用 PIL ImageTk 将 rtsp 流从我的 Ip cam 显示到 Tkinter GUI。尽管我认为由于编码错误,它在我的系统上有点滞后。我建议您在不同的线程上使用 cv2.VideoCapture 运行处理,因为它有时会冻结 GUI。

import tkinter as tk 

import cv2  
from PIL import Image
from PIL import ImageTk
import threading
import os

class MainWindow():
    def __init__(self, window, cap):
        self.window = window
        self.cap = cap
        self.width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
        self.interval = 10 # Interval in ms to get the latest frame
        # Create canvas for image
        self.canvas = tk.Canvas(self.window, width=600, height=400)
        self.canvas.grid(row=0, column=0)
        # Update image on canvas
        root.after(self.interval, self.update_image)
        self.button = tk.Button()

    def update_image(self):    
        # Get the latest frame and convert image format
        self.OGimage = cv2.cvtColor(self.cap.read()[1], cv2.COLOR_BGR2RGB) # to RGB
        self.OGimage = Image.fromarray(self.OGimage) # to PIL format
        self.image = self.OGimage.resize((600, 400), Image.ANTIALIAS)
        self.image = ImageTk.PhotoImage(self.image) # to ImageTk format
        # Update image
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image)
        # Repeat every 'interval' ms
        self.window.after(self.interval, self.update_image)

#def run_decoding(): 
    #os.system("ffmpeg -i rtsp://192.168.1.10?tcp -codec copy -f mpegts udp://127.0.0.1:5000 &")


if __name__ == "__main__":
    #my_cam = ONVIFCamera('192.168.1.10', 80, 'gemer.daniel@gmail.com', 'dg24111998')
    #media = my_cam.create_media_service()
    #ptz = my_cam.create_ptz_service()
    #media_profile = media.GetProfiles()[0]

    # Get PTZ configuration options for getting continuous move range
    #request = ptz.create_type('GetConfigurationOptions')
    #request.ConfigurationToken = media_profile.token
    #ptz_configuration_options = ptz.GetConfigurationOptions(request)

    #request = ptz.create_type('ContinuousMove')
    #request.ProfileToken = media_profile._token

    #ptz.Stop({'ProfileToken': media_profile._token})
    #p1 = threading.Thread(target=run_decoding)
    #p1.start()
    root = tk.Tk()
    MainWindow(root, cv2.VideoCapture("rtsp://192.168.1.10?tcp"))
    root.mainloop()

此外,如果您限制使用 Tkinted,您可以尝试 PyQT5 库,我在处理帧时有更好的结果。


推荐阅读