Code d'unité (côté serveur, côté image de réception)
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgcodecsModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class networkCon : MonoBehaviour {
Thread mThread;
TcpListener listener;
TcpClient client;
bool running;
Renderer renderer;
void Awake()
{
UnityThread.initUnityThread();
}
private void Start()
{
renderer = gameObject.GetComponent<Renderer>();
ThreadStart ts = new ThreadStart(GetInfo);
mThread = new Thread(ts);
mThread.Start();
}
void GetInfo()
{
listener = new TcpListener(IPAddress.Any, 9999);
listener.Start();
client = listener.AcceptTcpClient();
running = true;
while (running)
{
Connection();
}
listener.Stop();
}
void Connection()
{
NetworkStream nwStream = client.GetStream();
//接收第一个数字,表示数据长度,占16位
byte[] bufNumber = new byte[16];
int byReadNumber = nwStream.Read(bufNumber, 0, 16);
string dataReceived = Encoding.UTF8.GetString(bufNumber, 0, byReadNumber);
int dataSize = int.Parse(dataReceived.Trim());
//接收图片数据,可能一次性接收不完,分多次接收
int byLengthTotal = 0; //已接收字节长度
byte[] bufTotal = new byte[dataSize]; //已接收字节数组
while (true)
{
int leftSize = dataSize - byLengthTotal;//剩余字节数
byte[] bufTmp = new byte[leftSize];
int byReadTmp = nwStream.Read(bufTmp, 0, leftSize);
Array.Copy(bufTmp, 0, bufTotal, byLengthTotal, byReadTmp);
byLengthTotal += byReadTmp;
if (byLengthTotal == dataSize)
break;
}
//将buffer转化为Mat
Mat buff = new Mat(1, bufTotal.Length, CvType.CV_8UC1);
Utils.copyToMat<byte>(bufTotal, buff);
//解码图片
Mat srcImage = Imgcodecs.imdecode(buff, Imgcodecs.IMREAD_COLOR);
if (srcImage.width() > 0 && srcImage.height() > 0)
{
UnityThread.executeInUpdate(() =>
{
Mat imgMat = new Mat();
Imgproc.cvtColor(srcImage, imgMat, Imgproc.COLOR_BGR2RGB);
Texture2D texture = new Texture2D(imgMat.cols(), imgMat.rows(), TextureFormat.RGBA32, false);
Utils.matToTexture2D(imgMat, texture);
renderer.material.mainTexture = texture;
});
}
}
private void OnDestroy()
{
running = false;
}
}
Code Python (côté client, côté envoi image, reconnexion automatique en cas de déconnexion)
import os,sys,time
import socket
import cv2
import numpy
#建立图像读取对象
capture = cv2.VideoCapture(0)
#读取一帧图像,读取成功:ret=1 frame=读取到的一帧图像;读取失败:ret=0
ret, frame = capture.read()
#压缩参数,后面cv2.imencode将会用到,对于jpeg来说,15代表图像质量,越高代表图像质量越好为 0-100,默认95
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),15]
def main():
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.settimeout(5)
connect = False
while True:
ret, frame = capture.read()
cv2.imshow("capture", frame)
if cv2.waitKey(10) == 27:
break
try:
if connect == False:
client.connect(("192.168.0.101",9999))
connect = True
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
#建立矩阵
data = numpy.array(imgencode)
#将numpy矩阵转换成字符形式,以便在网络中传输
stringData = data.tostring()
#先发送要发送的数据的长度
#ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串
print(len(stringData))
strlen = str(len(stringData)).ljust(16)
client.send(bytes(strlen, 'UTF-8'));
#发送数据
client.send(stringData);
except socket.error as e:
print("Address-related error connecting to server: %s" % e)
connect = False
time.sleep(0.01)
if __name__ == "__main__" :
main()
Classe UnityThread utilisée par le code Unity voir cet article