socket传输图片之TCP协议

在学习socket传输图片之前,我们应该先具备一些基础知识。

opencv图片编码和解码

cv2.imencode()
cv2.imdecode()

这两个函数是本教程再传输图片会用到的。个人粗浅的理解是放在内存的中的图片是以图像数据的形式存放的,而它们的后缀.jpg或.png决定的是它们在传输过程中的形式以及它们从原来的原始数据被压缩过来的方式。简而言之,jpg、png(图像格式)是一个中间量,而不是一个状态量。可以理解为jpg通道之类的。
那么我们在用socket传输的时候就必须先把图像数据转化为图像格式。

#读取图像数据
image = cv2.imread("path/1.jpg")
#把图像数据转化为jpg格式(理解为打开jpg通道),至于以下参数什么意思,自行百度
img_encode = cv2.imencode('.jpg',img,[cv2.IMWRITE_JPEG_QUALITY, 99])

对应的解码和打开

img_decode = cv2.imdecode(img_encode, cv2.IMREAD_COLOR)
cv2.imshow("photo",img_decode)
cv2.waitkey(0)

tcp协议数据传输限制

tcp协议里面规定我们一次最多只能传输1024bytes(字节)的数据,但对于一张图片来说1024bytes实在是太少了,所以我们得分批传过去,然后再分批接收,但接收方如何知道到底要接收几个字节的数据呢?答案是定义一个结束标志位,这听起来是个麻烦的过程,但代码执行起来确十分轻松。
请看例程:

#发送端,发送字节长度+结束标志位
flag_data = (str(len(bytedata))).encode() + "end".encode()

解释一下,对于太大的数据,接收端必须先知道要即将会接收几个字节的数据,然后再开始进行内容的接收,而且发送的数据必须经过编码,至于为什么,这里不做探究。所以(str(len(bytedata)))代表即将发送的数据的长度,"end"为结束标志位。这里有点绕哈,不过理解了这个接下来的东西就没问题了。

#接收端,解码并且获取字节长度
flag = flag_data.decode().split("end")[0]
total = int(flag)

正式编成的一些重要板块

接下来的逻辑是:一:接收端到知道即将要接收多少个字节,做好准备,告诉发送端可以发送正式的数据(图片数据)了
二:发送端接收到可以发送的信号,开始发送数据。

#接收端
tcp.send(b"ok")
count = 0 
end_data = b""            #定义一个存储字节流的变量
while count < total:
	data = tcp.recv(1024)
	end_data += data           #end_data就是最终的图片数据
	count += len(data)
#为了能在Nms内发送N张图片,修改一下上面的读取程序
count = 0
temp = 1024
while count < total:
	data = tcp.recv(temp)
	end_data += data
	count += len(data)
	if (count+1024) > total:
		temp = total - count       #防止读取到下一次数据的包头

依旧啰嗦一下,TCP都是以字节流的形式进行传输的,所以end_data得到的是完整图片的字节流形式,我们解码之后才可以使用。但是opencv只能解码uint8格式的数据,所以我们还需要先将其转化为为uint8格式的数据。

#接收端解码
#字节流->uint8格式->opencv解码->完整图像
img = np.asarray(bytearray(end_data), dtype="uint8")   
img = cv2.imdecode(img, cv2.IMREAD_COLOR)

这个地方与我最开始说的解码编码不同,因为最开始没有把字节流传输这一块包含进去,cv2.imencode()出来的图像还不是字节流。所以真实的编码应当是这样的:

#发送端编码
img = cv2.imread("D:/pp-ocr/PaddleOCR/train_data/text_trian/1.jpg")
img_encode = cv2.imencode('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 99])[1] 
byte_data = img_encode.tobytes() #转化为字节流

ok,讲到这里大家也大概成功混乱了吧,待我都讲完为大家理清思绪。在上面我提到
“发送端接收到可以发送的信号,开始发送数据”
我们来看看它的代码:

#发送端接收到ok的信号,开始发送数据
if ("ok" == rec.decode()):   
    socket_tcp.send(byte_data)

理清思绪,就参考这篇文章咯

https://blog.csdn.net/qq_42688495/article/details/108279618

最后也附上这两天刚看到的文章,可以一次性传输图片。

https://blog.csdn.net/qq_24282081/article/details/106498871

  • 11
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__TAT__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值