Pynq-z2通过ps端调用usb摄像头

准备阶段:

确保板卡可以连接上以太网

一个免驱动的摄像头

Pynq-z2板卡套件

将pyqn-z2板卡连接在电脑上,电源器模式启动,连接上usb摄像头:

这里博者购买的是一款免驱的usb摄像头(要支持uvc模式)。

串口通信:

连接完成后,在pc端打开设备管理器,查看端口号博者的是com7,putty选中串口通信,speed:115200,在open终端界面。

在终端界面登入pynq后,输入: ls /dev/video*    

查看板卡是否识别到usb摄像头。

在终端界面输入命令行:

sudo apt update

sudo apt upgrade

确保包管理器是最新的,再输入命令行,安装gstreamer基础包:

sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly

这里博者的pynq镜像是pynq3.0.0,如果输入这段命令行后有报错,可以把所使用的版本号告诉gpt,让gpt查找相应的gstreamer版本包。

到这里应该就完成了板卡上环境的配置。(如果还少什么包,就按照报错的提示,让gpt写相应的命令行。)

Jupyter notebook(sever端的代码):

在usb摄像头调用上,我们使用socket库,它提供了一种在不同计算机进程间进行数据传输的机制。在互联网编程中,socket 是应用层与传输层(如 TCP/IP 协议栈)之间的接口,允许应用程序发送或接收数据,就像使用文件一样简单。简单来说就是实现网络通信,调用网络摄像头。

打开pynq-z2板卡的jupyter notebook界面,

创建一个新的.ipynb文件,命名为sever.ipynb就是服务端的代码。

import socket
import threading
import struct
import time
import cv2
import numpy

class Carame_Accept_Object:
    def __init__(self, S_addr_port=("", 1100)):
        self.resolution = (640, 480)  # 分辨率
        self.img_fps = 15  # 每秒传输多少帧数
        self.addr_port = S_addr_port
        self.Set_Socket(self.addr_port)
 
    def Set_Socket(self, S_addr_port):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 端口可复用
        self.server.bind(S_addr_port)
        self.server.listen(5)
 
def check_option(object, client):
    info = struct.unpack('lhh', client.recv(8))
    if info[0] > 888:
        object.img_fps = int(info[0]) - 888  # 获取帧数
        object.resolution = list(object.resolution)
        object.resolution[0] = info[1]
        object.resolution[1] = info[2]
        object.resolution = tuple(object.resolution)
        return 1
    else:
        return 0
 
def RT_Image(object, client, D_addr):
    if (check_option(object, client) == 0):
        return
    camera = cv2.VideoCapture(0)  # 从摄像头中获取视频
    img_param = [int(cv2.IMWRITE_JPEG_QUALITY), object.img_fps]  # 设置传送图像格式、帧数
    while (1):
        time.sleep(0.1)  # 推迟线程运行0.1s
        _, object.img = camera.read()  # 读取视频每一帧

        object.img = cv2.resize(object.img, object.resolution)  # 按要求调整图像大小(resolution必须为元组)
        _, img_encode = cv2.imencode('.jpg', object.img, img_param)  # 按格式生成图片
        img_code = numpy.array(img_encode)  # 转换成矩阵
        object.img_data = img_code.tobytes()  # 生成相应的字节数据

        try:
            # 按照相应的格式进行打包发送图片
            client.send(
                struct.pack("lhh", len(object.img_data), object.resolution[0], object.resolution[1]) + object.img_data)
        except:
            camera.release()  # 释放资源
            return
 
if __name__ == '__main__':
    camera = Carame_Accept_Object()
    while (1):
        client, D_addr = camera.server.accept()
        clientThread = threading.Thread(None, target=RT_Image, args=(camera, client, D_addr,))
        clientThread.start()

将代码直接在jupyter上运行。

主机端代码:

在连接板卡的电脑上,用pycharm创建一个client.py

import socket
import cv2
import threading
import struct
import numpy

class Camera_Connect_Object:
    def __init__(self, D_addr_port=["", 1100]):
        self.resolution = [384, 288]
        self.addr_port = D_addr_port
        self.src = 888 + 15  # 双方确定传输帧数,(888)为校验值
        self.interval = 0  # 图片播放时间间隔
        self.img_fps = 15  # 每秒传输多少帧数

    def Set_socket(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    def Socket_Connect(self):
        self.Set_socket()
        self.client.connect(self.addr_port)
        print("IP is %s:%d" % (self.addr_port[0], self.addr_port[1]))

    def RT_Image(self):
        # 按照格式打包发送帧数和分辨率
        self.name = self.addr_port[0] + " Camera"
        self.client.send(struct.pack("lhh", self.src, self.resolution[0], self.resolution[1]))
        while (1):
            info = struct.unpack("lhh", self.client.recv(8))
            buf_size = info[0]  # 获取读的图片总长度
            if buf_size:
                try:
                    self.buf = b""  # 代表bytes类型
                    temp_buf = self.buf
                    while (buf_size):  # 读取每一张图片的长度
                        temp_buf = self.client.recv(buf_size)
                        buf_size -= len(temp_buf)
                        self.buf += temp_buf  # 获取图片
                    data = numpy.frombuffer(self.buf, dtype='uint8')  # 按uint8转换为图像矩阵
                    self.image = cv2.imdecode(data, 1)  # 图像解码
                    cv2.imshow(self.name, self.image)  # 展示图片
                except Exception as e:
                    print("Error:", e)
                finally:
                    if (cv2.waitKey(10) == 27):  # 每10ms刷新一次图片,按‘ESC’(27)退出
                        self.client.close()
                        cv2.destroyAllWindows()
                        break

    def Get_Data(self, interval):
        showThread = threading.Thread(target=self.RT_Image)
        showThread.start()


if __name__ == '__main__':
    camera = Camera_Connect_Object()
    camera.addr_port[0] = input("Please input IP:")
    camera.addr_port = tuple(camera.addr_port)
    camera.Socket_Connect()
    camera.Get_Data(camera.interval)

保存然后运行,就出现一下界面

输入你板卡的IP地址就可以正常接收摄像头传过来的视频数据。

如果遇到串口已被占用,就换一个串口号就行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值