实时传输视频流
-
客户端需要的做的是连接服务端然后读摄像头数据发送给服务端需要注意的是服务器的IP地址需要注意一下,这里用的是服务端的IP地址,(这里使用的是树莓派5在服务端)
-
#以下是客户端程序 import socket import struct import time import traceback import cv2 import numpy class Client(object): """客户端""" def __init__(self, addr_port=('192.168.149.1', 11000)): # 连接的服务器的地址 # 连接的服务器的端口 self.addr_port = addr_port # 创建套接字 self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 地址端口可以复用 self.client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 分辨率 self.resolution = (640, 480) def connect(self): """链接服务器""" try: self.client.connect(self.addr_port) return True except Exception as e: traceback.print_exc() # 打印原始的异常信息 print('连接失败') return False def send2server(self): """读摄像头数据 发送给服务器""" camera = cv2.VideoCapture(0) # 摄像头对象 print('isOpened:', camera.isOpened()) while camera.isOpened(): try: # 获取摄像头数据 ret, frame = camera.read() # 对每一帧图片做大小处理 和大小的压缩 frame = cv2.resize(frame, self.resolution) # 参1图片后缀名 参2 原图片的数据 参3图片质量 0-100 越大越清晰 ret, img = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 100]) # img 是被压缩后的数据 无法正常显示 print(img) print('-------------') print(img.tostring()) # 转换为numpy格式数据 img_code = numpy.array(img) # 转为二进制数据 img = img_code.tostring() # 获取数据长度 length = len(img) # 发送的数据 大小 宽 高 图片数据 # 数据打包变为二进制 # pack方法参数1 指定打包数据的数据大小 i 4字节 h代表2字节 all_data = struct.pack('ihh', length, self.resolution[0], self.resolution[1]) + img self.client.send(all_data) time.sleep(0.01) except: camera.release() # 释放摄像头 traceback.print_exc() return if __name__ == '__main__': client = Client() if client.connect(): client.send2server()
服务端:在运行的时间需要先运行服务端在运行客户端
import socket import struct import threading import cv2 import numpy import os class Server: def __init__(self): # 设置tcp服务端的socket self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置重复使用 self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定地址和端口 self.server.bind(('192.168.149.1', 11000)) # 设置被动监听 self.server.listen(128) def run(self): while True: print('等待客户端连接') # 等待客户端连接 client, addr = self.server.accept() ProcessClient(client).start() class ProcessClient(threading.Thread): def __init__(self, client): super().__init__() self.client = client self.i = 0 # 初始化i的值 # 获取文件夹中图片序号最大的值 path = "D:/sample" file_list = [] for root, dirs, files in os.walk(path, topdown=False): # 确保files是当前目录下的文件列表 for file in files: if file.endswith(('.png', '.jpg', '.jpeg')): # 只处理图片文件 file_number = int(file.split('.')[0]) # 假设文件名是数字和图片扩展名组成 file_list.append(file_number) if len(file_list) == 0: self.i = 0 else: file_list.sort() self.i = file_list[-1] + 1 def run(self): while True: data = self.client.recv(8) if not data: break # 图片的长度 图片的宽高 length, width, height = struct.unpack('ihh', data) imgg = b'' # 存放最终的图片数据 while length: # 接收图片 temp_size = self.client.recv(length) length -= len(temp_size) # 每次减去收到的数据大小 imgg += temp_size # 每次收到的数据存到img里 # 把二进制数据还原 data = numpy.fromstring(imgg, dtype='uint8') # 还原成矩阵数据 image = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) print(image) cv2.imshow('capture', image) # 保存图片 k = cv2.waitKey(1) if k == ord('k'): cv2.imwrite(r"F:\sample\\" + str(self.i) + ".jpg", image) # 存储路径 self.i = self.i + 1 print(self.i) # time.sleep(5) if k == ord('q'): break if __name__ == '__main__': server = Server() server.run()
以下是效果:
-