当前位置:   article > 正文

全国大学生智能汽车大赛(一):摄像头识别赛道代码_无人车赛道代码汇总图

无人车赛道代码汇总图

全国大学生智能汽车大赛(一):摄像头识别赛道代码

全国大学生智能汽车大赛(二):摄像头识别赛道代码

全国大学生智能汽车大赛(三):上下位机通信协议及代码

        这些代码是我在大二时参加智能车竞赛时编写的程序,仅供参考。

        代码内容涉及二值化大津法(相关内容可以参考我的另一篇博文)等。

a087144010ff45f29c28da38181b05da.jpeg

        智能汽车基于先进的自动化控制技术以传感器信号检测处理为指引,驱动电机实现特定轨迹的高速稳定行驶。目前智能汽车技术在交通运输、智能驾驶等方面有着广阔的应用前景与发展空间。智能车的方案设计基本相似,整体的稳定性和高速行驶对控制系统的设计要求很高,尤其是面对复杂路况时赛道的识别、转向控制和车速控制是系统设计的难点。

  1. /**********************************************
  2. * @file 摄像头
  3. * @Target core TC264D
  4. * @date 2021-5-19
  5. * @note
  6. **********************************************/
  7. #include "headfile.h"
  8. double deviation1; //摄像头获得的偏差
  9. /************************************
  10. * 函数名称:otsu(uint16 column, uint16 row)
  11. * 功能说明:求阈值大小
  12. * 参数说明:
  13. * 函数返回:阈值大小
  14. * 修改时间:2021/5/12 Wed
  15. ************************************/
  16. uint16 otsu(uint16 column, uint16 row)
  17. {
  18. uint16 i,j;
  19. uint32 Amount = 0;
  20. uint32 PixelBack = 0;
  21. uint32 PixelIntegralBack = 0;
  22. uint32 PixelIntegral = 0;
  23. int32 PixelIntegralFore = 0;
  24. int32 PixelFore = 0;
  25. float OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma; //类间方差;
  26. uint16 MinValue, MaxValue;
  27. uint16 Threshold = 0;
  28. uint8 HistoGram[256];
  29. for (j = 0; j < 256; j++) HistoGram[j] = 0; //初始化灰度直方图
  30. for (j = 0; j < row; j++)
  31. {
  32. for (i = 0; i < column; i++)
  33. {
  34. HistoGram[mt9v03x_image[j][i]]++; //统计灰度级中每个像素在整幅图像中的个数
  35. }
  36. }
  37. for (MinValue = 0; MinValue < 256 && HistoGram[MinValue] == 0; MinValue++) ; //获取最小灰度的值
  38. for (MaxValue = 255; MaxValue > MinValue && HistoGram[MinValue] == 0; MaxValue--) ; //获取最大灰度的值
  39. for (j = MinValue; j <= MaxValue; j++) Amount += HistoGram[j]; //像素总数
  40. PixelIntegral = 0;
  41. for (j = MinValue; j <= MaxValue; j++)
  42. {
  43. PixelIntegral += HistoGram[j] * j; //灰度值总数
  44. }
  45. SigmaB = -1;
  46. for (j = MinValue; j < MaxValue; j++)
  47. {
  48. PixelBack = PixelBack + HistoGram[j]; //前景像素点数
  49. PixelFore = Amount - PixelBack; //背景像素点数
  50. OmegaBack = (float)PixelBack / Amount; //前景像素百分比
  51. OmegaFore = (float)PixelFore / Amount; //背景像素百分比
  52. PixelIntegralBack += HistoGram[j] * j; //前景灰度值
  53. PixelIntegralFore = PixelIntegral - PixelIntegralBack; //背景灰度值
  54. MicroBack = (float)PixelIntegralBack / PixelBack; //前景灰度百分比
  55. MicroFore = (float)PixelIntegralFore / PixelFore; //背景灰度百分比
  56. Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore); //计算类间方差
  57. if (Sigma > SigmaB) //找出最大类间方差以及对应的阈值
  58. {
  59. SigmaB = Sigma;
  60. Threshold = j;
  61. }
  62. }
  63. return Threshold; //返回最佳阈值;
  64. }
  65. /************************************
  66. * @brief 二值化
  67. * @param mode : 0:大津法阈值 1:平均阈值
  68. * @return
  69. * @note Get_01_Value(0); //使用大津法二值化
  70. * @date 2021/5/12 WED
  71. ************************************/
  72. uint8 Pixle[MT9V03X_H][MT9V03X_W]; //存放二值化后图像
  73. void binaryzation(uint8 mode)
  74. {
  75. int i = 0,j = 0;
  76. uint32 Threshold;
  77. uint32 tv=0;
  78. if(mode)
  79. {
  80. //累加
  81. for(i = 0; i <MT9V03X_H; i++)
  82. {
  83. for(j = 0; j <MT9V03X_W; j++)
  84. {
  85. tv+=mt9v03x_image[i][j]; //累加
  86. }
  87. }
  88. Threshold=tv/MT9V03X_H/MT9V03X_W; //求平均值,光线越暗越小,全黑约35,对着屏幕约160,一般情况下大约100
  89. Threshold=Threshold*7/10+10; //此处阈值设置,根据环境的光线来设定
  90. }
  91. else
  92. {
  93. Threshold = otsu(MT9V03X_W,MT9V03X_H); //大津法阈值
  94. // Threshold = (uint8_t)(Threshold * 0.5) + 70;
  95. }
  96. for(i = 0; i < MT9V03X_H; i++)
  97. {
  98. for(j = 0; j < MT9V03X_W; j++)
  99. {
  100. if(mt9v03x_image[i][j] >Threshold) //数值越大,显示的内容越多,较浅的图像也能显示出来
  101. Pixle[i][j] =0xff;
  102. else
  103. Pixle[i][j] =0x00;
  104. }
  105. }
  106. }
  107. /************************************
  108. * @brief 过滤噪点
  109. * @param
  110. * @return
  111. * @note
  112. * @date 2021/5/13 Thur
  113. ************************************/
  114. void Pixle_Filter(void)
  115. {
  116. int nr; //行
  117. int nc; //列
  118. for(nr=1; nr<MT9V03X_H-1; nr++)
  119. {
  120. for(nc=1; nc<MT9V03X_W-1; nc=nc+1)
  121. {
  122. 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))))
  123. {
  124. Pixle[nr][nc]=0xff;
  125. }
  126. 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))))
  127. {
  128. Pixle[nr][nc]=0x00;
  129. }
  130. }
  131. }
  132. }
  133. /************************************
  134. * @brief 摄像头获取偏差
  135. * @param start_row开始列,end_row终止列,step检测步值
  136. * @return camera_deviation偏差
  137. * @note
  138. * @date 2021/5/15 Sat
  139. ************************************/
  140. typedef struct //定义一个结构体,用于放置所用点的所在列数以及标志符
  141. {
  142. int16 column;
  143. int16 flag;
  144. }usefulpoint;
  145. usefulpoint jump_left[use_h_max], jump_right[use_h_max], midpoint[use_h_max];//定义每一行左,右跳变点,赛道中点
  146. double camera_deviation(int16 start_row, int16 end_row, int16 step)
  147. {
  148. int16 column, row, num_left = 0, num_right = 0,num_mid = 0; //定义检测偏差中所需的中间变量及标志
  149. double deviation = 0;
  150. //参数初始化
  151. for(row = 0; row>= end_row; row++)
  152. {
  153. jump_left[row].flag = 0;
  154. jump_right[row].flag = 0;
  155. midpoint[row].flag = 0;
  156. }
  157. //跳变点检测
  158. for (row = start_row; row < end_row; row=row+step)
  159. {
  160. //左侧跳变点检测
  161. for (column = 0; column < MT9V03X_W; column++)
  162. {
  163. if ( (Pixle[row-1][column]==0xff) && (Pixle[row][column]==0xff) && (Pixle[row+1][column]==0x00) && (Pixle[row+2][column]==0x00))
  164. {
  165. jump_left[row].column = column; //记录左侧跳变点列数
  166. jump_left[row].flag = 1; //标记为左侧跳变点
  167. num_left++; //左侧跳变点个数增加1
  168. break; //找到左侧跳变点,跳出循环
  169. }
  170. }
  171. //右侧跳变点检测
  172. for (column = MT9V03X_W; column > 0; column++)
  173. {
  174. if ( (Pixle[row-2][column]==0x00) && (Pixle[row-1][column]==0x00) && (Pixle[row][column]==0xff) && (Pixle[row+1][column]==0xff))
  175. {
  176. jump_right[row].column = column; //记录右侧跳变点列数
  177. jump_right[row].flag = 1; //标记为右侧跳变点
  178. num_right++; //右侧跳变点个数增加1
  179. break; //找到右侧跳变点,跳出循环
  180. }
  181. }
  182. }
  183. if(num_left<=4) return -10; //采集到的图像中只有右侧赛道边缘
  184. if(num_right<=4) return 10; //采集到的图像中只有左侧赛道边缘
  185. //计算赛道中点
  186. for (row = start_row; row < end_row; row=row+step)
  187. {
  188. if((jump_left[row].flag)&&(jump_right[row].flag))
  189. {
  190. midpoint[row].column = (jump_left[row].column+jump_right[row].column)/2; //计算赛道中点所在列
  191. if(midpoint[row].column <= MT9V03X_W) midpoint[row].flag = 1; //标记为赛道中点
  192. num_mid++; //赛道中点个数增加1
  193. }
  194. }
  195. //计算偏差1.0
  196. for (row = start_row; row < end_row; row=row+step)
  197. {
  198. if(midpoint[row].flag) deviation = deviation + midpoint[row].column - MT9V03X_W/2;
  199. }
  200. deviation=deviation/num_mid;
  201. return deviation;
  202. }

二、 推荐IO分配

摄像头: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 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/619200
推荐阅读
相关标签
  

闽ICP备14008679号