opencv-python send camera image to Unity in real time

Unity code (server side, receiving image side)

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;
    }
}

Python code (client side, sending image side, automatic reconnection when disconnected)

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()

UnityThread class used by Unity code see this article

Guess you like

Origin blog.csdn.net/zouxin_88/article/details/117325268#comments_20884696