视频采集到录制 - 采集到显示碰到一些难点

news2025/1/21 20:22:49

项目中用到相机后端处理,走了一些弯路,也遇到不少问题(解决了不少问题),特意写下本文记录下当时点点滴滴。

讲一下背景,公司自研相机,用于一些高端场合,因此对后端处理也非常讲究

采集-显示 基本方案:

  1. 前端模拟信号(BNC)
  2. PCIE采集图像
  3. 应用层通过PCIE采集卡(驱动)获取YUV图像
  4. YUV转码BGR
  5. BGR进行OSD叠加
  6. BGR显示到UI

方案很简单,也很常规一种解决办法,但仍然碰到许多问题

 

1. 首先采集端

        最初方案是USB采集卡,网购号称USB3.0采集卡,实测发现根本达不到3.0,后来拆开来看,外面接口是USB3.0,但里面转接是2.0,因此做不到。

        后来采用采集到HDMI 然后再HDMI - USB3.0采集卡,虽然可以达到,但延时、占用CPU资源大的问题很突出。

        又考虑到主板是ARM方案,因此,还是PCIE的方式比较靠谱(成本高),多路也方便

        为什么非要USB3.0?1080p*25的带宽,2.0明显不够(只能跑10帧)

2. YUV-转BGR编码

转码很好理解,但是考虑到性能,绝对不可以用CPU,

        最佳办法使用RGA(rk的解决办法),也占资源,但好在还可以接受

由于1080不是16倍数(一开始不知道这个原因),因此也搞了好久

测试640、720都没问题,1080就不行,以为是性能问题

而且,官方虽然有demo,但可复杂了,如果仅仅是rga转码,只要一点点代码就够了

int RgaConvert::YuvToRgb(uint8_t *srcBuf, uint32_t w,uint32_t h, uint8_t *dstBuf)
{
    int srcFormat = RK_FORMAT_YUYV_422;
    int dstFormat = RK_FORMAT_BGR_888;

    rga_info srcInfo,dstInfo;

    memset(&srcInfo, 0, sizeof(rga_info_t));
    srcInfo.fd = -1;
    srcInfo.mmuFlag = 1;

    memset(&dstInfo, 0, sizeof(rga_info_t));
    dstInfo.fd = -1;
    dstInfo.mmuFlag = 1;

    rga_set_rect(&srcInfo.rect,0,0,w,h,w,h,srcFormat);
    rga_set_rect(&dstInfo.rect,0,0,w,h,w,h,dstFormat);

    //图像翻转也可以这里做,但会增加CPU

    srcInfo.virAddr = (void *)srcBuf;
    dstInfo.virAddr = (void *)dstBuf;
    mRkRga.RkRgaBlit(&srcInfo, &dstInfo, NULL);

    return 0;
}

3. OSD叠加

OSD叠加也是个大学问,简单叠加当然简单,但是但是,

        考虑到图像背景,叠加颜色怎么处理也是个麻烦地方

首先,你得有图像数据传进来

其次,然后要计算图像数据的灰度(总不能取中心点,也不能去全部点,然后每帧都要计算吗?显然每秒计算一次也足够了),

。。。有了背景的灰度,此时,还要考虑临界点(比如128以上是白色,如果实际刚好是127-129来回切换,那不是每次都得切换颜色?这样效果也不好:肉眼看起来没有变化的,实际却在切换颜色);还有如果字符很长,那么背景灰度也很讨厌(一个一个字符去计算?还是,显然一个个字符去计算比较合理点)

最后,是否可以考虑描边?可以,但很丑(也非常占资源),且logo图标方式也很难支持描边

        这里涉及到很多参数,算法,需要慢慢去优化,调整,也很辛酸

/*计算灰度*//*斜线方向*/
uint32_t Osd::CalculateGray(const uint8_t *rgb,const QRect &rect,int base,bool w2b)
{
    uint32_t countGray = 0;
    /*y轴检测16像素*/
    int yStep = (rect.height() > 16) ? (rect.height() / 16) : 1;
    int xStep = (rect.width() > 16) ? (rect.width() / 16) : 1;

    int32_t tY = rect.y();
    for(int32_t j = 0; j < 16; j++)
    {
        int32_t start = (tY * VIDEO_WIDTH + rect.x() + j * xStep) * 3;
        uint8_t gray = (uint8_t)((19595 * rgb[start] + 38469 * rgb[start+1]  + 7472 * rgb[start+2]) >> 16);
        if(w2b)
        {
            countGray += ((gray > base) ? 1 : 0);
        }
        else
        {
            countGray += ((gray < base) ? 1 : 0);
        }
        tY += yStep;
    }

    //countGray = countGray >> 8;
    return countGray;
}

4. 内存交互问题

        采集端获取是YUV,是个内存,然后转码成BGR,此时又得一个内存

        肯定存在内存拷贝问题

        后面还有大的环节:OSD叠加、H264编码源、显示UI,这些都是需要内存的

        如果每个环节各管各的(强解耦),虽然流程简单了,但每次都是拷贝,性能非常受限

        因此设计一个内存自动管理机制(类似智能指针或许是个好的解决办法)

5. 显示问题

        双缓冲?等等,如何快速,如何不影响其他流程,等等也是很头疼的问题

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/527277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络基本知识分享

目录 1.IP地址 2.端口号 3.协议 4.协议分层 5.Tcp/Ip五层网络模型 5.1 应用层 5.2 传输层 5.3 网络层 5.4 数据链路层 5.5 物理层 6.封装和分用 6.1 封装 6.1.1 应用层拿到数据 6.1.2 向下传递给传输层 6.1.3 继续向下传递给网络层 6.1.4 继续向下传递给数据链…

【自制视频课程】C++OpnecV基础35讲——第一章 前言

为什么要学习OpenCV&#xff1f; 首先&#xff0c;opencv是一个广泛使用的计算机视觉库&#xff0c;它提供了丰富的图像处理和计算机视觉算法&#xff0c;可以帮助我们快速地开发出高质量的图像处理应用程序&#xff1b; 其次&#xff0c;opencv是一个开源库&#xff0c;可以免…

Spark大数据处理讲课笔记4.3 Spark SQL数据源 - Parquet文件

文章目录 零、本讲学习目标一、Parquet概述二、读取和写入Parquet的方法&#xff08;一&#xff09;利用parquet()方法读取parquet文件1、读取parquet文件2、显示数据帧内容 &#xff08;二&#xff09;利用parquet()方法写入parquet文件1、写入parquet文件2、查看生成的parque…

零入门kubernetes网络实战-32->基于路由技术+brigde+veth pair形成的跨主机通信方案

《零入门kubernetes网络实战》视频专栏地址 https://www.ixigua.com/7193641905282875942 本篇文章视频地址(稍后上传) 本文主要使用的技术是 路由技术Linux虚拟网桥虚拟网络设备veth pair来实现跨主机通信 该方案是flannel网络方案中的host-gw网络模型的基础。 1、总结 本…

化制为智,驭数前行 | 如何把握油气装备领域智能制造的未来?

01「智」赋未来&#xff0c;油燃而升 2015年&#xff0c;我国提出了“中国制造2025”规划&#xff0c;把智能制造作为两化深度融合的主攻方向&#xff0c;智能制造产业链所蕴藏的巨大投资机会将逐渐被市场挖掘。作为国家战略的基础&#xff0c;油气工程装备&#xff0c;特别是…

C++ 基础STL-list容器

STL-list 容器&#xff0c;又称双向链表容器&#xff0c;即该容器的底层是以双向链表的形式实现的。这意味着&#xff0c;list 容器中的元素可以分散存储在内存空间里&#xff0c;而不是必须存储在一整块连续的内存空间中。 链表的优点&#xff1a;可以对任意位置进行快速插入和…

【触觉智能分享】RK3568+Debian系统如何旋转屏幕显示方向

大家在购买开发板后&#xff0c;默认开机进入桌面屏幕显示方向是竖屏&#xff0c;有些用户想修改为横屏显示&#xff0c;本文就用IDO-EVB3568为例&#xff0c;用Debian系统演示如何旋转屏幕显示方向&#xff0c;此方法适用于所有RK356X系列产品。 IDO-EVB3568开发板拥有四核A5…

【数据结构】--- 几分钟走进栈和队列(详解-上)

文章目录 前言&#x1f31f;一、栈&#x1f30f;1.1栈的概念及结构&#xff1a;&#x1f30f;1.2实现栈的两种方式&#xff1a; &#x1f31f;二、栈实现(数组栈)&#x1f30f;2.1结构&#xff1a;&#x1f30f;2.2初始化&#xff1a;&#x1f4ab;2.2.1第一种代码&#xff1a;…

Direct3D 12——纹理——纹理贴图的作用

法线贴图 在不增加三角形的情况下增加表面细节 任何一个像素它的法线都做一个扰动&#xff0c;通过定义不同的高度和临近位置的高度差重新计算法线 纹理定义的是任何一个点&#xff0c;它的相对的高度的移动&#xff0c;通过高度的变化改变法线 原曲面法向量n ( p) (0,1) p点…

代码随想录 LeetCode链表篇 Java

文章目录 &#xff08;简单&#xff09;203. 移除链表元素&#xff08;中等&#xff09;707. 设计链表&#xff08;简单&#xff09;206. 反转链表&#xff08;中等&#xff09;24. 两两交换链表中的节点&#xff08;中等&#xff09;19. 删除链表的倒数第 N 个结点&#xff08…

Schlumberger ECLIPSE CRACK

Schlumberger ECLIPSE CRACK 工业和工程软件旨在模拟Schlumberger ECLIPSE Simulation的碳氢化合物&#xff0c;该模拟与Shelberger的技术服务有关&#xff0c;以及用于预测和历史的容器中当前方程数量的最新和最新解决方案集。动态行为是各种传统和不寻常的石油和天然气模式。…

DevExpress:报表控件绑定数据库数据源的三种方式(Winform)

1.写在前面 如果你是和我一样&#xff0c;第一次接触DevExpress&#xff0c;并且因为网上资源眼花缭乱无从下手&#xff0c;然后脑子一转直接到DevExpress官网寻找官方使用文档的&#xff0c;那我们的了解顺序应该差不多是一致的。 DevExpress官网&#xff1a;https://www.de…

【笔试强训选择题】Day12.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目录…

Facebook 手机应用广告:在移动时代实现营销突破

在移动时代&#xff0c;手机已经成为人们生活的重要组成部分。随着移动互联网的普及&#xff0c;人们更频繁地使用手机来浏览社交媒体、获取信息和进行购物。 对于企业而言&#xff0c;如何在移动平台上实现营销突破&#xff0c;吸引用户的注意力和提升品牌价值&#xff0c;是…

数说热点|社恐人群运动健身指南:不想去健身房,那就在家找面墙

连杰伦都开始跳操了&#xff0c;你还不动动动动动起来&#xff1f; 随着《运动者联盟》这档体育挑战真人秀节目的完美收官&#xff0c;忙碌生活中的运动激情似乎又被点燃了。5月9日&#xff0c;周杰伦现身厦门&#xff0c;在活动现场和刘耕宏合体跳起了《本草纲目》&#xff0…

音视频技术开发周刊 | 293

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 谷歌全面反攻 ChatGPT&#xff01;PaLM 2、Gemini 双杀&#xff0c;Bard 正式开放 以上是2023 Google I/O 大会的重点内容&#xff0c;AI含量极高。 谷歌推拥有26000个H10…

uni-app框架的小程序开发环境

文章目录 一、下载微信开发工具安装 二、构建uni-app开发环境2.1 Node.js下载与安装2.2 下载HBuilder-X2.3 创建uni-app项目2.4 填入uni-app专属标识和小程序标识 在阅读此博文前&#xff0c;需要注册完毕小程序账号 一、下载微信开发工具 微信开发工具下载地址 下载稳定版即…

代码随想录算法训练营day41 | 343. 整数拆分,96.不同的二叉搜索树

代码随想录算法训练营day41 | 343. 整数拆分&#xff0c;96.不同的二叉搜索树 343. 整数拆分解法一&#xff1a;动态规划 96.不同的二叉搜索树解法一&#xff1a;动态规划 总结 343. 整数拆分 教程视频&#xff1a;https://www.bilibili.com/video/BV1Mg411q7YJ 1、dp[i]代表…

【Linux命令】脚本里常用的几个命令sort,uniq,tr,cut,split,eval

脚本里常用的命令 一、SORT命令1.1、语法格式1.2常用选项 二、uniq命令2.1命令格式2.2常用选项2.3小实验&#xff0c;过滤出现三次以上的IP地址 三、tr命令3.1语法格式3.2常用选项3.3实验 四、cut命令4.1语法格式4.2常用选项 五、split命令5.1语法格式5.2常用选项 六、eval七、…

一个优秀系统构架师应具备的能力

作为软件开发的设计架构师&#xff0c;那么必须拥有一定的编程技能&#xff0c;同时有高超的学习新的架构设计、程序设计技能。另外&#xff0c;我觉得作为软件架构师&#xff0c;还必须了解一定的硬件、网络、服务器的基本知识。要不然&#xff0c;你都不知道有些什么材料可以…