- 前言
- socket
- makefile
- cv2
- cv2.imencode()
- cv.imdecode()
- 测试照片:
- 代码
1、由于树莓派用YOLOv5做识别检测帧率太慢了,所以想将树莓派拍的图像传到电脑进行识别。
因此所有搭建一个图传工程。
2、别人有做过使用socket、cv2、picamera做的一个图传,客服端是一定要在pi(即树莓派)运行才可以,因为picamera是树莓派的一个专用库,其他地方用不了。
下面是用picamera做的图传
树莓派/PC实现实时摄像头数据共享(Python—picamera)
我的代码是基于这个改的,里面的一些语句我也还没弄懂。
3、因为我想先在Win对Win下试试效果怎么样,所以我需要客服端也是使用cv2进行图像拍摄,但后来发现网上并没有这样的工程,所以只能自己琢磨。
socket是套接字编程库,用于网络服务的,是python的一个标准库,学起来比较容易,有很多教程。
这里不详细说,说一下我在这个库遇到的问题。
1、这个是socket用于传输二进制流数据的,注意它传输的是二进制,而cv2拍的不是二进制数据,我们需要将图片数据frame转换成二进制才可以
cv2cv2获得图片数据:
ret, frame = camera.read()
cv2.imencode()
这是cv2库里面用于.jpg数据编码的函数:
img_encode = cv2.imencode('.jpg', frame) // 编码
data_encode = np.array(img_encode) // 将编码后的数据转换为二进制数据
就是将frame转换成二进制数据了,data_encode就可以直接用于makefile.write()
cv.imdecode()是用于解码的,编码之后想用肯定要解码是吧。
image = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
这个其实是将两个语句合并了:
np.frombuffer(jpg, dtype=np.uint8) // 将二进制数据转换成编码数据,就是相反的一个过程。
获取编码的数据后,给解码函数解码出图片数据。
服务端:
import numpy as np
import cv2
import socket
h = socket.gethostbyname(socket.gethostname())
p = 8000
class VideoStreamingTest(object):
def __init__(self, host, port):
self.server_socket = socket.socket()
self.server_socket.bind((host, port))
self.server_socket.listen(0)
self.connection, self.client_address = self.server_socket.accept()
self.connection = self.connection.makefile('rb')
self.host_name = socket.gethostname()
self.host_ip = socket.gethostbyname(self.host_name)
self.streaming()
def streaming(self):
try:
print("Host: ", self.host_name + ' ' + self.host_ip)
print("Connection from: ", self.client_address)
print("Streaming...")
print("Press 'q' to exit")
# need bytes here
stream_bytes = b' '
while True:
msg = self.connection.read(1024)
stream_bytes += msg
first = stream_bytes.find(b'\xff\xd8')
last = stream_bytes.find(b'\xff\xd9')
if msg == b'exit':
break
if first != -1 and last != -1:
jpg = stream_bytes[first:last + 2]
stream_bytes = stream_bytes[last + 2:]
image = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
cv2.imshow('image12', image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
except:
print("Error")
finally:
self.connection.close()
# self.server_socket.close()
if __name__ == '__main__':
# host, port
print("host:", h)
print("开始图传:")
while True:
VideoStreamingTest(h, p)
客服端:
import io
import socket
import struct
import time
import cv2
import numpy as np
camera = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
# create socket and bind host
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.239.2', 8000)) // 修改为服务端运行输出的地址就行
connection = client_socket.makefile('wb')
start = time.time()
stream = io.BytesIO()
try:
while True:
ret, frame = camera.read()
img_encode = cv2.imencode('.jpg', frame)[1]
data_encode = np.array(img_encode)
stream.write(data_encode)
connection.write(struct.pack(', stream.tell()))
connection.flush()
stream.seek(0)
connection.write(stream.read())
if time.time() - start > 100:
break
stream.seek(0)
stream.truncate()
connection.write(struct.pack(', 0))
finally:
msg = 'exit'
client_socket.send(msg.encode('utf-8'))
connection.close()
client_socket.close()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)