通过 TCP 发送图像

Posted

技术标签:

【中文标题】通过 TCP 发送图像【英文标题】:Image send via TCP 【发布时间】:2014-01-16 05:17:58 【问题描述】:

我正在尝试使用 python (raspberry PI) 通过 TCP Socket 发送捕获图像的数据。 TCP Server (QT) 在其他机器上运行并尝试读取图像并在 QLabel 中显示。

我从来没有在 python 中编程过,完全不明白我做错了什么。我花了很多时间(几天)来解决持续出现的错误,终于到了可以实际运行它的地步。但是我收到的数据是垃圾。

以下程序在 raspberry PI 的 sep 窗口中显示视频,并应通过套接字发送单个捕获的图像。

import cv2.cv as cv
import cv2
import time
from socket import socket
import sys
import numpy

cv.NamedWindow("camera",cv.CV_WINDOW_AUTOSIZE)

capture = cv.CaptureFromCAM(0)

sock = socket()
sock.connect(('192.168.0.2', 5001))
sock.send('Pi - Hallo')

while True:
    frame = cv.QueryFrame(capture)
    cv.ShowImage("camera", frame)

    mat = cv.GetMat(frame)
    buf = [1,90]

    image = cv.CreateImage (cv.GetSize (frame), 8, 3)
    nuImage = numpy.asarray(frame[:,:])
    imgencode = cv2.imencode('.png', nuImage, buf)
    data = numpy.array(imgencode)
    stringData = data.tostring()
    sock.send('Pi - Sending image data');
    sock.send( stringData );

    if cv.WaitKey(10) == 27:
        break

sock.send('Pi - closing connection')
sock.close()

【问题讨论】:

好吧,如果您收到“一块垃圾”,那只是编码和解码问题。尝试调试看看。 【参考方案1】:

您收到的数据不是垃圾。它是发送数据。但它是以字节为单位发送的。因此,在接收端,您需要在处理数据之前将字节转换为字符串。阅读this 以更好地了解在套接字编程中发送和接收数据,阅读this 了解当前版本的opencv 中使用的方法。

您也不需要使用 cv 来执行此任务。当前版本的 opencv 提供了仅通过 import cv2 执行此操作的方法。

以下是一个工作代码,虽然它的通信被简化了。

client.py

#!/usr/bin/python
import socket
import cv2
import numpy

TCP_IP = 'localhost'
TCP_PORT = 5001

sock = socket.socket()
sock.connect((TCP_IP, TCP_PORT))

capture = cv2.VideoCapture(0)
ret, frame = capture.read()

encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90]
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = numpy.array(imgencode)
stringData = data.tostring()

sock.send( str(len(stringData)).ljust(16));
sock.send( stringData );
sock.close()

decimg=cv2.imdecode(data,1)
cv2.imshow('CLIENT',decimg)
cv2.waitKey(0)
cv2.destroyAllWindows() 

server.py

#!/usr/bin/python
import socket
import cv2
import numpy

def recvall(sock, count):
    buf = b''
    while count:
        newbuf = sock.recv(count)
        if not newbuf: return None
        buf += newbuf
        count -= len(newbuf)
    return buf

TCP_IP = 'localhost'
TCP_PORT = 5001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(True)
conn, addr = s.accept()

length = recvall(conn,16)
stringData = recvall(conn, int(length))
data = numpy.fromstring(stringData, dtype='uint8')
s.close()

decimg=cv2.imdecode(data,1)
cv2.imshow('SERVER',decimg)
cv2.waitKey(0)
cv2.destroyAllWindows() 

【讨论】:

我认为你这里有一个错误 - 你的行 decimg = cv2.imdecode(data,1) 应该替换为:decimg =data.reshape((480,640,3)) 请问您通过套接字发送图像是否是一种有效的方式?并且套接字对大量图像有好处吗? (对不起,我是 socket 新手) 自此发布以来已经 4 年了,我不确定是否开发了一些新的有效方法。 一般来说,为了使用原始套接字发送视频流,您必须使用 UDP 协议。但这是一个常见问题,您可能会遇到link。一般来说,通过 TCP 发送大流是“不好”的做法

以上是关于通过 TCP 发送图像的主要内容,如果未能解决你的问题,请参考以下文章

Java:通过 TCP 发送/接收数据并从 UDP 接收图像

套接字编程/通过无线发送二进制图像数据

从内存中打开 PNG 文件并通过 TCP 套接字发送

从android客户端通过套接字发送后收到黑色图像

通过 TCP 发送/接收文件 [重复]

使用 SyslogNet.Client 通过 TCP 发送 SysLog 消息