技术标签: android
yuv420数据快速裁剪
最近碰到一个项目需求,这个项目是两年多年已经量产的项目,这是一个车载后视镜项目,当时配置的后视摄像头是确定的,也就是说这个后视摄像头是厂家定制出去的,当时研发在做倒车显示的时候,显示的画面是完整的裸数据,没有裁剪过,也就是后视摄像头出来的CVBS数据是N制式的时候就是720X480的原始数据来显示的。
但是最近又接到一个需求,就是这个项目的机器可能会作为周转机器装到适合别的项目产品的车上,也就是配置的后视摄像头是不一样的,因此就会出现一些差异,在测试中发现最左边有一条白线,这是这种后视摄像头的原始数据出了问题,因此需要在现实的时候把数据给裁剪掉。
首先我们这种CVBS数据通过主控芯片上来后都是一种8位的YUV420数据,也就是Y数据存放在一起是连续的,UV数据放在一起也是连续的,按照这种格式也就是说每个像素点Y值是一个字节,对于UV数据是每两个像素点存储一个字节的数据,也就是说对应Y数据是减半的。其实裁剪也很简单,本来是可以利用CPU之外的另外加速器来处理的,因为是一个早期项目,早点完工解决问题就可以了,因此在CPU运算量富足的情况下采用了用CPU来裁剪,裁剪方法如下:
+
+ {
+ int heightcunt = 0;
+ int heightUVcunt = 0;
+ int newWidth =0 ;
+ int cropStartX;
+ int srcWidth;
+ int srcHeight;
+ int cropHeight;
+
+ cropStartX = 16;//裁剪左边多少个像素
+ if (mSystemType == 0) {//NTSC制式
+ srcWidth = 720;//裁剪前的原始宽度
+ cropHeight = 480;//裁剪后的高度
+ srcHeight = 480; //裁剪前的原始高度
+ } else {//PAL制式
+ srcWidth = 720;
+ cropHeight = 576;
+ srcHeight = 576;
+ }
+ newWidth = srcWidth - cropStartX;
+
+ for( heightcunt = 0; heightcunt < cropHeight; heightcunt++){
+ memcpy((void *)(v4l2_buf.addrVirY + newWidth*heightcunt),
+ (const void*)(v4l2_buf.addrVirY + cropStartX + srcWidth*heightcunt), newWidth);
+ }//addrVirY 存放Y数据的内存地址
+
+ for( heightUVcunt = 0; heightUVcunt < cropHeight; heightUVcunt++){
+ memcpy((void *)(v4l2_buf.addrVirY + newWidth*cropHeight + newWidth*heightUVcunt/2),
+ (const void*)(v4l2_buf.addrVirY + srcWidth*srcHeight+cropStartX/2 + srcWidth*heightUVcunt/2), newWidth/2);//Y数据之后就是UV的数据,他们是连续的,因此可以这样UV接着Y的数据顺序存放。
+ }
+ }
通过以上一个简单的运输把原始数据做了重新的排布组合,完成了项目需求。对于这种老项目的需求开发,有时是难免的,因此在考虑软件功能设计的时候尽量考虑扩展性。市场需求变化,公司管理市场的能力也各有不同,往往技术成为解决市场奇葩需求的最终方法,有时候你的老板同事觉得可能这样的改变很容易,实际上做这种事真的是人在江湖、身不由己,这种事做多了好累。程序员说设计的时候你考虑好兼容性、扩展性啊,实际上在很多项目上不是不考虑,而是当时的项目需求非常明确,给你的时间精力也是有限的,因此在满足了项目需求的情况下,多数时候都会够用就好。这种建议教训告诉我们,在精力许可的情况下尽可能多考虑一下这种多变性。
文章浏览阅读4.3k次。添加一行为列求和_dataframe添加一行数据不改变索引
文章浏览阅读86次。#include <iostream>#include <algorithm>#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>#include <string>#include <queue>#include <stack>#include <map>#include <se
文章浏览阅读3.6k次,点赞8次,收藏35次。目录一.cin的常见读取方法Ⅰ.cin>>Ⅱ.cin.get()Ⅲ.cin.getline()二.从标准输入读取一行字符串的其它方法Ⅰ.getline()Ⅱ.gets()一.cin的常见读取方法Ⅰ.cin>>cin 可以连续从键盘读取想要的数据,以空格、tab 或换行作为分隔符。当 cin>> 从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或..._cin的成员函数
文章浏览阅读3.9k次。html代码:ion-infinite-scroll on-infinite="appendBike()" distance="1%" immediate-check="false" ng-if="moreDataCanBeLoaded()">ion-infinite-scroll>js代码:apendBike:/** * @动态加载函数 */function _数据不够时如何停止v-infinite-scroll
文章浏览阅读1.1k次。str2 = '1234567890'str3 = '你好啊我是'len(str2.encode('gbk'))len(str3.encode('gbk'))> 10> 10差不多了。_python如何获取字号的长和宽
文章浏览阅读712次。网上有一些安装Alcatraz的命令行 执行以后都没有效果,去了它在github主页上拷贝了下面两个代码。这两天试着使用Xcode的 一些插件管理工具,自己记录一下。用的是Alcatraz,这个是github上的一个开源项目,用来管理Xcode上的插件。有搜索功能,界面也很人性化。在终端上输入如下命令即可完成安装:curl -fsSL https://raw_xcode 注释对齐
文章浏览阅读2.2k次,点赞3次,收藏9次。问题说明:新建mdk工程时第一步是选芯片(以STM32F103ZE为例),但是芯片没有的话需要自己手动添加,如图:解决方法:下载KEIL MDK5以后是没有安装device的,如果此时创建工程会找不到目标芯片,如下图所示:此时我们就要安装自己需要的芯片系列,比如STM32F1系列。首先选择Project-Manage-Pack Installer如下图所示:..._stm32f103ze芯片
文章浏览阅读483次。ICodingRule codingRule = CodingRuleFactory.getLocalInstance(ctx);ICodingRuleManager codingRuleManager = CodingRuleManagerFactory.getLocalInstance(ctx);CodingRuleInfo codingInfo = codingRule.getCodingRuleInfo("where id='6InSdpiUSAGKghKCKHJO3vimVMM='");/_服务端的 coderulebuilder 组件根据这些配置信息生成指定编码,他的具体的生成编码
文章浏览阅读5.5k次。1、查询所有节点及关系: MATCH (n)returnn2、查询指定类型节点: MATCH(h:Helo),(m:Mailfrom)returnh,mn,h,m都是随意的,可以理解为变量_neo4j查询语句
文章浏览阅读3.8w次。git推代码报错&quot;you do not have permission to push to the repository via HTTPS&quot;问题描述:使用git提交代码时报错,如图下:意思是: 通过https推代码没有权限解决办法:情况一: 有可能是没有推代码的权限解决方法: 你可以git pull 拉取一下代码,如果能拉取,不能推就是权限问题,请找公司其他人帮你开通权限..._you do not have permission to push to 'enterprise__asm1/ams' via ssh
文章浏览阅读3.2k次,点赞6次,收藏18次。一、概述大家好,很高兴能跟大家一起分享深度学习的课程,本课程基于RK3399ProD的人工智能开发板,简单介绍深度学习领域的相关内容,在后面的课程会加入实际项目的内容,以常见的实际项目为例,更能让初学者或企业直接入手,同时缩短产品的研发周期。分享这个课程内容,也是能够让我们对AI领域的研究更接地气,不过因为也是第一次写这样的课程,如果有缺陷,也请各位大佬们不吝支持一下,谢谢!开发板采用了高..._rk3399 rk3399pro
文章浏览阅读590次,点赞5次,收藏5次。Java数据库管理JDBC和数据库连接池的介绍与使用【内含jar与配置文件】_java面向对象编程 连接数据库