问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

第十八届智能车摄像头组技术解析:从图像处理到控制算法

创作时间:
作者:
@小白创作中心

第十八届智能车摄像头组技术解析:从图像处理到控制算法

引用
CSDN
11
来源
1.
https://blog.csdn.net/qq_58114029/article/details/132006971
2.
https://cloud.baidu.com/article/3384306
3.
https://blog.csdn.net/chu_kuang_/article/details/128401434
4.
https://blog.csdn.net/A469333242/article/details/134617021
5.
https://cloud.baidu.com/article/3346075
6.
https://blog.csdn.net/m0_58857034/article/details/126030856
7.
https://blog.csdn.net/zhuoqingjoking97298/article/details/143926993
8.
https://blog.csdn.net/2301_79407667/article/details/142528028
9.
https://wenku.csdn.net/answer/3ce1f9n47k
10.
https://www.smartautoclub.com/p/29408/
11.
https://www.haolizi.net/example/view_90548.html

第十八届全国大学生智能车竞赛的摄像头组比赛,要求参赛队伍设计并制作一辆能够自主识别赛道并完成比赛的智能车。本文将从图像处理、赛道识别和控制算法三个方面,详细解析摄像头组的核心技术要点,并结合具体代码示例,帮助读者快速掌握比赛要领。

01

比赛规则与要求

根据比赛规则,摄像头组要求车模从车库出发运行一周后返回到车库,且摄像头镜头中心高度需小于等于15厘米。比赛场地使用PVC材料制作,不再允许增加路肩,赛道元素包括断路口、横断路障等。参赛队伍可以使用竞赛秘书处统一指定的竞赛车模套件,也可以自行设计制作车模。

02

图像处理技术

二值化处理

在图像处理中,最常用的方法是图像二值化。二值化可以将灰度图像转换为黑白图像,使赛道与背景形成鲜明对比,便于后续处理。这里我们采用大津法(OTSU)来自动计算最佳阈值。

// 大津法求动态阈值
uint8 otsuThreshold(uint8 *image, uint16 col, uint16 row)
{
#define GrayScale 256
    uint16 Image_Width  = col;
    uint16 Image_Height = row;
    int X; uint16 Y;
    uint8* data = image;
    int HistGram[GrayScale] = {0};

    uint32 Amount = 0;
    uint32 PixelBack = 0;
    uint32 PixelIntegralBack = 0;
    uint32 PixelIntegral = 0;
    int32 PixelIntegralFore = 0;
    int32 PixelFore = 0;
    double OmegaBack=0, OmegaFore=0, MicroBack=0, MicroFore=0, SigmaB=0, Sigma=0; // 类间方差;
    uint8 MinValue=0, MaxValue=0;
    uint8 Threshold = 0;

    for (Y = 0; Y <Image_Height; Y++) 
    {
        for (X = 0; X < Image_Width; X++)
        {
        HistGram[(int)data[Y*Image_Width + X]]++; //统计每个灰度值的个数信息
        }
    }

    for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;        //获取最小灰度的值
    for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ; //获取最大灰度的值

    if (MaxValue == MinValue)
    {
        return MaxValue;          // 图像中只有一个颜色
    }
    if (MinValue + 1 == MaxValue)
    {
        return MinValue;      // 图像中只有二个颜色
    }

    for (Y = MinValue; Y <= MaxValue; Y++)
    {
        Amount += HistGram[Y];        //  像素总数
    }

    PixelIntegral = 0;
    for (Y = MinValue; Y <= MaxValue; Y++)
    {
        PixelIntegral += HistGram[Y] * Y;//灰度值总数
    }
    SigmaB = -1;
    for (Y = MinValue; Y < MaxValue; Y++)
    {
          PixelBack = PixelBack + HistGram[Y];    //前景像素点数
          PixelFore = Amount - PixelBack;         //背景像素点数
          OmegaBack = (double)PixelBack / Amount;//前景像素百分比
          OmegaFore = (double)PixelFore / Amount;//背景像素百分比
          PixelIntegralBack += HistGram[Y] * Y;  //前景灰度值
          PixelIntegralFore = PixelIntegral - PixelIntegralBack;//背景灰度值
          MicroBack = (double)PixelIntegralBack / PixelBack;//前景灰度百分比
          MicroFore = (double)PixelIntegralFore / PixelFore;//背景灰度百分比
          Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore);//g
          if (Sigma > SigmaB)//遍历最大的类间方差g
          {
              SigmaB = Sigma;
              Threshold = (uint8)Y;
          }
    }
   return Threshold;
}  

得到阈值后,我们可以对图像进行二值化处理:

uint8 bin_image[image_h][image_w];//图像数组
void threshold(uint8 *image, uint8 threshold)
{
    for (int i = 0; i < image_h; i++)
    {
        for (int j = 0; j < image_w; j++)
        {
            if (image[i * image_w + j] > threshold)
            {
                bin_image[i][j] = 255; // 白色
            }
            else
            {
                bin_image[i][j] = 0; // 黑色
            }
        }
    }
}
03

赛道识别与定位

赛道识别的核心是通过图像扫描获取赛道边界和中线。这里采用从屏幕中线向两侧边缘进行扫线的方法。

for (line = 100; line >= 20; line--) //纵向
{
    for (list = old; list < 188 - 2; list++) //向右横向
    {
        if (mt9v03x_image1[line][list] == 255 &&
            mt9v03x_image1[line][list + 1] == 0 &&
            mt9v03x_image1[line][list + 2] == 0)
        {
            rightline[line] = list;
            right_flag[line] =1;
            break;
        }
    }
    if (list == 188 - 2) 
    {
        right_flag[line] =0;
        rightline[line] = 187;//右侧边缘位默认为187,即数组最大位
    }

    for (list = old; list >= 2; list--) //向左横向
    {
        if (mt9v03x_image1[line][list] == 255 &&
            mt9v03x_image1[line][list - 1] == 0 &&
            mt9v03x_image1[line][list - 2] == 0)
        {
            leftline[line] = list;
            left_flag[line] = 1
            break;
        }
    }
    if (list == 1) 
    {
        left_flag[line] = 0;
        leftline[line] = list;
    }
    
    road_width[line] = leftline[line] - rightline[line]; //计算赛道宽度,存放在一个一维数组中
    centerline[line] = (rightline[line] + leftline[line]) / 2; //计算中线的位置,存放在一维数组中
    old = centerline[line]; //将上一次的中线位置记入进变量old,下次以其为点进行寻找。
}
04

控制算法

控制算法是智能车的核心,决定了车辆的行驶稳定性和响应速度。这里采用PD控制算法,通过调整舵机角度来控制车辆方向。

// 舵机PD控制
float steer_pid(float deviation)
{
    static float last_dev = 0;
    float Kp = 1.2, Kd = 0.8;
    float output = Kp * deviation + Kd * (deviation - last_dev);
    last_dev = deviation;
    return constrain(output, -100, 100);  // 限制舵机角度
}

// 应用示例
float dev = calculate_deviation();  // 从图像获取偏差
pwm_set(SERVO_PIN, 1500 + steer_pid(dev)*10);  // 1500为中位
05

实战经验分享

参数调优

  • 图像大小:一般设置为180*100左右,过大会影响处理速度,过小则信息量不足。
  • 曝光时间:需要根据现场光线条件调整,建议在512左右。
  • 帧率:默认50帧即可,过高会增加处理负担。
  • 图像偏移:需要调整摄像头位置和角度,确保图像中线与实际赛道中线对齐。

常见问题解决

  • 光线干扰:可以使用对比度算法增强边界识别,或在必要时使用遮光布。
  • 图像偏移:通过调整摄像头安装位置和角度来解决。
  • 焦距问题:需要手动调节摄像头焦距,确保图像清晰。
06

总结

智能车摄像头组比赛是一个集图像处理、控制算法和机械设计于一体的综合性工程挑战。通过掌握上述核心技术要点,结合实际调试经验,相信你能够设计出一辆性能优异的智能车。建议在实际操作中多进行实验和调试,不断优化参数和算法,以应对比赛中的各种挑战。

参考资源:

  1. 第十八届智能车摄像头组开源代码:https://gitee.com/joshua_xu/the-18th-smartcar
  2. 智能车摄像头技术详解:https://blog.csdn.net/chu_kuang_/article/details/128401434
  3. 大津法二值化算法:https://blog.csdn.net/A469333242/article/details/134617021
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号