行业知识
智能车摄像头算法——寻线
2026-11-05 07:38:43
来源:互联网转载
寻线
- 1.灰度图像二值化
- 2.找边线
- 3.获���中线
1.灰度图像二值化
如果使用的是小钻风摄像(二值化摄像头),就不用再进行软件二值化。
()使用灰度摄像头,就需要这步。
以下展示常用的大津法
()(1)首先获得分割的阈值
uint8 otsuThreshold(uint8 *GrayImage,uint32 ImageSize) { int T; //T为动态阈值 uint8 threshold = 0; //最佳阈值 uint32 N0 = 0,N1 = ImageSize; //图像中像素小于阈值T的像素个数记作N0,像素大于阈值T的像素个数记作N1 float w0,w1; //w0为前景像素点占整幅图像的比例 w0 = N0/ImageSize (ImageSize为图像大小) //w1为前景像素点占整幅图像的比例 w1 = N1/ImageSize (ImageSize为图像大小) uint32 u0den = 0,u1den = 0; //图像中像素小于阈值T的像素加权和记作u0den //图像中像素大于阈值T的像素加权和记作u1den float u0,u1; //u0为前景像素点平均灰度 u0 = u0den/N0 //u1为前景像素点平均灰度 u1 = u1den/N1 float deltaTmp; //类间方差 计算公式 w0*w1*(u0-u1)^2 //类间方差最大的阈值T为所求最佳阈值 uint32 itemp,*pPixelCount = pixelCount; float deltaMax = 0; //获取灰度图像直方图 _Getting_GrayHistogram(pPixelCount,GrayImage,ImageSize); //计算动态阈值 for (T = 0;T deltaMax) { deltaMax = deltaTmp; threshold = T; } } if(deltaMax = 50) threshold = 10; else if(threshold(2)再进行二值化(white=255 black =0)
//***********************************************// //函数名称: image_Gray2Binary // //函数版本: V1.0 // //函数说明: 灰度图片转化为二值化图片 // //函数输入: BinImage : 二值化图像指针 // // GrayImage : 灰度图像指针 // // ImageSize : 输入图像尺寸(长度*宽度) // // threshold : 图像转化阈值 // //函数输出: BinImage : 二值化图像指针 // //***********************************************// void image_Gray2Binary(uint8 *Binimg,uint8 *GrayImage,uint32 ImageSize,uint8 threshold) { uint32 z; uint32 temp,temp_1 = white,temp_2 = black; for (z = 0;z = threshold) *(Binimg + z) = temp_1; else *(Binimg + z) = temp_2; } }使用:
//mt9v03x_image是灰度图像数组 pixel=otsuThreshold(&mt9v03x_image[0][0],MT9V03X_W*MT9V03X_H);//img是二值化后得到的图像image_Gray2Binary(&img[0][0],&mt9v03x_image[0][0],MT9V03X_W*MT9V03X_H,pixel);//img二值化图像
当然还有很多算法,例如基于sobel算子,动态阈值法等等。有需要可以评论邮箱,我发你。但是我觉得只要能把图像大体的边界信息保留下来,就可以了。并且有部分算法运算量很大,智能车比赛有些指定的单片机运用这些算法会把图像卡成PPT。
2.找边线
找边线可以就用最简单的逻辑,从中间向两边搜黑点。从距离车头较近的行开始从中间向两边搜线。
以下代码思路稍微有点变化:
左边线默认:1 右边线默认:(图像宽度-1)
从车头最近的一行开始,把这行图像单独拿出来,作为一个参考。之后的行,搜左边线时,从前一个搜的左边线的横坐标加一个值向左搜;搜右边线时,从前一个搜的右边线的横坐标减一个值向右搜。这个过程完成,就得到了一幅图像的边界数组。
/*-----------------------------------------------------------------! * @brief 获取边线 * * @param imageInput : 二值图像信息 * @param imageOut : 边线数组 * * @return 是否丢线 * * @note 思路:从距离车头较近的行开始从中间向两边搜线 ---------------------------------------------------------------------- */uint8_t ImageGetSide(uint8_t imageInput[OV7725_UART_H][OV7725_UART_W], uint8_t imageOut[OV7725_UART_H][2]){ uint8_t i = 0, j = 0,k=0; for(i = OV7725_UART_H-1; i > 0; i--) { imageOut[i][left] = 1; imageOut[i][right] = OV7725_UART_W-1; } // 用距离小车比较近的行 判断是否丢线 for(i = OV7725_UART_W/2; i > 1; i--) { if(!imageInput[OV7725_UART_H-1][i]) { imageOut[OV7725_UART_H-1][left] = i; break; } } for(i = OV7725_UART_W/2+1; i 0; i--) { // 向左搜线 for(j = imageOut[i+1][left] + 10; j > 0; j--) { if(!imageInput[i][j]) { imageOut[i][left] = j; break; } } if(imageOut[i][left] > OV7725_UART_W/2) { imageOut[i][left]=OV7725_UART_W/2; for(k=i;k>0;k--) { imageOut[k][left]=OV7725_UART_W/2; } break; } } //遍历每一行 for(i = OV7725_UART_H-2; i > 0; i--) { //向右搜线 for(j = imageOut[i+1][right] - 10; j 0;k--) { imageOut[k][right]=OV7725_UART_W/2; } break; } }3.获得中线
一般情况:
中线 =(左边线+右边线)/2
特殊情况:
中线 = 左边线+N 或者
中线 = 右边线-N
这个特殊处理根据实际情况自己处理就行了。比如说,在左转弯的时候弧度太大,导致左边线全部丢线,这个时候就可以令中线 = 右边线 - N。当然还是要根据自己摄像头采集到的图像特征来灵活运用
有问题可以私聊我咯~
另外承接各种单片机设计
可以加企鹅群 658476482 交流