赞
踩
这些代码是我在大二时参加智能车竞赛时编写的程序,仅供参考。
代码内容涉及二值化、大津法(相关内容可以参考我的另一篇博文)等。
智能汽车基于先进的自动化控制技术以传感器信号检测处理为指引,驱动电机实现特定轨迹的高速稳定行驶。目前智能汽车技术在交通运输、智能驾驶等方面有着广阔的应用前景与发展空间。智能车的方案设计基本相似,整体的稳定性和高速行驶对控制系统的设计要求很高,尤其是面对复杂路况时赛道的识别、转向控制和车速控制是系统设计的难点。
- /**********************************************
- * @file 摄像头
- * @Target core TC264D
- * @date 2021-5-19
- * @note
- **********************************************/
-
- #include "headfile.h"
- double deviation1; //摄像头获得的偏差
-
- /************************************
- * 函数名称:otsu(uint16 column, uint16 row)
- * 功能说明:求阈值大小
- * 参数说明:
- * 函数返回:阈值大小
- * 修改时间:2021/5/12 Wed
- ************************************/
- uint16 otsu(uint16 column, uint16 row)
- {
- uint16 i,j;
- uint32 Amount = 0;
- uint32 PixelBack = 0;
- uint32 PixelIntegralBack = 0;
- uint32 PixelIntegral = 0;
- int32 PixelIntegralFore = 0;
- int32 PixelFore = 0;
- float OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma; //类间方差;
- uint16 MinValue, MaxValue;
- uint16 Threshold = 0;
- uint8 HistoGram[256];
-
- for (j = 0; j < 256; j++) HistoGram[j] = 0; //初始化灰度直方图
-
- for (j = 0; j < row; j++)
- {
- for (i = 0; i < column; i++)
- {
- HistoGram[mt9v03x_image[j][i]]++; //统计灰度级中每个像素在整幅图像中的个数
- }
- }
-
- for (MinValue = 0; MinValue < 256 && HistoGram[MinValue] == 0; MinValue++) ; //获取最小灰度的值
- for (MaxValue = 255; MaxValue > MinValue && HistoGram[MinValue] == 0; MaxValue--) ; //获取最大灰度的值
-
- for (j = MinValue; j <= MaxValue; j++) Amount += HistoGram[j]; //像素总数
-
- PixelIntegral = 0;
- for (j = MinValue; j <= MaxValue; j++)
- {
- PixelIntegral += HistoGram[j] * j; //灰度值总数
- }
- SigmaB = -1;
- for (j = MinValue; j < MaxValue; j++)
- {
- PixelBack = PixelBack + HistoGram[j]; //前景像素点数
- PixelFore = Amount - PixelBack; //背景像素点数
- OmegaBack = (float)PixelBack / Amount; //前景像素百分比
- OmegaFore = (float)PixelFore / Amount; //背景像素百分比
- PixelIntegralBack += HistoGram[j] * j; //前景灰度值
- PixelIntegralFore = PixelIntegral - PixelIntegralBack; //背景灰度值
- MicroBack = (float)PixelIntegralBack / PixelBack; //前景灰度百分比
- MicroFore = (float)PixelIntegralFore / PixelFore; //背景灰度百分比
- Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore); //计算类间方差
- if (Sigma > SigmaB) //找出最大类间方差以及对应的阈值
- {
- SigmaB = Sigma;
- Threshold = j;
- }
- }
- return Threshold; //返回最佳阈值;
- }
-
- /************************************
- * @brief 二值化
- * @param mode : 0:大津法阈值 1:平均阈值
- * @return
- * @note Get_01_Value(0); //使用大津法二值化
- * @date 2021/5/12 WED
- ************************************/
- uint8 Pixle[MT9V03X_H][MT9V03X_W]; //存放二值化后图像
- void binaryzation(uint8 mode)
- {
- int i = 0,j = 0;
- uint32 Threshold;
- uint32 tv=0;
- if(mode)
- {
- //累加
- for(i = 0; i <MT9V03X_H; i++)
- {
- for(j = 0; j <MT9V03X_W; j++)
- {
- tv+=mt9v03x_image[i][j]; //累加
- }
- }
- Threshold=tv/MT9V03X_H/MT9V03X_W; //求平均值,光线越暗越小,全黑约35,对着屏幕约160,一般情况下大约100
- Threshold=Threshold*7/10+10; //此处阈值设置,根据环境的光线来设定
- }
- else
- {
- Threshold = otsu(MT9V03X_W,MT9V03X_H); //大津法阈值
- // Threshold = (uint8_t)(Threshold * 0.5) + 70;
- }
-
- for(i = 0; i < MT9V03X_H; i++)
- {
- for(j = 0; j < MT9V03X_W; j++)
- {
- if(mt9v03x_image[i][j] >Threshold) //数值越大,显示的内容越多,较浅的图像也能显示出来
- Pixle[i][j] =0xff;
- else
- Pixle[i][j] =0x00;
- }
- }
- }
-
- /************************************
- * @brief 过滤噪点
- * @param
- * @return
- * @note
- * @date 2021/5/13 Thur
- ************************************/
- void Pixle_Filter(void)
- {
- int nr; //行
- int nc; //列
-
- for(nr=1; nr<MT9V03X_H-1; nr++)
- {
- for(nc=1; nc<MT9V03X_W-1; nc=nc+1)
- {
- if((Pixle[nr][nc]==0xff)&&(((Pixle[nr-1][nc]==0xff)&&(Pixle[nr+1][nc]==0xff))||((Pixle[nr][nc+1]==0xff)&&(Pixle[nr][nc-1]==0xff))))
- {
- Pixle[nr][nc]=0xff;
- }
- else if((Pixle[nr][nc]==0x00)&&(((Pixle[nr-1][nc]==0x00)&&(Pixle[nr+1][nc]==0x00))||((Pixle[nr][nc+1]==0x00)&&(Pixle[nr][nc-1]==0x00))))
- {
- Pixle[nr][nc]=0x00;
- }
- }
- }
- }
-
- /************************************
- * @brief 摄像头获取偏差
- * @param start_row开始列,end_row终止列,step检测步值
- * @return camera_deviation偏差
- * @note
- * @date 2021/5/15 Sat
- ************************************/
-
- typedef struct //定义一个结构体,用于放置所用点的所在列数以及标志符
- {
- int16 column;
- int16 flag;
- }usefulpoint;
- usefulpoint jump_left[use_h_max], jump_right[use_h_max], midpoint[use_h_max];//定义每一行左,右跳变点,赛道中点
- double camera_deviation(int16 start_row, int16 end_row, int16 step)
- {
- int16 column, row, num_left = 0, num_right = 0,num_mid = 0; //定义检测偏差中所需的中间变量及标志
- double deviation = 0;
- //参数初始化
- for(row = 0; row>= end_row; row++)
- {
- jump_left[row].flag = 0;
- jump_right[row].flag = 0;
- midpoint[row].flag = 0;
- }
- //跳变点检测
- for (row = start_row; row < end_row; row=row+step)
- {
- //左侧跳变点检测
- for (column = 0; column < MT9V03X_W; column++)
- {
- if ( (Pixle[row-1][column]==0xff) && (Pixle[row][column]==0xff) && (Pixle[row+1][column]==0x00) && (Pixle[row+2][column]==0x00))
- {
- jump_left[row].column = column; //记录左侧跳变点列数
- jump_left[row].flag = 1; //标记为左侧跳变点
- num_left++; //左侧跳变点个数增加1
- break; //找到左侧跳变点,跳出循环
- }
- }
- //右侧跳变点检测
- for (column = MT9V03X_W; column > 0; column++)
- {
- if ( (Pixle[row-2][column]==0x00) && (Pixle[row-1][column]==0x00) && (Pixle[row][column]==0xff) && (Pixle[row+1][column]==0xff))
- {
- jump_right[row].column = column; //记录右侧跳变点列数
- jump_right[row].flag = 1; //标记为右侧跳变点
- num_right++; //右侧跳变点个数增加1
- break; //找到右侧跳变点,跳出循环
- }
- }
- }
- if(num_left<=4) return -10; //采集到的图像中只有右侧赛道边缘
- if(num_right<=4) return 10; //采集到的图像中只有左侧赛道边缘
- //计算赛道中点
- for (row = start_row; row < end_row; row=row+step)
- {
- if((jump_left[row].flag)&&(jump_right[row].flag))
- {
- midpoint[row].column = (jump_left[row].column+jump_right[row].column)/2; //计算赛道中点所在列
- if(midpoint[row].column <= MT9V03X_W) midpoint[row].flag = 1; //标记为赛道中点
- num_mid++; //赛道中点个数增加1
- }
- }
- //计算偏差1.0
- for (row = start_row; row < end_row; row=row+step)
- {
- if(midpoint[row].flag) deviation = deviation + midpoint[row].column - MT9V03X_W/2;
- }
- deviation=deviation/num_mid;
-
- return deviation;
- }
摄像头:8个数据口,一个串口,两eru中断
数据口:00_0 00_1 00_2 00_3 00_4 00_5 00_6 00_7
配置串口:摄像头RX:02_2 摄像头TX:02_3
VSY:02_0
HREF:程序不需要,所以不接
PCLK:02_1
四路运放 A0 A1 A2 A3 等
四个编码器:
LSB:33_7 DIR:33_6
LSB:02_8 DIR:00_9
LSB:10_3 DIR:10_1
LSB:20_3 DIR:20_0
8路pwm:
21_2 21_3 21_4 21_5 02_4 02_5 02_6 02_7
ICM20602:
CLK: P20_11
MOSI: P20_14
MISO: P20_12
CS: P20_13
SPI0
TFT屏幕:
CLK 15_3
MOSI 15_5
MISO 15_4 //实际上TFT没有这个引脚 这里仅仅占位而已
CS0 15_2
BL 15_4 //复用控制背光
REST 15_1
DC 15_0
SPI2
舵机:
P33_9
尽量不要使用以下引脚,以下引脚属于boot引脚,不合理的使用容易导致单片机无法启动等问题,因此建议大家尽量不要使用:
P14_2
P14_3
P14_4
P14_5
P14_6
P10_5
P10_6
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。