在智能车调试摄像头图像中经历了带着小车在趴着赛道跑后,觉得这种但对于摄像头处理来验证算法实在是过于低效,于是我下载了c++版本的opencv作为可视化界面,保存一份小车跑图的视频,每次去读取视频来针对每一帧图像的处理,这样可以更加着重于图像处理算法中,在调试小车摄像头图像数据时不再需要除电脑外的任何小车的硬件资源,以下我来分享一些我的调试经验和代码成果,希望可以对你有帮助
1.首先我们需要分析在赛道中所包含的赛道类型
1.1 长直赛道 1.2 S型弯道 1.3 十字弯道 1.4 环岛
而对于1.1 和 1.2 类型一般不需要用到补线和特定的元素查找
明确以上后便可正式开始真正的图像处理了
2.图像的二值化处理
2.1 对于一般的灰度摄像头采集到的灰度图的像素点都是位于 0-255 ,而如此多的像素类别不便于我们对特定元素的查找,所以我们一般为了简化对只有0和255 和二值化图像 ,而这个过程便不可避免的对二值化阈值的设定(二值化阈值就是在灰度图的0-255间取一个值,大于该阈值就设定为255(像素点亮),小于就为0(像素点灭)),这样我们就可以的到实际的二值化图像
经过阈值划分得到的二值化图像
而图像的数据我们一般采用一个二维数组进行存储,通过输入位于图像的x,y 坐标即可擦找该点的像素值(图像一般以左上为0,0 x为以左向右增加,y为以上向下增加)
unsigned char img_data[y][x] = {0}; // 原始灰度图像数据
unsigned char img_2data[y][x] = { 0 }; // 二值化后的图像
由之前提及到的得到二值化图核心就是要的到阈值
我这里采用经典的大津法求阈值,这个其实是一个获得动态阈值的算法,会统计每个灰度像素值,会在像素值个数最多划分成两个部分,而这个像素值就是最后获得的阈值,会由于场地的光线不同发生变化(但在一场跑图中并不会有太大的波动,几乎都是稳定在一个值,觉得算法占用太多的资源其实可以根据现场调整)
// 大津法计算阈值
uint8 Threshold_Deal(uint8* image,int col,int row, int pixel_threshold)
{
#define GrayScale 256
int width = col;
int height = row;
int pixelCount[GrayScale];
float pixelPro[GrayScale];
int i, j;
int pixelSum = width * height;
uint8 threshold = 0;
uint8* data = image;
for (i = 0; i < GrayScale; i++)
{
pixelCount[i] = 0;
pixelPro[i] = 0;
}
int gray_sum = 0;
for (i = 0; i < height; i += 1)
{
for (j = 0; j < width; j += 1)
{
pixelCount[(
int)data[i * width + j]]++;
gray_sum += (int)data[i * width + j];
}
}
for (i = 0; i < GrayScale; i++)
{
pixelPro[i] = (float)pixelCount[i] / pixelSum;
}
float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
for (j = 0; j < pixel_threshold; j++)
{
w0 +=
pixelPro[j];
u0tmp +