前提:
之前写过一个基于imagezmq的方式实现基于python的视频流推送python局域网视频推送,配合frp进行外网访问_陆志鹏的博客-CSDN博客局域网视频推流,外网访问局域网视频https://blog.csdn.net/qq_23607397/article/details/127296165?spm=1001.2014.3001.5502
优点:实现简单,稳定
缺点:无法进行双向视频流的传输,在其它机器上只能看到发送端的经过处理的视频流
优化:
为了满足双向视频流传输
实现在一个配置较低的设备上负责视频的拉取,将算法等对设备要求较高的功能放在服务端。
本文章充分利用了grpc的特性,实现了再没有gpu的低配置的设备上,直接调用服务端的函数,完成低配置设备的图像识别和展示
gRPCA high performance, open source universal RPC …https://grpc.io/有兴趣的同学可以去这个网站深入学习下grpc的相关用法,在这里我就不做过多的叙述
客户端应用程序可以像本地对象一样直接调用不同机器上的服务器应用程序上的用法
实现:
pip install DXR -U
由于grpc的实现还是比较繁琐的,我在我自己的库中进行了一些简单的封装,方便大家将更多的精力放在算法的开发上
首先我们在高配置机器上写一个服务器代码
from Dxr_grpc.dxr_grpc_server import Dxr_grpc_server
import cv2
def callbck(dst, json_data):
# json_data的格式为:
# {
# "type": "face // 人脸识别",
# }
if json_data['type'] == 'face':
# 模拟人脸识别
cv2.rectangle(dst, (100, 100), (200, 200), (0, 0, 255), 2)
cv2.putText(dst, 'face', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
elif json_data['type'] == 'object':
# 模拟物体识别
cv2.rectangle(dst, (100, 100), (200, 200), (0, 255, 0), 2)
cv2.putText(dst, 'object', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 返回处理后的图像和识别结果
return dst, json_data
# 启动grpc服务,port为grpc服务端口,默认为50051,rec_callback为识别回调函数
server = Dxr_grpc_server(rec_callback=callbck)
server.run()
下面我们来实现一个客户端,代码如下
from Dxr_grpc.dxr_grpc_client import Dxr_grpc_client
import cv2
# 初始化客户端,ip和端口号
dxr_client = Dxr_grpc_client('127.0.0.1', "50051")
cap = cv2.VideoCapture(0)
json_data = {
'type': 'face',
}
while True:
ret, frame = cap.read()
if ret:
# 调用get_response方法,获取处理后的图像
res = dxr_client.get_response(frame, json_data)
# res是一个生成器,可以通过for循环获取处理后的图像
for i in res:
frame = i['dst']
cv2.imshow('frame', frame)
k = cv2.waitKey(1)
# 根据按键选择不同的处理方式
if k == ord('q'):
break
elif k == ord('f'):
json_data['type'] = 'face'
elif k == ord('m'):
json_data['type'] = 'object'
cap.release()
运行下可以看下效果,我这边服务端实现了一些简单的算法,下面可以看下效果
使用笔记本的摄像头测试了整体的延迟,局域网内使用,和直接在本地调取摄像头视频流几乎没有差别,基本上感觉不到延迟,广域网中,配合zerotier的方式进行局域网组网后,测试也几乎没什么延迟,占用带宽目前还没去测试,后续会针对于延迟和所占带宽进行一个系统的测试