PC电脑实时接收树莓派摄像头图像数据并显示(Python实现)
目录
一、任务概述
二、环境安装
三、实现
3.1 上位机端(PC服务器端)
3.2 树莓派端(客户请求端)
四、运行效果
一、任务概述
最近在做一个树莓派自动驾驶小车,上位机使用windows10 PC电脑,下位机小车采用树莓派4B,树莓派上安装了USB免驱摄像头。上位机通过SSH来控制和分析树莓派小车。树莓派上使用python版的opencv读取摄像头图像数据。
实验时发现,上位机通过SSH控制树莓派时会自发的将远程图像数据也显示过来(调用cv2.imshow的时候),但是这种通过SSH传输图像的方式会造成SSH卡顿,导致视频图像卡、下位机机电控制卡。但是在小车运行的时候它上面的树莓派不方便连接显示器,而我们又需要实时反馈运动中的小车图像给上位机来调试分析。因此,需要一种高效的在树莓派和PC之间通过无线局域网的视频图像传输方案。
网上方法有很多,这里介绍一种自己亲身试验过并且相对比较简单的方法。
二、环境安装
首先确保上位机(PC电脑)和下位机(树莓派)均安装好了python版的opencv和numpy。
接下来在上下位机均安装帧传输模块zmq:
sudo pip3 install zmq
然后在上下位机均安装帧编解码库pybase64:
sudo pip3 install pybase64
到这里环境安装结束。
三、实现
3.1 上位机端(PC服务器端)
import cv2
import zmq
import base64
import numpy as np
def main():
'''
主函数
'''
context = zmq.Context()
footage_socket = context.socket(zmq.PAIR)
footage_socket.bind('tcp://*:5555')
cv2.namedWindow('Stream',flags=cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)
while True:
print("监听中")
frame = footage_socket.recv_string() #接收TCP传输过来的一帧视频图像数据
img = base64.b64decode(frame) #把数据进行base64解码后储存到内存img变量中
npimg = np.frombuffer(img, dtype=np.uint8) #把这段缓存解码成一维数组
source = cv2.imdecode(npimg, 1) #将一维数组解码为图像source
cv2.imshow("Stream", source) #把图像显示在窗口中
cv2.waitKey(5) #延时等待,防止出现窗口无响应
if __name__ == '__main__':
'''
程序入口
'''
main()
然后在上位机上运行上述脚本代码。
3.2 树莓派端(客户请求端)
import cv2
import zmq
import base64
def main():
'''
主函数
'''
IP = '192.168.2.148' #上位机视频接受端的IP地址
# 创建并设置视频捕获对象
cap = cv2.VideoCapture(0)
print("摄像头是否已经打开 ? {}".format(cap.isOpened()))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) # 设置图像宽度
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # 设置图像高度
# 建立TCP通信协议
contest = zmq.Context()
footage_socket = contest.socket(zmq.PAIR)
footage_socket.connect('tcp://%s:5555'%IP)
while True:
# 读取图像
ret, frame = cap.read()
# 转换为流数据并编码
encoded, buffer = cv2.imencode('.jpg', frame)
jpg_as_test = base64.b64encode(buffer) #把内存中的图像流数据进行base64编码
# 发送数据
footage_socket.send(jpg_as_test) #把编码后的流数据发送给视频的接收端
cv2.waitKey(5) #延时等待,防止出现窗口无响应
if __name__ == '__main__':
'''
程序入口
'''
main()
在下位机端运行上述脚本代码。
四、运行效果
整体运行还是比较顺畅的,解决了上下位机图像实时显示的问题。
来源:钱彬 (Qian Bin)