当前位置:   article > 正文

十六届智能车全向组算法开源(四)-圆环处理_lcd_showint

lcd_showint




系列文章目录

之前一段时间在处理手头的一些事情,将算法开源系列搁置了一段时间(主要是懒了)。之前介绍了预处理,边线,拐点等,这一章主要介绍环岛。


算法开源系列(三)

算法开源系列(二)

算法开源系列(一)

硬件开源系列(二)

硬件开源系列(一)





前言

         在我比赛的算法,通常在处理元素之前,需要具备良好的图像边界,拐点,边界起始行,边界截止行等主要条件。之前系列文章介绍过了边界,和拐点。有人留言提到过拐点的程序,其实最简单的方法,就是连续几行的边界做差,差值满足条件就判断为拐点。

        圆环!!这个在我做车三年一直都是噩梦存在的元素,虽然16届增加了新元素三岔,我依然在圆环花费了最多的时间。因为今年选用的是摄像头入环,所以在处理圆环的时候,不仅仅要考虑如何识别,还需要在入环,环内进行补线处理。于是我在处理圆环大致分为识别,入环切线,入环 ,环内,出环,出环切线,完全出环这几个阶段。

  1. void R_uppoint( unsigned char Row_START,unsigned char Row_END ,unsigned char Col_START,unsigned char Col_END,unsigned char Edge_ROW)
  2. {
  3. int Col;
  4. //uint8 N_P=0;
  5. int C1=0;
  6. int Row=Edge_ROW;
  7. for(Row=Edge_ROW;Row>Edge_ROW-7 && Row>ROW_START+1;Row--)//从本行开始向上扫10
  8. {
  9. for(Col=Col_END-2;Col>15;Col--)//初始值固定
  10. {
  11. if(difference_sum(image[Row][Col-COL_SPACE],image[Row][Col])>=g_threshold_value)//检测到跳变点
  12. {
  13. if( abs(Col-COL_SPACE-C1)<2&& Col-COL_SPACE<=C1)//如果两列差值小于3,说明C为拐点
  14. {
  15. Inflection_point.R_up_point.x=Row;
  16. Inflection_point.R_up_point.y=C1;
  17. return;
  18. }
  19. C1=Col-COL_SPACE;
  20. break;
  21. }
  22. }
  23. }
  24. }




一、起始行和截止行

顾名思义吧,起始行就是第一次扫到边界的那一行,截止行是最后一次找到边界的行。这两个特征代表了边界的可用范围。

二、圆环识别:

      圆环的特征还是相当明显,一边边线,连续,一边边线,缺失。这里我采用的方式是在识别到一边拐点存在,一边拐点不存在,并且存在的拐点距离最远端很近,这里我以当拐点距离最远行小于5行为标准。当存在这些条件后,再进行拐点上面几行边线缺失判断。以左环为例,当左边存在拐点,并且拐点上方有三行不存在边线。就行下面的右边线计数,当右边先满足远小近大的条件,并且连续存在13行边线就满足圆环的识别。这种识别是很稳定的,但由于车库的存在通常会与车库误识别,所以对于两者区别还需要想办法解决。

  1. round->Entrance_count=0;//圆环入口计数清零
  2. if(point->L_down_point.x+5>ROW_END-1)
  3. Round_row=ROW_END-1;
  4. else
  5. Round_row=point->L_down_point.x+5;
  6. for(;Round_row>point->L_down_point.x-10&&Round_row>=ROW_START;Round_row--)//从左拐点下面5行到上面10行进行搜索
  7. {
  8. if(str->RightEdge[Round_row+1]!=0&&str->RightEdge[Round_row]!=0)
  9. {
  10. //如果右边正常递减,且不丢线 斜率符合要求
  11. if(str->RightEdge[Round_row+1]-str->RightEdge[Round_row]>=0 &&str->RightEdge[Round_row+1]-str->RightEdge[Round_row]<=2)
  12. {
  13. round->Entrance_count++; //圆环入口计数增加
  14. }
  15. }
  16. }
  17. if(round->Entrance_count>=13)//min修改,其中有13行满足条件即可判定为圆环
  18. {
  19. round->Round_flag=1;
  20. RoundType=Left_Round;
  21. RoundProcess=Find_Round;
  22. RoadType= Round_Road;
  23. // BlueRing;
  24. //RoundSize=Large_Round; //待定
  25. }

进环前处理:

我们在识别到环的时候,是在环外的,所以需要保持一段距离直行到环的切点A。我的方法是通过 B点之前的斜率进行补线。    

  1. for(Round_row=ROW_END;Round_row>=ROW_START;Round_row--)
  2. {
  3. if(str->RightEdge[Round_row])
  4. {
  5. char temp_r;
  6. char temp_l;
  7. char track;
  8. temp_r=str->RightEdge[Round_row];
  9. track=Boundary.track_Width[Round_row];
  10. temp_l=temp_r-track-1;
  11. if(temp_l>=79)
  12. {
  13. temp_l=78;
  14. }
  15. if(temp_l<=1)
  16. {
  17. temp_l=1;
  18. }
  19. str->LeftEdge[Round_row]=temp_l;
  20. // str->LeftEdge[Round_row]=str->RightEdge[Round_row]-str->track_Width[Round_row];//左边界等于右边界减半宽
  21. }
  22. else
  23. {
  24. str->LeftEdge[Round_row]=0;
  25. }
  26. }

 进环处理:

对于进环,需要将右边线通过补线方式补成一个类似与弯道的情况。然后通过陀螺仪积分判断旋转的角度,当角度满足车身已经进入到环里的条件,就可以正常的巡线走了。

 

  1. case Into_Round://进环 关键 分两步
  2. {
  3. // lcd_showint8(110,6, 2);
  4. /*进环的补线处理*/
  5. if(!Inflection_point.L_down_point.x&&!Inflection_point.L_up_point.x&&str->LeftEdge[ROW_END-5])//&&str->LeftEdge[ROW-4])
  6. // if(Inflection_point.L_up_point.x==0&&Inflection_point.L_down_point.x&&str->LeftEdge[ROW_END-3])
  7. // if(Inflection_point.L_up_point.x&&(left_ad>=220||right_ad>200)&&!str->LeftEdge[ROW_END-1])
  8. {
  9. RoundProcess=Into_Round2;
  10. }
  11. else
  12. { //获取补线点信息
  13. if(point->L_down_point.x>5) //记录上一次拐点存在的信息
  14. {
  15. Inflection_Temp_x=point->L_down_point.x;
  16. Inflection_Temp_y=point->L_down_point.y;
  17. }
  18. //得到信息后,开始补线
  19. for(uint8 i=Inflection_Temp_x;i>2;i--)
  20. {
  21. if(image[i][Inflection_Temp_y]>=Threshold&&image[i-1][Inflection_Temp_y]<Threshold)
  22. {
  23. LeftLoopTemp_R=i-1;
  24. str->EndLine=i-1;
  25. break;
  26. }
  27. }
  28. for(uint8 i=Inflection_Temp_y;i<75;i++)
  29. {
  30. if((image[LeftLoopTemp_R-1][i+1]>=Threshold)&&(image[LeftLoopTemp_R-1][i]<Threshold))
  31. {
  32. LeftLoopTemp_C=i;
  33. break;
  34. }
  35. }
  36. /*进环斜率*/
  37. LeftLoopSlope=1.3;//*(str->RightEdge[aa1]-aa2)/(aa1-LeftLoopTemp_R);
  38. for(uint8 i=0;i<=28;i++)
  39. {
  40. str->RightEdge[LeftLoopTemp_R+i]=(int)(i*LeftLoopSlope+LeftLoopTemp_C);
  41. str->RightEdge[LeftLoopTemp_R+i]=int8_range_protect(str->RightEdge[LeftLoopTemp_R+i],1,79) ;
  42. if(str->RightEdge[LeftLoopTemp_R+i]>78||LeftLoopTemp_R+i>ROW_END)
  43. break;
  44. }
  45. }
  46. for(uint8 i=str->EndLine;i<ROW_END;i++)
  47. {
  48. for(uint8 j=1;j<=79;j++)
  49. {
  50. if(image[i][j]>=Threshold&&image[i][j+1]<Threshold)
  51. {
  52. if(str->RightEdge[i]>j+1)
  53. str->RightEdge[i]=j+1;
  54. break;
  55. }
  56. }
  57. }
  58. break;
  59. }
  60. case Into_Round2://进环 关键 4
  61. {
  62. // lcd_showint8(110,6, 3);
  63. /*判断是否进入环岛*/
  64. if(angle_z<=-40)//&&str->L_StartLine==0&& RoundSize==Small_Round) //定距离一段
  65. {
  66. RoundProcess=In_Round;
  67. Inflection_Temp_x=0;
  68. Inflection_Temp_y=0;
  69. //lcd_showint8(80,5, 4);
  70. }
  71. #if 1 //补线
  72. for(uint8 i=str->EndLine;i<=ROW_END;i++)
  73. {
  74. for(uint8 j=1;j<=75;j++)
  75. {
  76. if(image[i][j]>=Threshold&&image[i][j+1]<Threshold&&image[i][j+2]<Threshold&&image[i][j+3]<Threshold)
  77. //if (difference_sum(image[i][j],image[i][j-COL_SPACE])>=g_threshold_value)
  78. {
  79. if(str->RightEdge[i]>j+1)
  80. str->RightEdge[i]=j+1;
  81. break;
  82. }
  83. }
  84. }
  85. /*进环斜率*/
  86. LeftLoopSlope=2.0;
  87. for(uint8 i=ROW_END;i>ROW_START;i--)
  88. {
  89. // lcd_showint8(80,5, 5);
  90. if(str->RightEdge[i]!=0)
  91. str->RightEdge[i]=str->RightEdge[i]<(int)(LeftLoopSlope*i+5)?str->RightEdge[i]:(int)(LeftLoopSlope*i+5);
  92. else
  93. str->RightEdge[i]=(int)(LeftLoopSlope*i+5);
  94. if(str->RightEdge[i]>79)
  95. str->RightEdge[i]=0;
  96. }
  97. for(uint8 i=29;i>str->EndLine&&i>ROW_START+2;i--)
  98. {
  99. //lcd_showint8(80,5, 6);
  100. if(image[i][10]>=Threshold&&image[i-1][10]<Threshold&&image[i-2][10]<Threshold)
  101. //if (difference_sum(image[i-2][10],image[i][10])>=g_threshold_value)
  102. {
  103. for(uint8 j=i;j>str->EndLine&&j>ROW_START;j--)
  104. {
  105. str->LeftEdge[j]=0;
  106. }
  107. str->EndLine=i-1; //改变endline
  108. break;
  109. }
  110. if(str->LeftEdge[i]>30)
  111. {
  112. str->LeftEdge[i]=0; //限幅
  113. }
  114. }
  115. #endif
  116. break;
  117. }

 出环处理:

在出环时,由于左边线不存在,因此也需要进行补线操作。目的就是为了出环时车转弯方向是正确的,

 

  1. case Leave_Round://离开圆环
  2. {
  3. // lcd_showint8(110,4, 6);
  4. Round_num=0;
  5. for(Round_row=str->R_StartLine;Round_row>str->EndLine+1&&Round_row>ROW_START+10;Round_row--)
  6. {
  7. if(str->RightEdge[Round_row]==0)
  8. {
  9. Round_num++;
  10. }
  11. }
  12. if(Round_num<3&&((str->R_StartLine-str->EndLine)>22||str->RightEdge[str->EndLine]>18)) //30需要调 huo 判断斜率
  13. {
  14. RoundProcess=Leave_Round2;//暂定
  15. }
  16. else
  17. {
  18. LeftLoopSlope=2.5;
  19. for(uint8 i=29;i>5;i--)
  20. {
  21. if(str->RightEdge[i]!=0)
  22. str->RightEdge[i]=str->RightEdge[i]<(unsigned char)(LeftLoopSlope*i+5)?str->RightEdge[i]:(unsigned char)(LeftLoopSlope*i+5);
  23. else
  24. str->RightEdge[i]=(unsigned char)(LeftLoopSlope*i+5);
  25. if(str->RightEdge[i]>79)
  26. str->RightEdge[i]=0;
  27. }
  28. for(uint8 i=29;i>str->EndLine;i--) //消除左线误搜索
  29. {
  30. if(str->LeftEdge[i]>40)
  31. {
  32. str->LeftEdge[i]=0;
  33. }
  34. if(i<29&&i>ROW_START)
  35. {
  36. if(str->LeftEdge[i]!=0&&str->LeftEdge[i-1]==0&&str->LeftEdge[i+1]==0)
  37. str->LeftEdge[i]=0;
  38. }
  39. }
  40. }
  41. break;
  42. }

出环后处理:

在出环后,由于环岛元素存在的缺口,仍需要补线进行引导。也是通过斜率来进行补线。

 

  1. Round_num=0;
  2. for(Round_row=str->R_StartLine;Round_row>str->EndLine+1&&Round_row>ROW_START+10;Round_row--)
  3. {
  4. if(str->RightEdge[Round_row]==0)
  5. {
  6. Round_num++;
  7. }
  8. }
  9. if(Round_num<3&&((str->R_StartLine-str->EndLine)>22||str->RightEdge[str->EndLine]>18)) //30需要调 huo 判断斜率
  10. {
  11. RoundProcess=Leave_Round2;//暂定
  12. }
  13. else
  14. {
  15. LeftLoopSlope=2.5;
  16. for(uint8 i=29;i>5;i--)
  17. {
  18. if(str->RightEdge[i]!=0)
  19. str->RightEdge[i]=str->RightEdge[i]<(unsigned char)(LeftLoopSlope*i+5)?str->RightEdge[i]:(unsigned char)(LeftLoopSlope*i+5);
  20. else
  21. str->RightEdge[i]=(unsigned char)(LeftLoopSlope*i+5);
  22. if(str->RightEdge[i]>79)
  23. str->RightEdge[i]=0;
  24. }
  25. for(uint8 i=29;i>str->EndLine;i--) //消除左线误搜索
  26. {
  27. if(str->LeftEdge[i]>40)
  28. {
  29. str->LeftEdge[i]=0;
  30. }
  31. if(i<29&&i>ROW_START)
  32. {
  33. if(str->LeftEdge[i]!=0&&str->LeftEdge[i-1]==0&&str->LeftEdge[i+1]==0)
  34. str->LeftEdge[i]=0;
  35. }
  36. }
  37. }

之后当车行过缺口就可以恢复正常巡线,这里可以积路程,简单一点,也可以采用起始行是否在图像最底端来判断。

最后

底下附上完整过程代码,以便大家推导理解,对于代码,不建议直接拿去用,因为图像与摄像头参数都不一样。可以根据上面提到的思路,自己写一遍。分阶段来实现进环,至少这套方法我在圆环这里基本没出现过问题,除了速度快了,麦轮没办法很及时的转弯进去。

多嘴一句,这里的方法也不是最好的,但之于我是很有效的。可能也有更快,更好,更丝滑的进环算法。我就充当一个抛砖引玉的角色,希望能帮助没有思路的车友有一种简单有效的方法去实现进环。这一章也是自己用手画的图,在我看来在调试元素的时候,趴赛道才是最好的方法。需要各位仔细琢磨,不断完善,才可以有适合自己的算法。

  1. void Round_Process(Str_Boundary *str,Str_Round *round,Str_Inflection_point *point)
  2. {
  3. float LeftLoopSlope;
  4. float RightLoopSlope;
  5. uint8 break_point_num;
  6. uint8 many_bp_row;
  7. uint8 white_point_num;
  8. uint8 Round_num=0;
  9. break_point_num=0;
  10. switch(RoundType)
  11. {
  12. case Left_Round: //左环
  13. {
  14. switch(RoundProcess)
  15. {
  16. case Find_Round://发现圆环
  17. {
  18. // mark_garage();
  19. // lcd_showint8(110,4, 0);
  20. for(uint8 i=29;i>=0&&i>Boundary.EndLine;i--)
  21. {
  22. if( Boundary.LeftEdge[i]==0 && Boundary.RightEdge[i] )
  23. {
  24. for(uint8 j=Boundary.RightEdge[i];j-1>5;j--)
  25. {
  26. if(mark_middle_num(image[i][j],image[i][j-1],Threshold)
  27. && abs( difference_sum(image[i][j],image[i][j-1]) )>=g_threshold_value-10 )//跳变
  28. {
  29. break_point_num++;
  30. if(break_point_num>7 )
  31. {
  32. many_bp_row++;
  33. break;
  34. }
  35. }
  36. }
  37. }
  38. if(many_bp_row>3)//黑白跳变点数 90
  39. {
  40. round->Round_flag=0;
  41. RoadType= else_road;
  42. return;
  43. }
  44. }
  45. // lcd_showint8(120,5,many_bp_row);
  46. //*进入下个阶段的判定*/
  47. if(str->L_StartLine<25) //da待改进
  48. {
  49. Round_num=0;
  50. for(Round_row=str->L_StartLine;Round_row>=str->L_StartLine-4&&Round_row>=ROW_START+1;Round_row--) //防止误判 检测换中心岛
  51. {
  52. if(str->LeftEdge[Round_row]!=0)
  53. {
  54. Round_num+=str->LeftEdge[Round_row]-str->LeftEdge[Round_row+1] ;
  55. }
  56. else
  57. {
  58. Round_num=0;
  59. }
  60. }
  61. if(Round_num>10)
  62. {
  63. Round_num=0;
  64. RoundProcess=Find_Gap;//就认为有缺口
  65. // lcd_showint8(80,1, 1);
  66. }
  67. }
  68. //*入环的补线*/
  69. for(Round_row=ROW_END;Round_row>=ROW_START;Round_row--)
  70. {
  71. if(str->RightEdge[Round_row])
  72. {
  73. char temp_r;
  74. char temp_l;
  75. char track;
  76. temp_r=str->RightEdge[Round_row];
  77. track=Boundary.track_Width[Round_row];
  78. temp_l=temp_r-track-1;
  79. if(temp_l>=79)
  80. {
  81. temp_l=78;
  82. }
  83. if(temp_l<=1)
  84. {
  85. temp_l=1;
  86. }
  87. str->LeftEdge[Round_row]=temp_l;
  88. // str->LeftEdge[Round_row]=str->RightEdge[Round_row]-str->track_Width[Round_row];//左边界等于右边界减半宽
  89. }
  90. else
  91. {
  92. str->LeftEdge[Round_row]=0;
  93. }
  94. }
  95. break;
  96. }
  97. case Find_Gap://发现圆环中心
  98. {
  99. // lcd_showint8(110,6, 1);
  100. /*下一阶段的判定*/
  101. //底部三行左边界都不丢线
  102. // if(str->LeftEdge[ROW_END-2]&&str->LeftEdge[ROW_END-1]&&str->LeftEdge[ROW_END-3])//&&str->LeftEdge[ROW_END-2]
  103. // if(Inflection_point.L_up_point.x&&Inflection_point.L_down_point.x&&(Inflection_point.L_down_point.x-Inflection_point.L_up_point.x)<15)
  104. // if(str->LeftEdge[ROW_END-2]&&str->LeftEdge[ROW_END-1]&&str->LeftEdge[ROW_END-3]&&Inflection_point.L_up_point.x)
  105. // mark_garage();
  106. // if(str->LeftEdge[ROW_END-1]-str->LeftEdge[ROW_END-2]>0&&str->LeftEdge[ROW_END-2]-str->LeftEdge[ROW_END-3]>0)
  107. // for(uint8 i=29;i>=0&&i>Boundary.EndLine;i--)
  108. // {
  109. //
  110. //
  111. if( Boundary.LeftEdge[i]==0 && Boundary.RightEdge[i] )
  112. {
  113. // for(uint8 j=Boundary.RightEdge[i];j-1>COL_END-10;j++)
  114. // {
  115. // if(mark_middle_num(image[i][j],image[i][j-1],Threshold)
  116. // && abs( difference_sum(image[i][j],image[i][j-1]) )>=g_threshold_value-10 )//跳变
  117. // {
  118. // break_point_num++;
  119. // if(break_point_num>7 )
  120. // {
  121. // many_bp_row++;
  122. // break;
  123. // }
  124. // }
  125. // }
  126. }
  127. //
  128. // if(many_bp_row>2)//黑白跳变点数 90
  129. // {
  130. // round->Round_flag=0;
  131. // RoadType= else_road;
  132. // return;
  133. // }
  134. // }
  135. if(e_distance>1000)
  136. {
  137. if(Inflection_point.L_up_point.x)
  138. {
  139. RoundProcess=Into_Round;
  140. }
  141. }
  142. /*左补线*/
  143. for(Round_row=ROW_END;Round_row>=ROW_START;Round_row--)
  144. {
  145. if(str->RightEdge[Round_row])
  146. {
  147. // str->LeftEdge[Round_row]=str->RightEdge[Round_row]-str->track_Width[Round_row];//左边界等于右边界减半宽
  148. char temp_r;
  149. char temp_l;
  150. char track;
  151. temp_r=str->RightEdge[Round_row];
  152. track=Boundary.track_Width[Round_row];
  153. temp_l=temp_r-track;
  154. if(temp_l>=79)
  155. {
  156. temp_l=78;
  157. }
  158. if(temp_l<=1)
  159. {
  160. temp_l=1;
  161. }
  162. str->LeftEdge[Round_row]=temp_l;
  163. }
  164. else
  165. {
  166. str->LeftEdge[Round_row]=0;
  167. }
  168. }
  169. break;
  170. }
  171. case Into_Round://进环 关键 分两步
  172. {
  173. // lcd_showint8(110,6, 2);
  174. /*进环的补线处理*/
  175. if(!Inflection_point.L_down_point.x&&!Inflection_point.L_up_point.x&&str->LeftEdge[ROW_END-5])//&&str->LeftEdge[ROW-4])
  176. // if(Inflection_point.L_up_point.x==0&&Inflection_point.L_down_point.x&&str->LeftEdge[ROW_END-3])
  177. // if(Inflection_point.L_up_point.x&&(left_ad>=220||right_ad>200)&&!str->LeftEdge[ROW_END-1])
  178. {
  179. RoundProcess=Into_Round2;
  180. }
  181. else
  182. { //获取补线点信息
  183. if(point->L_down_point.x>5) //记录上一次拐点存在的信息
  184. {
  185. Inflection_Temp_x=point->L_down_point.x;
  186. Inflection_Temp_y=point->L_down_point.y;
  187. }
  188. //得到信息后,开始补线
  189. for(uint8 i=Inflection_Temp_x;i>2;i--)
  190. {
  191. if(image[i][Inflection_Temp_y]>=Threshold&&image[i-1][Inflection_Temp_y]<Threshold)
  192. {
  193. LeftLoopTemp_R=i-1;
  194. str->EndLine=i-1;
  195. break;
  196. }
  197. }
  198. for(uint8 i=Inflection_Temp_y;i<75;i++)
  199. {
  200. if((image[LeftLoopTemp_R-1][i+1]>=Threshold)&&(image[LeftLoopTemp_R-1][i]<Threshold))
  201. {
  202. LeftLoopTemp_C=i;
  203. break;
  204. }
  205. }
  206. /*进环斜率*/
  207. LeftLoopSlope=1.3;//*(str->RightEdge[aa1]-aa2)/(aa1-LeftLoopTemp_R);
  208. for(uint8 i=0;i<=28;i++)
  209. {
  210. str->RightEdge[LeftLoopTemp_R+i]=(int)(i*LeftLoopSlope+LeftLoopTemp_C);
  211. str->RightEdge[LeftLoopTemp_R+i]=int8_range_protect(str->RightEdge[LeftLoopTemp_R+i],1,79) ;
  212. if(str->RightEdge[LeftLoopTemp_R+i]>78||LeftLoopTemp_R+i>ROW_END)
  213. break;
  214. }
  215. }
  216. for(uint8 i=str->EndLine;i<ROW_END;i++)
  217. {
  218. for(uint8 j=1;j<=79;j++)
  219. {
  220. if(image[i][j]>=Threshold&&image[i][j+1]<Threshold)
  221. {
  222. if(str->RightEdge[i]>j+1)
  223. str->RightEdge[i]=j+1;
  224. break;
  225. }
  226. }
  227. }
  228. break;
  229. }
  230. case Into_Round2://进环 关键 4
  231. {
  232. // lcd_showint8(110,6, 3);
  233. /*判断是否进入环岛*/
  234. if(angle_z<=-40)//&&str->L_StartLine==0&& RoundSize==Small_Round) //定距离一段
  235. {
  236. RoundProcess=In_Round;
  237. Inflection_Temp_x=0;
  238. Inflection_Temp_y=0;
  239. //lcd_showint8(80,5, 4);
  240. }
  241. #if 1 //补线
  242. for(uint8 i=str->EndLine;i<=ROW_END;i++)
  243. {
  244. for(uint8 j=1;j<=75;j++)
  245. {
  246. if(image[i][j]>=Threshold&&image[i][j+1]<Threshold&&image[i][j+2]<Threshold&&image[i][j+3]<Threshold)
  247. //if (difference_sum(image[i][j],image[i][j-COL_SPACE])>=g_threshold_value)
  248. {
  249. if(str->RightEdge[i]>j+1)
  250. str->RightEdge[i]=j+1;
  251. break;
  252. }
  253. }
  254. }
  255. /*进环斜率*/
  256. LeftLoopSlope=2.0;
  257. for(uint8 i=ROW_END;i>ROW_START;i--)
  258. {
  259. // lcd_showint8(80,5, 5);
  260. if(str->RightEdge[i]!=0)
  261. str->RightEdge[i]=str->RightEdge[i]<(int)(LeftLoopSlope*i+5)?str->RightEdge[i]:(int)(LeftLoopSlope*i+5);
  262. else
  263. str->RightEdge[i]=(int)(LeftLoopSlope*i+5);
  264. if(str->RightEdge[i]>79)
  265. str->RightEdge[i]=0;
  266. }
  267. for(uint8 i=29;i>str->EndLine&&i>ROW_START+2;i--)
  268. {
  269. //lcd_showint8(80,5, 6);
  270. if(image[i][10]>=Threshold&&image[i-1][10]<Threshold&&image[i-2][10]<Threshold)
  271. //if (difference_sum(image[i-2][10],image[i][10])>=g_threshold_value)
  272. {
  273. for(uint8 j=i;j>str->EndLine&&j>ROW_START;j--)
  274. {
  275. str->LeftEdge[j]=0;
  276. }
  277. str->EndLine=i-1; //改变endline
  278. break;
  279. }
  280. if(str->LeftEdge[i]>30)
  281. {
  282. str->LeftEdge[i]=0; //限幅
  283. }
  284. }
  285. #endif
  286. break;
  287. }
  288. case In_Round://在环内 5
  289. {
  290. // lcd_showint8(110,4,4);
  291. //记录上一次拐点存在的信息
  292. if(point->R_down_point.x&&image[point->R_down_point.x][point->R_down_point.y-2]>=Threshold&&image[point->R_down_point.x][point->R_down_point.y-3]>=Threshold&&image[point->R_down_point.x-1][point->R_down_point.y]>=Threshold&&image[point->R_down_point.x-2][point->R_down_point.y]>=Threshold)
  293. {
  294. Inflection_Temp_x=point->R_down_point.x;
  295. Inflection_Temp_y =point->R_down_point.y;
  296. //判断下一阶段
  297. if(point->R_down_point.x>5)
  298. {
  299. uint8 hang_num=0; //清除白块计数值 8
  300. for(Round_row=point->R_down_point.x-1; Round_row>=point->R_down_point.x-6&&Round_row>ROW_START ; Round_row-- ) //在搜索到的黑白跳变点后,向上搜索白点,判断是否为干扰点
  301. {
  302. if(str->RowLose[Round_row]==4)
  303. {
  304. hang_num++;
  305. }
  306. }
  307. if( hang_num>2|| point->R_down_point.x>20||Inflection_point.R_down_point.y>30)
  308. {
  309. RoundProcess=Out_Round;
  310. // lcd_showint8(110,4, 4);
  311. }
  312. }
  313. }
  314. if(Inflection_Temp_x>0)
  315. {
  316. //补线
  317. LeftLoopSlope=2.0;
  318. for(uint8 i=Inflection_Temp_x+1;i>ROW_START;i--)
  319. {
  320. str->RightEdge[i]=(int)((i-Inflection_Temp_x)*LeftLoopSlope+Inflection_Temp_y); //fuhao
  321. if (str->RightEdge[i]<COL_START)
  322. {
  323. str->EndLine =i;
  324. break;
  325. }
  326. }
  327. //str->StartLine=ROW_END;
  328. //memset(str->LeftEdge, 0,sizeof(str->LeftEdge) ); //z左线清空
  329. }
  330. for(uint8 i=29;i>str->EndLine;i--) //消除左线误搜索
  331. {
  332. if(str->LeftEdge[i]>30)
  333. {
  334. str->LeftEdge[i]=0;
  335. }
  336. }
  337. break;
  338. }
  339. case Out_Round://出环 6
  340. {
  341. // BlueRing;
  342. // lcd_showint8(110,4, 5);
  343. LeftLoopSlope=2.1;
  344. for(uint8 i=29;i>5;i--)//取小值
  345. {
  346. if(str->RightEdge[i]!=0)
  347. str->RightEdge[i]=str->RightEdge[i]<(unsigned char)(LeftLoopSlope*i+7)?str->RightEdge[i]:(unsigned char)(LeftLoopSlope*i+7);
  348. else
  349. str->RightEdge[i]=(unsigned char)(LeftLoopSlope*i+7);
  350. if(str->RightEdge[i]>79)
  351. str->RightEdge[i]=0;
  352. }
  353. // str->StartLine=ROW_END;
  354. // memset(str->LeftEdge, 0,sizeof(str->LeftEdge) );
  355. //
  356. if(angle_z<-85) //下一阶段标志
  357. {
  358. RoundProcess=Leave_Round;
  359. }
  360. for(uint8 i=29;i>str->EndLine;i--) //消除左线误搜索
  361. {
  362. if(str->LeftEdge[i]>35)
  363. {
  364. str->LeftEdge[i]=0;
  365. }
  366. if(i<29&&i>ROW_START)
  367. {
  368. if(str->LeftEdge[i]!=0&&str->LeftEdge[i-1]==0&&str->LeftEdge[i+1]==0)
  369. str->LeftEdge[i]=0;
  370. }
  371. }
  372. /*下一阶段的判定*/
  373. break;
  374. }
  375. case Leave_Round://离开圆环
  376. {
  377. // lcd_showint8(110,4, 6);
  378. Round_num=0;
  379. for(Round_row=str->R_StartLine;Round_row>str->EndLine+1&&Round_row>ROW_START+10;Round_row--)
  380. {
  381. if(str->RightEdge[Round_row]==0)
  382. {
  383. Round_num++;
  384. }
  385. }
  386. if(Round_num<3&&((str->R_StartLine-str->EndLine)>22||str->RightEdge[str->EndLine]>18)) //30需要调 huo 判断斜率
  387. {
  388. RoundProcess=Leave_Round2;//暂定
  389. }
  390. else
  391. {
  392. LeftLoopSlope=2.5;
  393. for(uint8 i=29;i>5;i--)
  394. {
  395. if(str->RightEdge[i]!=0)
  396. str->RightEdge[i]=str->RightEdge[i]<(unsigned char)(LeftLoopSlope*i+5)?str->RightEdge[i]:(unsigned char)(LeftLoopSlope*i+5);
  397. else
  398. str->RightEdge[i]=(unsigned char)(LeftLoopSlope*i+5);
  399. if(str->RightEdge[i]>79)
  400. str->RightEdge[i]=0;
  401. }
  402. for(uint8 i=29;i>str->EndLine;i--) //消除左线误搜索
  403. {
  404. if(str->LeftEdge[i]>40)
  405. {
  406. str->LeftEdge[i]=0;
  407. }
  408. if(i<29&&i>ROW_START)
  409. {
  410. if(str->LeftEdge[i]!=0&&str->LeftEdge[i-1]==0&&str->LeftEdge[i+1]==0)
  411. str->LeftEdge[i]=0;
  412. }
  413. }
  414. }
  415. break;
  416. }
  417. case Leave_Round2://离开圆环 7
  418. {
  419. //可以拉长视野
  420. // lcd_showint8(110,4, 7);
  421. for(Round_row=ROW_END;Round_row>=ROW_START;Round_row--)
  422. {
  423. if(str->RightEdge[Round_row])
  424. {
  425. // str->LeftEdge[Round_row]=str->RightEdge[Round_row]-str->track_Width[Round_row];//左边界等于右边界减半宽
  426. //if(str->RightEdge[Round_row])
  427. char temp_r;
  428. char temp_l;
  429. char track;
  430. temp_r=str->RightEdge[Round_row];
  431. track=str->track_Width[Round_row]+2.8;
  432. temp_l=temp_r-track;
  433. if(temp_l>=79)
  434. {
  435. temp_l=78;
  436. }
  437. if(temp_l<=1)
  438. {
  439. temp_l=1;
  440. }
  441. str->LeftEdge[Round_row]=temp_l;
  442. }
  443. else
  444. {
  445. str->LeftEdge[Round_row]=0;
  446. }
  447. }
  448. if (Lost_num<2)
  449. {
  450. if(str->L_StartLine&&str->R_StartLine&&str->L_StartLine==29&&str->R_StartLine==29&&Inflection_point.L_down_point.x==0&&Inflection_point.L_up_point.x==0)
  451. {
  452. // lcd_showint8(110,4, 7);
  453. if(str->LeftEdge[ROW_END-2]-str->LeftEdge[ROW_END-1]>0&&str->LeftEdge[ROW_END-4]-str->LeftEdge[ROW_END-3]>0)
  454. {
  455. RoundProcess=Round_Not_Found;//暂定
  456. round->Round_flag=0;
  457. RoadType= else_road;
  458. // BlueQuiet;
  459. }
  460. }
  461. }
  462. break;
  463. }
  464. default:
  465. {
  466. break;
  467. }
  468. }
  469. break;
  470. }
  471. }

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

闽ICP备14008679号