话不多说,先看一下效果(python为服务器端,Qt为客户端)
左边是在python中用OpenCV显示的图像(RGB通道翻转过),右边是Qt接受数据后画出的图像,左下角是Qt发送到python的控制指令。
python服务器端实现
import socketserver
import socket
import cv2
import numpy as np
import threading
IMAGESIZE = 921600
IMAGEWIDTH = 640
IMAFEHEIGHT = 480
FRAMELENGTH = 1024
# 读取路径下的视频文件,以OpenCV打开
# 当然也可以打开摄像头
filepath = 'VideoTest.mp4'
cap = cv2.VideoCapture(filepath)
# 创建服务器
server = socket.socket()
# 获取到本机IP
PCname = socket.gethostname()
IP = socket.gethostbyname(PCname)
print(IP)
# 设置IP和端口号
server.bind((IP, 8082))
server.listen(1)
print('connecting...')
# 多线程接收数据
# socket接收为阻塞接收方式,阻断程序运行
# 用多线程的方式来避免发生阻塞
class Receive_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.return_value = b'0'
def run(self):
while True:
# 每次接收一个字节的数据
self.return_value = cmd = conn.recv(1)
# 返回接收到的数据
def get_value(self):
return self.return_value
while True:
# 等待客户端连接
# 阻塞方式,不连接不会执行下一步
# conn为新创建的socket对象
# 用于下边数据收发
conn, addr = server.accept()
print('收到请求')
print('客户端地址', addr)
# 创建数据接收线程
rec_thread = Receive_Thread()
rec_thread.start()
while True:
# 读取下一帧
ret, frame = cap.read()
# 数据类型为uint8
framed = cv2.resize(frame, (IMAGEWIDTH, IMAFEHEIGHT))
framed = cv2.cvtColor(framed, cv2.COLOR_BGR2RGB)
has_sent = 0
rec_data = rec_thread.get_value()
# 打印接收到的控制指令
if rec_data != b'0':
print(rec_data)
# 发送图片,每次发送1024字节
while has_sent < IMAGESIZE:
data_to_send = framed[has_sent: has_sent+FRAMELENGTH]
conn.send(data_to_send)
has_sent += FRAMELENGTH
cv2.waitKey(100)
cv2.imshow('jj', framed)
break
cap.release()
到这里完成了TCPserver的部分,接下来在Qt中完成TCPClient的部分
Qt客户端实现
由于Qt代码较长,可以点击这里前往我的git主页下载
鉴于git网速较慢,也可以点击这里下载
根据其他博客,每一个部分基本都比较容易实现
但是又一个重要的一步是从Qbytearray转化到图片
在很多博客中都是通过QImage类的loadfromdata()来从数据获取图片
然而我测试n+1次仍未成功
后来采用了以下方法,其实很简单,只不过是不用loadfromdata函数来加载Qbytearray数据,而是改成了字符串:
void MainWindow::onSocketReadyRead()
{
QByteArray bytes=NULL;
while(Client->waitForReadyRead(100))
{
bytes.append((QByteArray)Client->readAll());
}
imagecount++;
ReceiveCount->setText(QString::number(imagecount,10));
// 网上大多数转换方法不对
// uchar imagebuffer[IMAGESIZE];
memcpy(imagebuffer, bytes, IMAGESIZE);
image_receive=new QImage(imagebuffer, imagewidth,imageheight,QImage::Format_RGB888);
DrawPainter->PassImage(*image_receive);
DrawPainter->update();
}
至此整个程序完成