【问题标题】:JPG encoding in python sent via socket to C# and decodepython中的JPG编码通过套接字发送到C#并解码
【发布时间】:2018-05-15 06:37:02
【问题描述】:

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

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

谁能指导我如何解码这张图片并显示它。

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

C# 客户端解码图像 JPG 中的代码

            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;

【问题讨论】:

  • 如果 bytesRead 小于 Python 代码发送的字节数怎么办?不能保证您将在单个接收事件中接收到完整的数据缓冲区。另外,你有什么理由不能只使用Image.FromStream(...) 方法吗?
  • 我也尝试过,但它也不起作用
  • 你在 MemoryStream 中没有放任何东西。您只需使用bytesRead 确定的大小对其进行初始化。您可能想使用new MemoryStream(bytesToRead)
  • 我检查两边的字节大小。这些都是一样的。
  • 再次阅读我的评论。您的问题不在于接收(尽管正如约翰已经指出的那样,它有些缺陷)。你的 MemoryStream 是空的。你正在使用这个构造函数:msdn.microsoft.com/en-us/library/bx3c0489(v=vs.110).aspx,但你需要这个:msdn.microsoft.com/en-us/library/e55f3s5k(v=vs.110).aspx

标签: c# python sockets stream jpeg


【解决方案1】:

TcpClient.ReceiveBufferSize 有一个default value 8KB。如果您的 jpeg 数据的字节数比这多,由于您的 c# 代码只读取缓冲区一次,您将不会收到整个数据。

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

试试这个:

var ms = new MemoryStream();
var buff = new byte[client.ReceiveBufferSize];
while (true) {
    var len = nwStream.Read(buff, 0, buff.Length);
    if (len <= 0) { break; }
    ms.Write(buff, 0, len);
}
ms.Seek(0, SeekOrigin.Begin);

希望有所帮助。

【讨论】:

  • 编码后的数据大小为161183字节。其中将近 1.5kb
  • @AminUllah 大约 16KB。
  • @YunLuo 161183 / 1024 = 157.4(四舍五入)
  • @Fildor :) 大约 160KB,我的错,但仍然远远超过 8KB。
  • @YunLuo 是的。不过,如果 OP 修复了他的接收代码,问题仍然存在。但是,使用 your sn-p 它应该可以工作。
【解决方案2】:
MemoryStream ms = new MemoryStream(bytesRead); // bytesRead = int, number of bytes received

此行创建一个初始容量为bytesRead 字节的 MemoryStream。见MemoryStream(int)

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

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

MemoryStream(Byte[])


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

无法保证您将在单个接收事件中接收到完整的数据缓冲区。

【讨论】:

  • 我的代码是时间事件,它不在单个事件中接收。 private void Timer_Tick(object sender, EventArgs e) { 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); BitmapSource bitmapSource = decoder.Frames[0]; }
  • 暂时忽略那部分。 只需尝试在 MemoryStream CTOR 中用 bytesToRead 替换 bytesRead 看看会发生什么...
  • 是的,我收到了第一张图片,但它是一半。我不知道为什么。
  • 这是一个不同的问题 ;)
猜你喜欢
  • 2018-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-27
  • 2022-01-15
  • 2017-04-04
  • 2016-04-04
  • 2011-10-02
相关资源
最近更新 更多