当前位置: 首页 > news >正文

RK3588——网口实时传输视频

由于通过流媒体服务器传输画面延迟太高的问题,不知道是没有调试到合适的参数还是其他什么问题。诞生了这篇博客。

RK3588板端上接摄像头,采集画面,通过网口实时传输给上位机并显示。

第一代版本

RK3588代码
import cv2
import socket
import struct# 配置
SERVER_IP = '192.168.137.1'  # 上位机的IP地址
PORT = 5000  # 端口号# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 打开摄像头
cap = cv2.VideoCapture(23)if not cap.isOpened():print("无法打开摄像头")exit()while True:# 读取摄像头帧ret, frame = cap.read()if not ret:print("无法读取帧")breakframe = cv2.resize(frame,(320,240))# 对帧进行编码encoded, buffer = cv2.imencode('.jpg', frame)if not encoded:print("编码帧失败")break# 发送数据data = buffer.tobytes()print(len(data))print(len(struct.pack('L', len(data))))print(struct.pack('L', len(data)))# 发送数据大小client_socket.sendto(struct.pack('L', len(data)), (SERVER_IP, PORT))# 发送数据client_socket.sendto(data, (SERVER_IP, PORT))# 释放资源
cap.release()
client_socket.close()

上位机代码(windows系统)

import cv2
import socket
import numpy as np# 配置
PORT = 5000  # 端口号# 创建一个socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', PORT))# 创建窗口并设置为全屏模式
cv2.namedWindow('Video Stream', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('Video Stream', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)while True:# 接收数据大小data_size, _ = server_socket.recvfrom(8)# 接收的视频数据长度data_size = int.from_bytes(data_size, byteorder='little')# 接收视频数据data, _ = server_socket.recvfrom(data_size)# 解码np_data = np.frombuffer(data, dtype=np.uint8)frame = cv2.imdecode(np_data, cv2.IMREAD_COLOR)if frame is None:print("解码帧失败")continue# 显示帧cv2.imshow('Video Stream', frame)if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
server_socket.close()
cv2.destroyAllWindows()

测试视频

遗留问题:视频每帧只能一次传输完毕,且每帧的大小不能过大,不然会报错。

第二代版本

通过分组发送帧图像的方式,即segment_size,优化了帧图像必须要一次传输的问题。

并且把b'\xff\xff'当作一帧画面传输完成的表中,暂时还没发现什么问题。

RK3588代码
import cv2
import socket# 配置
SERVER_IP = '192.168.137.1'  # 上位机的IP地址
PORT = 5000  # 端口号# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 打开摄像头
cap = cv2.VideoCapture(23)if not cap.isOpened():print("无法打开摄像头")exit()frame_count = 0
segment_size = 65000 #32678 # 一组数据的大小
while True:# 读取摄像头帧ret, frame = cap.read()if not ret:print("无法读取帧")break# 对帧进行编码encoded, buffer = cv2.imencode('.jpg', frame)if not encoded:print("编码帧失败")break# 发送数据data = buffer.tobytes()data_len = len(data) # 一帧图像的数据大小print(data_len)# 发送数据time = data_len // segment_size # 需要发多少组left = data_len % segment_size # 剩下多少个if time > 0:for i in range(time): # 遍历发送所有的组start_pos = i*segment_size end_pos = (i+1)*segment_sizeclient_socket.sendto(data[start_pos:end_pos], (SERVER_IP, PORT))# 发送剩下的,并且加上结束帧标识符client_socket.sendto(data[time*segment_size:data_len] + b'\xff\xff', (SERVER_IP, PORT))frame_count +=1
# 释放资源
cap.release()
client_socket.close()
上位机代码(windows系统)

 

import cv2
import socket
import numpy as np# 配置
PORT = 5000  # 端口号# 创建一个socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', PORT))
# 一组数据的大小
segment_size = 65000 #32678while True:data_byte = b''# 接收视频数据data, _ = server_socket.recvfrom(segment_size)while (b'\xff\xff' not in data):data_byte += datadata, _ = server_socket.recvfrom(segment_size)# 把分组发送的字节相加data_byte += data#去除最后两个结束帧标识符rev_data = data_byte[:-2]# 解码np_data = np.frombuffer(rev_data, dtype=np.uint8)frame = cv2.imdecode(np_data, cv2.IMREAD_COLOR)if frame is None:print("解码帧失败")continue# 显示帧cv2.imshow('Video Stream', frame)if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
server_socket.close()
cv2.destroyAllWindows()

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 什么是深拷贝
  • ubuntu20 vmware硬盘空间不够,进行扩容,实操成功!
  • 通俗易懂 serverless 架构、微服务架构和云原生架构,并简单代码
  • UltraISO制作Centos7.X系统U盘启动
  • 2024年入职/转行网络安全,该如何规划?_网络安全职业规划
  • Docker的介绍、保姆级安装和使用
  • 数据库学习(进阶)
  • LoginFormDTO
  • iOS18 Beta7 最终测试版推送:苹果的又一次技术飞跃
  • HTTP 之 HTTP/1.0、HTTP/1.1和HTTP2的缓存策略(六)
  • [数据集][目标检测]起子检测数据集VOC+YOLO格式1215张1类别
  • 在Excel中“直接引用”字符串地址
  • 【实战教程】用scikit-learn玩转KNN:鸢尾花数据集的分类之旅
  • leetcode371. 两整数之和,位运算
  • Git介绍及配置
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • [译]前端离线指南(上)
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • java 多线程基础, 我觉得还是有必要看看的
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JavaScript异步流程控制的前世今生
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Shell编程
  • Terraform入门 - 3. 变更基础设施
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 订阅Forge Viewer所有的事件
  • 和 || 运算
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 微信支付JSAPI,实测!终极方案
  • 协程
  • 优化 Vue 项目编译文件大小
  • 由插件封装引出的一丢丢思考
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (二)测试工具
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (转)linux 命令大全
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET IoC 容器(三)Autofac
  • .NET 材料检测系统崩溃分析
  • .NET 读取 JSON格式的数据
  • .net 设置默认首页
  • .NET8 动态添加定时任务(CRON Expression, Whatever)
  • .Net面试题4
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • ::
  • :如何用SQL脚本保存存储过程返回的结果集
  • @DataRedisTest测试redis从未如此丝滑