python socket传输摄像头实时获取的ndarray图片

python socket传输摄像头实时获取的ndarray图片

简介

最近在实现一个ubuntu系统下的pyqt(pyside)应用,一台电脑跑ubuntu+ros,一台电脑跑win10和TensorFlow做实时图像实例分割,需要把图像传回到跑ros的ubuntu上面显示,所以使用局域网传输的方式解决,速度在可接受范围,图像尺寸640x480

1. 服务端(跑TF的win10电脑)

1.1 创建子线程启动socket服务函数

t1 = threading.Thread(target=socket_server)
t1.start()

1.2 实现socket服务函数

def socket_server():
    s = socket.socket()  # 创建 socket 对象
    host = socket.gethostname()  # 获取本地主机名
    port = 60000  # 设置端口
    s.bind((host, port))  # 绑定端口
    print("服务端开启")
    s.listen(5)
    while True:
        try:
            c, addr = s.accept()  # 建立客户端连接
            print("连接地址:" + str(addr))
            while True:
                # 先获取客户端发送过来的请求
                rec_data = c.recv(64)
                rec_data = str(rec_data, encoding='utf-8')
                print(rec_data)
                # 是返回原图还是预测后的图片
                if rec_data == "origin" or rec_data == "pred":
                    send_data = server_test(rec_data)
                    arrBuf = bytearray(b'\xff\xaa\xff\xaa')
                    picBytes = send_data

                    # 图片大小
                    picSize = len(picBytes)

                    # 数据体长度 = guid大小(固定) + 图片大小
                    datalen = picSize

                    # 组合数据包
                    arrBuf += bytearray(datalen.to_bytes(4, byteorder='little'))
                    arrBuf += picBytes
                    c.sendall(arrBuf)
                # 用来返回口腔坐标信息, 只需要发送图像的可忽略
                else:
                    send_data = send_json()
                    c.send(bytes(send_data, encoding='utf-8'))
            c.close()
        except Exception as e:
            print("远程主机强制关闭连接")
            print(e.args)
    s.close()

1.3 ndarray转bytes数据

ndarray图片转为二级制数据

# 定义全局变量,将从摄像头获取到的图片二进制数据保存到全局变量
global pred_frame_bytes
# 使用tobytes函数转换为二进制数据
pred_frame_bytes = image_np.tobytes()

返回数据

# 1.2调用的函数,判断返回原图还是预测后的图片,返回的是一个全局变量
def server_test(value):
    if value == "origin":
        return origin_frame_bytes
    else:
        return pred_frame_bytes

2. 客户端(跑ros的ubuntu电脑)

    def get_display(self):
        host = self.host_content.text()
        port = self.port_content.text()
        s = socket.socket()
        s.connect((host, int(port)))
        while True:
        		# self.mask_type是一个字符串, 用于给服务端判断是返回原图还是预测后的图片
                s.send(bytes(self.mask_type, encoding='utf-8'))
                str = s.recv(8)
                # 头部检验
                data = bytearray(str)
                headIndex = data.find(b'\xff\xaa\xff\xaa')
                if headIndex == 0:
                        allLen = int.from_bytes(data[headIndex + 4:headIndex + 8], byteorder='little')
                        curSize = 0
                        allData = b''
                        # 通过循环获取完整图片数据
                        while curSize < allLen:
                                data = s.recv(1024)
                                allData += data
                                curSize += len(data)
                        # 取出图片数据
                        imgData = allData[0:]
                        # bytes转PIL.Image
                        img = Image.frombuffer('RGB', (640, 480), imgData)
                        # 传过来的图片被上下镜面了,将其返回来
                        img = img.transpose(Image.FLIP_TOP_BOTTOM)
                        # PIL.Image转ndarray
                        img_conv = np.asarray(img)
                        # 下面根据自己的业务逻辑来进行修改
                        qimage = QImage(img_conv, 640, 480, QImage.Format_RGB888)
                        pixmap = QPixmap.fromImage(qimage)
                        # 更新QLabel图片
                        self.dis_update.emit(pixmap)

测试效果

通过socket返回的实时预测图片

你可能感兴趣的:(Python,python)