在图像处理方面,我原来是在opencv和MATLAB方面用的比较多。没怎么接触过单片机方面的处理。这次比赛算是收获挺多的。在项目总帖中展示的那段追踪视频。识别是基于颜色分布直方图实现的。先转换颜色空间从RGB到HSV然后根据概率分布图确定概率最大的区域。最后将区域中心坐标发送给云台。
先贴一下RGB2HSV的函数static unsigned char CvtColor(float R,float G,float B,float*s,float*v)
{
//unsigned char max=0,min=0;
short ret=0;
float vmin, diff;
R=R/255;G=G/255;B=B/255;//RGB normalization
(*v) = vmin = R;
if( *v < G ) *v = G;
if( *v < B ) *v = B; // v = max(b, g, r)
if( vmin > G ) vmin = G;
if( vmin > B ) vmin = B;
diff=(*v)-vmin;
*s = diff/(*v); // s = 1 - min/max
diff = (float)(60/(diff + 1.192092896e-07F));
if( *v == R )
ret = (G - B)*diff;
else if( *v == G )
ret = (B - R)*diff + 120;
else
ret = (R - G)*diff + 240;
if( ret < 0 ) ret += 360; // h
return ret/2;
}
然后还有一个实现方法更符合这个项目。但是没调试好,所以没有放在展示中。这个实现方法是通过光流实现的,我们知道光流不适合摄像机本身运动的场合。所以我先用帧间差分提取背景然后检测到帧间发生很大的变化时判定有物体闯入,然后再开始计算光流场。并得出重心。以这个为坐标,云台向该坐标运动。然后再使得摄像机静止重新求取光流。
还有就是发一个开发过程中遇到的官方驱动的BUG。在 BSP_LCD_ReadPixel();函数中官方是这么写的
if(hLtdcHandler.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
{
/* Read data value from SDRAM memory */
ret = *(__IO uint32_t*) (hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (2*(Ypos*BSP_LCD_GetXSize() + Xpos)));
}
我们知道RGB8888是32位的也就是4个字节。所以应该吧2*(Ypos*BSP_LCD_GetXSize() + Xpos改成4*(Ypos*BSP_LCD_GetXSize() + Xpos这样就得到正确结果而不会意外卡死