一.传统的扫线循迹,网上的资料繁杂,开源资料或者博客破碎化
1.我于2021年10份正式接触摄像头,在到最终比赛期间,遇到了不少困难和迷惑的地方,接下来我会阐述摄像头小车整个从图像处理到实现循迹的大概过程。
2.本开源博客的代码处理皆是基于逐飞科技提供的底层开源函数库
二.摄像头如何采集到图像
1.采集原始值
/*
*****图像处理函数*****
* 内部调用图像二值化函数,采集开始时先进行二值化,
* 然后进行扫线处理,得到赛道中点、边界和宽度
*/
void image_get(void)
{
if(mt9v03x_finish_flag_dvp)
{
Image_preprocessing();//图像二值化函数
Bin_Image_Filter ();//过滤噪点
image_scan();//双边扫线
mt9v03x_finish_flag_dvp = 0;//在图像使用完毕后 务必清除标志位,否则不会开始采集下一幅图像
//注意:一定要在图像使用完毕后在清除此标志位
}}
除去Image_preprocessing();Bin_Image_Filter (); image_scan();三个函数,单片机通过dvp中段
采集摄像头传来的原始图像,原始图像是一张灰色的0—255图像:
在此之后,如果需要判断出赛道的形状,那么需要分辨出赛道和蓝布的边界,也就是说要找出赛道的边界,可以明显的看出,赛道部分的图像明显不同于蓝布区,赛道部分颜色浅,蓝布区域颜色深。图像二值化可以解决这个问题,顾名思义,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。这时,如何划分这个值是一个问题,大津法可以很好的解决这个问题
/*
*************大津法*************
* *image---需要处理的图像
* col---列w
* row---行h
* 在二值化函数中被调用,每次二值化之前计算阈值
*/
uint8 otsuThreshold(uint8 *image, uint16 col, uint16 row)//w,h
{
#define GrayScale 255
uint16 width = col;
uint16 height = row;
int pixelCount[GrayScale];
float pixelPro[GrayScale];
int i, j, pixelSum = width * height;
uint8 threshold = 0;
uint8* data = image; //指向像素数据的指针
for (i = 0; i < GrayScale; i++