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

如何在Tkinter GUI中直接显示树莓派4间的Pi Camera视频流

解决方案:在Tkinter窗口内整合树莓派摄像头流

下面提供两种可行的方案,替代原有的raspivid+netcat+mplayer组合,直接在Tkinter界面内渲染摄像头画面:

方案1:OpenCV + TCP 流媒体 + Tkinter

机器人端(发送端)代码

用OpenCV读取Pi Camera的帧,编码为JPEG后通过TCP套接字发送到控制端:

import cv2
import socket
import struct

# 配置参数
HOST = "控制端树莓派的IP"  # 示例:"192.168.1.100"
PORT = 8000

# 初始化摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 创建TCP套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))

try:
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        # 编码为JPEG
        _, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
        # 发送帧长度 + 帧数据
        client_socket.sendall(struct.pack('>L', len(buffer)) + buffer)
finally:
    cap.release()
    client_socket.close()

控制端(接收端)Tkinter整合代码

接收TCP传输的帧,解码后转换成Tkinter的PhotoImage,在Label组件中显示:

import tkinter as tk
import cv2
import socket
import struct
import numpy as np
from PIL import Image, ImageTk

class CameraStreamApp:
    def __init__(self, root):
        self.root = root
        self.root.title("机器人摄像头流")
        
        # 创建显示用的Label
        self.label = tk.Label(root)
        self.label.pack()
        
        # 初始化TCP套接字
        self.HOST = "0.0.0.0"  # 监听所有网卡
        self.PORT = 8000
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind((self.HOST, self.PORT))
        self.server_socket.listen(1)
        self.client_socket, _ = self.server_socket.accept()
        
        # 开始帧接收和更新
        self.update_frame()
    
    def update_frame(self):
        # 接收帧长度
        length_data = self.recvall(struct.calcsize('>L'))
        if not length_data:
            self.root.quit()
            return
        length = struct.unpack('>L', length_data)[0]
        # 接收帧数据
        frame_data = self.recvall(length)
        # 解码帧
        frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)
        # 转换颜色空间(OpenCV是BGR,Tkinter需要RGB)
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # 转换成PhotoImage
        img = Image.fromarray(frame_rgb)
        imgtk = ImageTk.PhotoImage(image=img)
        self.label.imgtk = imgtk  # 保留引用防止被垃圾回收
        self.label.config(image=imgtk)
        # 循环调用更新
        self.root.after(10, self.update_frame)
    
    def recvall(self, count):
        # 确保接收完整的数据
        buf = b''
        while count:
            new_buf = self.client_socket.recv(count)
            if not new_buf:
                return None
            buf += new_buf
            count -= len(new_buf)
        return buf

if __name__ == "__main__":
    root = tk.Tk()
    app = CameraStreamApp(root)
    root.mainloop()

方案2:Picamera2 + Tkinter(树莓派原生摄像头库)

如果使用Pi Camera v2/v3,推荐用官方的Picamera2库,延迟更低:

机器人端(发送端)代码

from picamera2 import Picamera2
import socket
import struct
import cv2

HOST = "控制端IP"
PORT = 8000

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"size": (640, 480)}))
picam2.start()

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))

try:
    while True:
        frame = picam2.capture_array()
        # 转换为BGR格式(Picamera2默认是RGB)
        frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        _, buffer = cv2.imencode('.jpg', frame_bgr, [cv2.IMWRITE_JPEG_QUALITY, 80])
        client_socket.sendall(struct.pack('>L', len(buffer)) + buffer)
finally:
    picam2.stop()
    client_socket.close()

控制端代码

和方案1的控制端代码完全一致,无需修改。

注意事项

  • 两台树莓派需在同一以太网段,确保防火墙开放对应端口(8000)
  • 安装依赖:
    机器人端/控制端都需要安装:pip install opencv-python pillow
    用Picamera2的话,机器人端还需安装:sudo apt install python3-picamera2
  • 可以调整帧的分辨率和JPEG质量来平衡流畅度和画质
  • 如果需要开机自启动发送端脚本,可将其加入rc.local或创建systemd服务,替代原来的bash脚本

内容的提问来源于stack exchange,提问作者Pablo Córdoba Rodríguez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:07:27