骁龙820A搭载Hexagon 680数字信号处理器(DSP),DSP分为三部分,第一部分负责处理音频、视频、图像、声音输入等,第二部分负责管理手机的低功耗处理器,可以带来语音唤醒的功能.第三部分搭载调制解调器,可以在CPU休眠时启动,减少唤醒CPU的次数。
Hexagon 680 DSP性能显著提升,让CPU减少任务负载量,以更低能耗达到更快的处理速度。Hexagon 680 DSP 还兼顾了“持久续航”的低功耗传感器和超低功耗的高级图像处理功能。
Hexagon 680最大的变化就是支持“Hexagon矢量扩展”,可执行图像处理中的计算量大的部分,例如虚拟现实,视频处理,计算机视觉等,以往CPU/GPU,相对更耗电的任务可以交给DSP更高效的做。
笔者所在公司正好有一个利用820A开发项目,主要是对820A上支持raw data数据的OV5647摄像头进行数据获取和转换。获取和转换在前面的文章已经讲过,有兴趣的可以查看小编该系列的其他文章。本篇主要介绍图像数据的转换原理和具体实现。
raw格式
raw图像是cmos或者ccd图像感应器将捕捉到的光源信号转换成数字信号的原始数据,同时记录由相机拍摄产生的元数据,例如光圈值,白平衡等。raw是未经处理,未经压缩的格式。OV5647的格式分为两种,一种是raw10,另一种是raw8。经过一定条件的考虑,小编所在的项目组成员决定采用raw10的格式。
Raw10转RGB的原理
Raw10就是10bit Raw RGB, 就是说用10bit去表示一个R, G, 或者B, 但是通常平时用的都是8bit的. 所以笔者所在公司在后面处理时都要把10bit的转换为8bit的, 比较简单的方法就是将低两位去掉, 因为低两位的信号代表范围很小(0~3), 所以可以忽略不计的。
每一个像素仅仅包括了光谱的一部分,必须通过插值补偿算法来实现每个像素的RGB值。为了从raw8格式得到每个像素的RGB格式,我们需要通过插值填补缺失的2个色彩。插值的方法有很多(包括领域、线性、3*3等),速度与质量权衡,最好的线性插值补偿算法。
在(a)与(b)中,R和B分别取领域的平均值,在(c)与(d)中,取领域的4个B或R的均值作为中间像素的B值。由于人眼对绿光反应最敏感,对紫光和红光则反应较弱,因此为了达到更好的画质,需要对G特殊照顾(多采集一倍数据G)。所以上述(c)与(d)中扩展开来就如下图所示:
Raw10转RGB的实现和调试
BGbGrRProcess(image3,image1);//按照插值规则转换成RGB,
对于BGGR格式的图像如上图,每个像素值[W,H]
W=0,H=0 B
RGB[0,0] = R11; //R
RGB[0,0] = (G01+G10)>>1; //G
RGB[0,0] = B00; //B
W=0,H=1 G
RGB[0,1] = R11; //R
RGB[0,1] = G01; //G
RGB[0,1] = (B00+B02)>>1; //B
W=0,H=2 B
RGB[0,2] = R11; //R
RGB[0,2] = (G10+G10)>>1; //G
RGB[0,2] = B02; //B
W=0,H=3 G
RGB[0,3] = R11; //R
RGB[0,3] = (G10+G10)>>1; //G
RGB[0,3] = (B01+B03)>>1; //B
W=1,H=0 G
RGB[1,0] = R11; //R
RGB[1,0] = G10; //G
RGB[1,0] = (B00+B02)>>1; //B
void BGbGrRProcess(char *imageRGB,char *imageRaw)
{
int rgbH = 0;
int rgbW = 0;
char *pRGB = imageRGB;
char *pRaw = imageRaw;
for(rgbW=0;rgbW
{
for(rgbH=0;rgbH
{
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3]=pRaw[(rgbH+1)*m_RawW+rgbW];//R
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+1]=BYTE(0.5*(float)pRaw[(rgbH)*m_RawW+rgbW]+0.5*(float)pRaw[(rgbH+1)*m_RawW+rgbW+1]);//G
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+2]=pRaw[rgbH*m_RawW+rgbW+1];//B
}
}
for(rgbW=0;rgbW
{
for(rgbH=1;rgbH
{
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3]=pRaw[rgbH*m_RawW+rgbW];//R
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+1]=BYTE(0.5*(float)pRaw[(rgbH+1)*m_RawW+rgbW]+0.5*(float)pRaw[(rgbH)*m_RawW+rgbW+1]);//G
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+2]=pRaw[(rgbH+1)*m_RawW+rgbW+1];//B
}
}
for(rgbW=1;rgbW
{
for(rgbH=0;rgbH
{
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3]=pRaw[(rgbH+1)*m_RawW+rgbW+1];//R
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+1]=BYTE(0.5*(float)pRaw[(rgbH+1)*m_RawW+rgbW]+0.5*(float)pRaw[(rgbH)*m_RawW+rgbW+1]);//G
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+2]=pRaw[rgbH*m_RawW+rgbW];//B
}
}
for(rgbW=1;rgbW
{
for(rgbH=1;rgbH
{
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3]=pRaw[rgbH*m_RawW+rgbW+1];//R
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+1]=BYTE(0.5*(float)pRaw[(rgbH+1)*m_RawW+rgbW+1]+0.5*(float)pRaw[rgbH*m_RawW+rgbW]);//G
pRGB[(m_RawH-rgbH-1)*m_RawW*3+rgbW*3+2]=pRaw[(rgbH+1)*m_RawW+rgbW];//B
}
}
}
按照这个算法实际验证确实可以还原图片,能够清晰的看清楚图片。但是图片的质量不是很好,需要进一步优化。
从OV5647看骁龙820A
OV5647输出的是10bit的rawRGB数据,最高分辨率是五百万,文中提到OV5647的帧数仅仅只是出rawRGB数据的速度,并不代表帧数处理速度。
笔者在对比开发板上(不支持DSP)图像处理速度,如果只用CPU计算图像数据,并且只是将rawRGB转成可以用的RGB数据,结果表明用户体验的不好。不仅效率很低,而且占用大量的CPU资源,计算1080分辨率的图像只能达到20帧。
这更加能够很好体现了820A上矢量DSP对于图像处理的重要性,它有专业的图像处理功能,图像处理方面效率更高,并且能够节省大量的CPU资源。配合上Qualcomm专门为发挥其潜能的而开发的优化的Hexagon DSP算法库,在车载应用上将是非常不错的选择。下面是小编所在公司开发基于820A的车载原型系统。
对于骁龙820A来说,不但DSP性能卓著,CPU和GPU也是专门为车载应用前瞻性设计,对于未来大数据、智能化时代的汽车而言尤其显得为其量身定制一样。