赞
踩
目录
(1)我们整个图像处理的步骤如下:
(2)前一篇文章我们已经对循迹原理进行了分析,找赛道边界就是找黑白跳变点。
我们这篇文章来讲解第二步“找边界求赛道中线”的代码实现,为了避免赛道附近的杂物对二值化产生影响,推荐从中间往两边找赛道中线,适用于中间是白色的情况,能向两边找到两个黑白跳变点;假如遇到中间不是白色的情况,就取1/4中点往两边找黑白跳变点,那么我们就要注意:是图像左边的1/4中点,还是图像右边的1/4中点?我们在代码实现的时候要将这个问题处理好。
处理方法就是:采用按“顺序判断“来写:(1)如果图像的二分之一点是白点,那从二分之一点开始找。(2)如果图像的二分之一点是白点,那就分别判断左右两个1/4点哪个为黑点,不可能出现左右两个1/4点均为黑点的情况。
针对以上思想,写出下面伪代码,注释详细,大家可以自行理解,有问题在评论区交流:
- /* 名字:Find_Mid_Line
- * 功能:寻找赛道的左右边界
- * 参数:index[MT9V03X_H][MT9V03X_W](为二值化后的数组)
- * 输出:无(会得到左边界线、右边界线、中线)
- */
- //找左边界 右边界 需要三个一维数组
- uint8 left_line_list[MT9V03X_H]; //高
- uint8 right_line_list[MT9V03X_H]; //高
- uint8 mid_line_list[MT9V03X_H]; //高
- void Find_Mid_Line(uint8 index[MT9V03X_H][MT9V03X_W]) //index指数
- {
- //定义左边点与右边点,并赋初值(当下面for循环没有左边点与右边点时用初值)
- uint8 left_point = 1;
- uint8 right_point = MT9V03X_W - 1; //宽
-
- left_line_list[0] = 1;
- right_line_list[0] = MT9V03X_W - 1;
- mid_line_list[0] = (left_point + right_point) / 2;
-
- //从图片底部往上找
- for(uint8 i = MT9V03X_H - 1;i > 0;i--) //高——行
- {
- /**************以下代码是遍历一整个横行找两个黑白跳变点***************/
- // 如果二分之一点是白点,从二分之一点开始找
- if(index[i][MT9V03X_W/2] == 255) //255 - 白
- {
- //寻找左边点
- for(uint8 j = MT9V03X_W/2 - 1;j > 0;j--)
- {
- if(index[i][j] == 0 && index[i][j+1] == 255) //255 - 白
- {
- left_point = j;
- break;
- }
- }
-
- //寻找右边点
- for(uint8 j = MT9V03X_W/2 + 1;j < MT9V03X_W;j++)
- {
- if(index[i][j] == 0 && index[i][j-1] == 255) //255 - 白
- {
- right_point = j;
- break;
- }
- }
- }
-
- // 如果四分之一点是白点,从四分之一点开始找
- else if(index[i][MT9V03X_W/4] == 255)
- {
- //寻找左边点
- for(uint8 j = MT9V03X_W/4 - 1;j > 0;j--)
- {
- if(index[i][j] == 0 && index[i][j+1] == 255) //255 - 白
- {
- left_point = j;
- break;
- }
- }
-
- //寻找右边点
- for(uint8 j = MT9V03X_W/4 + 1;j < MT9V03X_W;j++)
- {
- if(index[i][j] == 0 && index[i][j-1] == 255) //255 - 白
- {
- right_point = j;
- break;
- }
- }
- }
-
- // 如果四分之三点是白点,从四分之三开始找
- else if(index[i][MT9V03X_W/4*3] == 255)
- {
- //寻找左边点
- for(uint8 j = MT9V03X_W/4*3 - 1;j > 0;j--)
- {
- if(index[i][j] == 0 && index[i][j+1] == 255) //255 - 白
- {
- left_point = j;
- break;
- }
- }
-
- //寻找右边点
- for(uint8 j = MT9V03X_W/4*3 + 1;j < MT9V03X_W;j++)
- {
- if(index[i][j] == 0 && index[i][j-1] == 255) //255 - 白
- {
- right_point = j;
- break;
- }
- }
- }
- else //1/2点,1/4点,3/4点都是黑色时
- {
- left_point = 1;
- right_point = MT9V03X_W - 1;
- }
-
- left_line_list[i] = left_point;
- right_line_list[i] = right_point;
- mid_line_list[i] = (left_point + right_point)/2;
- }
- }
通过扫线,我们可以找到左边线的横坐标数组left_line_list[i],右边线的横坐标数组right_line_list[i],确定了左边线和右边线上所有点的横坐标,而边线的纵坐标就是是整个图像的高,所以左边线和右边线就确定了。
对左边线和右边线的横坐标求平均值:mid_line_list[i] = (left_point + right_point)/2, 最后得到的数组mid_line_list[i]为赛道中线的横坐标数组,中线的纵坐标也是整个图像的高,到此赛道边线和中线都确定下来了。
在cpu1.c中添加以下代码:
- while (TRUE)
- {
- // 此处编写需要循环执行的代码
-
- if(mt9v03x_finish_flag) //一幅图像完全采集完毕后,再进行图像的显示判断和显示
- {
- //Set_image_towvalues(150); //固定阈值二值化
- BandW_threshold = otsuThreshold_fast(mt9v03x_image[0]);//大津法得到动态阈值
- Set_image_towvalues(BandW_threshold); //动态阈值二值化,得到二值化后的二维数组mt9v03x_image_BandW
-
- Find_Mid_Line(mt9v03x_image_BandW[MT9V03X_H][MT9V03X_W]);//找边线
-
- tft180_displayimage03x(mt9v03x_image_BandW[0],MT9V03X_W,MT9V03X_H);//显示二值化后的图像
- mt9v03x_finish_flag = 0;//图像显示完成后才对标志位清零
- }
-
- // 此处编写需要循环执行的代码
- }
tc264对于数组越界,包括循环中遍历时的数组越界是比较严格的,一旦有什么地方有越界产生,工程会运行失败,功能会运行异常,屏幕可能显示不了图像。
下一节介绍,在屏幕中画出所找的边线和中线,直观地体现我们通过算法找的边线和中线是否合适。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。