python中的JPG编码通过套接字发送到C#并解码

python中的JPG编码通过套接字发送到C#并解码,c#,python,sockets,stream,jpeg,C#,Python,Sockets,Stream,Jpeg,我想将处理后的图像从python后端发送到C#前端。 所以我使用JPG编码器对其进行编码并发送 当我收到它并使用C#中的JPEG解码器对其进行解码时,它抛出异常。其中,接收字节的大小等于编码后发送的字节 谁能指导我如何解码和显示这幅图像 Python服务器端编码图像JPG中的代码 while True: conn, addr = s.accept() print ('connected to : ' + addr[0] +" :"+ str(addr[1])) vid

我想将处理后的图像从python后端发送到C#前端。 所以我使用JPG编码器对其进行编码并发送

当我收到它并使用C#中的JPEG解码器对其进行解码时,它抛出异常。其中,接收字节的大小等于编码后发送的字节

谁能指导我如何解码和显示这幅图像

Python服务器端编码图像JPG中的代码

while True:
    conn, addr = s.accept()
    print ('connected to : ' + addr[0] +" :"+ str(addr[1])) 

    vidcap = cv2.VideoCapture(videoPath)
    total_frames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
    conn.setblocking(0)
    for mm in range(0,total_frames ,1):
       try:
           dataClient = str(conn.recv(4096).decode('UTF-8'))
           conn.send(str.encode(dataClient))   
           conn.close()
           kk=2
           break
       except socket.error:

           ret,img= vidcap.read()
           image = cv2.resize(img, (640, 480)) 
           #############################################
           encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),100]
           result,enData=cv2.imencode('.jpg',image,encode_param)
           conn.send(enData)
           #############################################
            const int PORT_NO = 6666;
            //const string SERVER_IP = "210.107.232.138"; // 210.107.232.138          127.0.0.1
            string SERVER_IP = IpAddress.Text;
            client = new TcpClient(SERVER_IP, PORT_NO);
            nwStream = client.GetStream();
            bytesToRead = new byte[client.ReceiveBufferSize];
            bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
            /////////////////////////////////////
            MemoryStream ms = new MemoryStream(bytesRead);
            JpegBitmapDecoder decoder = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); //line 129
            BitmapSource bitmapSource = decoder.Frames[0];
            ///////////////////////////////////// 
            var src = new System.Windows.Media.Imaging.FormatConvertedBitmap();
            src.BeginInit();
            src.Source = bitmapSource;
            src.DestinationFormat = System.Windows.Media.PixelFormats.Bgra32;
            src.EndInit();

            //copy to bitmap
            Bitmap bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            src.CopyPixels(System.Windows.Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
            bitmap.UnlockBits(data);

            pictureBox2.Image = bitmap;
C#客户端解码图像JPG中的代码

while True:
    conn, addr = s.accept()
    print ('connected to : ' + addr[0] +" :"+ str(addr[1])) 

    vidcap = cv2.VideoCapture(videoPath)
    total_frames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
    conn.setblocking(0)
    for mm in range(0,total_frames ,1):
       try:
           dataClient = str(conn.recv(4096).decode('UTF-8'))
           conn.send(str.encode(dataClient))   
           conn.close()
           kk=2
           break
       except socket.error:

           ret,img= vidcap.read()
           image = cv2.resize(img, (640, 480)) 
           #############################################
           encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),100]
           result,enData=cv2.imencode('.jpg',image,encode_param)
           conn.send(enData)
           #############################################
            const int PORT_NO = 6666;
            //const string SERVER_IP = "210.107.232.138"; // 210.107.232.138          127.0.0.1
            string SERVER_IP = IpAddress.Text;
            client = new TcpClient(SERVER_IP, PORT_NO);
            nwStream = client.GetStream();
            bytesToRead = new byte[client.ReceiveBufferSize];
            bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
            /////////////////////////////////////
            MemoryStream ms = new MemoryStream(bytesRead);
            JpegBitmapDecoder decoder = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); //line 129
            BitmapSource bitmapSource = decoder.Frames[0];
            ///////////////////////////////////// 
            var src = new System.Windows.Media.Imaging.FormatConvertedBitmap();
            src.BeginInit();
            src.Source = bitmapSource;
            src.DestinationFormat = System.Windows.Media.PixelFormats.Bgra32;
            src.EndInit();

            //copy to bitmap
            Bitmap bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            src.CopyPixels(System.Windows.Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
            bitmap.UnlockBits(data);

            pictureBox2.Image = bitmap;

TCP客户端。ReceiveBufferSize
具有。如果您的jpeg数据的字节数大于此数,因为您的c#代码只读取缓冲区一次,您将无法接收整个数据

您可能希望在c#代码中使用循环进行读取,直到到达tcp流的末尾

试试这个:

var ms=newmemoryStream();
var buff=新字节[client.ReceiveBufferSize];
while(true){
var len=nwStream.Read(buff,0,buff.Length);

如果(len
TcpClient.ReceiveBufferSize
有一个。如果您的jpeg数据的字节数大于该字节数,因为您的c#代码只读取缓冲区一次,您将不会收到整个数据

您可能希望在c#代码中使用循环进行读取,直到到达tcp流的末尾

试试这个:

var ms=newmemoryStream();
var buff=新字节[client.ReceiveBufferSize];
while(true){
var len=nwStream.Read(buff,0,buff.Length);
如果(len)
此行创建一个内存流,初始容量为
bytesRead
字节。请参阅

您还需要使用另一个构造函数来填充接收到的数据:

MemoryStream ms = new MemoryStream(bytesToRead); // byte[], received data


请注意john对您的接收代码的评论:

不能保证您将在单个接收事件中接收完整的数据缓冲区

此行创建一个内存流,初始容量为
bytesRead
字节。请参阅

您还需要使用另一个构造函数来填充接收到的数据:

MemoryStream ms = new MemoryStream(bytesToRead); // byte[], received data


请注意john对您的接收代码的评论:

不能保证您将在单个接收事件中接收完整的数据缓冲区



如果ByteRead小于Python代码发送的字节,该怎么办?不能保证在单个接收事件中接收到完整的数据缓冲区。还有,为什么不能只使用
Image.FromStream(…)
方法?我也尝试过,但它也不起作用,因为您没有在MemoryStream中放入任何内容。您只需使用由
bytesRead
确定的大小初始化它。您可能想使用
新MemoryStream(bytesToRead)
?我检查两侧的字节大小。它们是相同的。请再次阅读我的评论。您的问题不在于接收(尽管它有点缺陷,正如john指出的那样)。您的MemoryStream为空。您正在使用此构造函数:但您需要此构造函数:如果ByteRead小于Python代码发送的字节,该怎么办?无法保证您将在单个接收事件中接收到完整的数据缓冲区。此外,您是否有理由不能仅使用
Image.FromStream(…)
方法?我也尝试过,但它也不起作用,因为您没有在MemoryStream中放入任何内容。您只需使用由
bytesRead
确定的大小初始化它。您可能想使用
新MemoryStream(bytesToRead)
?我检查两侧的字节大小。它们是相同的。请再次阅读我的评论。您的问题不在于接收(尽管它有点缺陷,正如john指出的那样)。您的MemoryStream为空。您正在使用此构造函数:但您需要此构造函数:编码后的数据大小为161183字节。这几乎是1。5kb@AminUllah大约16KB。@yunlo 161183/1024=157.4(四舍五入)@Fildor:)大约160KB,我的错误,但仍然远远超过8KB。@Yunloo是的。但是,如果OP修复了接收代码,问题仍然存在。不过,使用您的代码段应该可以工作。编码后的数据大小是161183字节。这几乎是1。5kb@AminUllah大约16KB。@yunlo 161183/1024=157.4(四舍五入)@Fildor:)大约160KB,我的错误,但仍然远远超过8KB。@yunlo是的。但是,如果OP修复了他的接收代码,问题仍然会存在。但是,使用您的代码片段,它应该可以工作。我的代码是时间事件,而不是在单个事件中接收。
private void Timer_Tick(object sender,EventArgs e){nwStream=client.GetStream();bytesToRead=新字节[client.ReceiveBufferSize];bytesRead=nwStream.Read(bytesToRead,0,client.ReceiveBufferSize);MemoryStream ms=新的MemoryStream(bytesRead);JpegBitmapDecoder=新的JpegBitmapDecoder(ms,BitmapCreateOptions.PreservePixelFormat,BitmapCacheOption.Default);BitmapSource BitmapSource=decoder.Frames[0];}
暂时忽略该部分。只需尝试在MemoryStream CTOR中用bytesToRead替换bytesRead,看看会发生什么……是的,它可以工作,我收到第一个图像,但它是一半。我不知道为什么。这是另一个问题;)我的代码是时间事件,它不是在单个事件中接收的。
私有无效计时器\u勾选(对象发送方,事件参数e){nwStream=client.GetStream();bytesToRead=new byte[client.ReceiveBufferSize];bytesRead=nwStream.Read(bytesToRead,0,client.ReceiveBufferSize);MemoryStream ms=new MemoryStream(bytesRead);JpegBitmapDecoder=new JpegBitmapDecoder(ms,BitmapCreateOptions.PreservePixelFormat,BitmapCacheOption.Default);BitmapSource BitmapSource=decoder.Frames[0];}
暂时忽略该部分。只需尝试在MemoryStream CTOR中将bytesRead替换为bytesToRead,然后看看会发生什么……是的,它可以工作,我收到第一张图像,但它是一半。我不知道为什么。这是另一个问题;)