该项目的目标是通过tcp套接字将从python主机捕获的视频流式传输到c#客户端 .
关联python2服务器脚本:
import cv2
import numpy as np
import socket
from threading import Thread
_continue = True
def imageStreamer4():
global _continue
cam = cv2.VideoCapture(0)
camSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
camSocket.bind(("",8081))
camSocket.listen(1)
# set flip image to false if you don't want the image to be flipped
flipImage = True
while _continue:
try:
client,address = camSocket.accept()
print("client connected")
ret,camImage = cam.read()
if flipImage:
camImage = cv2.flip(camImage,1)
#uncomment the below code to view the webcam stream locally
"""
cv2.imshow('image',camImage)
if cv2.waitKey(1) == 27:
break # esc to quit
"""
byteString = bytes(cv2.imencode('.jpg', camImage)[1].tostring())
fileSize = len(byteString)
totalSent = 0
client.send(str(fileSize).encode())
sizeConfirmation = client.recv(1024)
totalSent = 0
while totalSent < fileSize:
totalSent += client.send(byteString[totalSent:])
print(str(fileSize), str(totalSent),sizeConfirmation.decode('utf-8'))
except Exception as e:
print(e)
print("shutting down video stream")
_continue = False
print("video stream exited.")
相关的c#客户端代码:
using System.Collections;
using UnityEngine;
using System;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using UnityEngine.UI;
using System.IO;
void getVideoStream()
{
byte[] header;
int recieved;
int fileSize;
NetworkStream dataStream;
MemoryStream ms;
while (connectCam)
{
fileSize = 0;
recieved = 0;
camClient = new TcpClient(camIP, camPort);
//get header
dataStream = camClient.GetStream();
while (!dataStream.DataAvailable)
{
//waste time
}
header = new byte[1024];
dataStream.Read(header, 0, header.Length);
fileSize = Int32.Parse(Encoding.Default.GetString(bytesReducer(header)));
byte[] result = Encoding.ASCII.GetBytes(fileSize.ToString());
//send response
dataStream.Write(result, 0, result.Length);
ms = new MemoryStream();
while (!dataStream.DataAvailable)
{
//waste time
}
while (recieved < fileSize)
{
byte[] data = new byte[camClient.ReceiveBufferSize];
recieved += dataStream.Read(data, 0, data.Length);
ms.Write(data, 0, data.Length);
}
//the below class simply sends function calls from secondary thread back to the main thread
UnityMainThreadDispatcher.Instance().Enqueue(convertBytesToTexture(ms.ToArray()));
dataStream.Close();
camClient.Close();
}
}
void convertBytesToTexture(byte[] byteArray) {
try
{
camTexture.LoadImage(byteArray); //Texture2D object
camImage.texture = camTexture; //RawImage object
}
catch (Exception e)
{
print(e);
}
}
发送和接收的字节数与它们应该匹配 . 我不熟悉使用套接字,但我很确定数据是完整无缺的 . 不幸的是,我真的不知道为什么图像会像现在这样分裂 . (如上图所示)如果它完全相关,则服务器和客户端功能都在各自独立的线程上运行 .
我在不同的主机和客户端上运行脚本,结果保持不变 . 如果需要任何不同的信息来帮助,请问 . 我很乐意根据需要更新 .
2 回答
通过删除以下代码插入的空白区域,我能够正确地将图片放在一起:
用这个替换它:
因此,不是将客户端缓冲区的大小数组带入内存流(即使它未满),而是将其浓缩为仅通过read方法接收的信息量 . 这有效地移除了接收图像中的所有空白区域 .
因为Tcp是一个流,所以你应该将它视为一个字节流,所以你应该应用一些机制来识别每个图像,这样你就可以应用:
在客户端,您开始阅读,直到达到分隔符
当您首先在客户端上读取数据时,您总是读取8个字节,然后根据此大小读取其余数据 .