利用socket和opencv搭建局域网图传

利用socket和opencv搭建局域网图传,第1张

目录
  • 前言
  • socket
    • makefile
  • cv2
    • cv2.imencode()
    • cv.imdecode()
  • 测试照片:
  • 代码

前言

1、由于树莓派用YOLOv5做识别检测帧率太慢了,所以想将树莓派拍的图像传到电脑进行识别。


因此所有搭建一个图传工程。


2、别人有做过使用socket、cv2、picamera做的一个图传,客服端是一定要在pi(即树莓派)运行才可以,因为picamera是树莓派的一个专用库,其他地方用不了。


下面是用picamera做的图传
树莓派/PC实现实时摄像头数据共享(Python—picamera)

我的代码是基于这个改的,里面的一些语句我也还没弄懂。


3、因为我想先在Win对Win下试试效果怎么样,所以我需要客服端也是使用cv2进行图像拍摄,但后来发现网上并没有这样的工程,所以只能自己琢磨。


socket

socket是套接字编程库,用于网络服务的,是python的一个标准库,学起来比较容易,有很多教程。


这里不详细说,说一下我在这个库遇到的问题。


makefile

1、这个是socket用于传输二进制流数据的,注意它传输的是二进制,而cv2拍的不是二进制数据,我们需要将图片数据frame转换成二进制才可以

cv2

cv2获得图片数据:

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/569830.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存