智能车制作

标题: 提取中线 ,请大家给点意见 [打印本页]

作者: 璺鋈    时间: 2012-6-29 00:54
标题: 提取中线 ,请大家给点意见
本帖最后由 璺鋈 于 2012-6-29 01:01 编辑

t题设:赛道以外处理成黑色,缺点容易受反光影响,优点让判断变得更简单.摄像头反装,容易写程序,但容易头晕.前瞻1.5米思想:
二值化;
前面20行从中间往里面搜索;

判断左右跳变左111000,右000111记录跳变位置及标记
根据跳变标记,左右均有      右-左、              (满足赛道宽度条件才采用)         
                     只有左          (左+列数)/2   (满足赛道宽度条件才采用)   
                      只有右           右/2                 (满足赛道宽度条件才采用)   
                   左右均无                等于上一行值
连续判断四行连续有效值,则进入下一循环    分别寻左右跳变继续往后寻找
判断方法与上面相同.

写出来的程序如下后面是全部,但是提取出来的中心很不稳定,而且急弯还很容易出错.后面的10行左右如截图
[attach]26060[/attach]
大s二值化,按照思路,后面的一截应该判断为找到左右跳边沿但是宽度不满足则使用上行数据,但是通过串口发回来的数据显示,最后几行的数据是40多,完全不符合要求。

作者: 璺鋈    时间: 2012-6-29 00:55
[attach]26061[/attach]
作者: 璺鋈    时间: 2012-6-29 00:58
  1. void Black_Extract(void)
  2. {
  3. volatile int get_black_cnt,
  4. get_black_cnt1,
  5. base_point_flag;
  6. volatile byte i=0,j=0,left_temp=0,right_temp=0;
  7. volatile int k,m,n,o;
  8. volatile byte start_flag1=0,start_flag2=0;
  9. volatile word left_line=0,right_line=0,left_line1=0,right_line1=0;
  10. volatile word left_edge=0,right_edge=0;
  11. volatile char ins_black_center=0;
  12. black_lost_cnt=0;
  13. get_black_cnt =0;
  14. black_lost_cnt1 =0;
  15. black_lost_cnt=0;
  16. base_point_flag=0;
  17. Flag_Lost=0;
  18. SER_NUM=6;//搜索范围赋初值
  19. //Line_Center[0] = Line_Center[IMAGE_ROW-1];//每场的末尾给新的一场的开始,让图像连续,这句很重要
  20. //后10行两边都查找,取中间点
  21. start_flag1=0;start_flag2=0;
  22. left_edge=0;right_edge=0; //左右跳变清零
  23. //###########################二十行搜索##########################
  24. erzhihua(135);
  25. for(i=0;i<20;i++)
  26. {

  27. for(j=43;j>3;j--)
  28. {
  29. if(ImageSample_Buffer[i][j-1]==1&&ImageSample_Buffer[i][j-2]==1&&ImageSample_Buffer[i][j-3]==1&&ImageSample_Buffer[i][j]==0&&ImageSample_Buffer[i][j+1]==0&&ImageSample_Buffer[i][j+2]==0)
  30. {
  31. start_flag1=1;
  32. left_edge=j; //记录左跳变沿位置
  33. left_line=left_edge;
  34. }
  35. }//左边搜索结束
  36. for(j=43;j<IMAGE_COL-3;j++)
  37. {
  38. if(ImageSample_Buffer[i][j+1]==1&&ImageSample_Buffer[i][j+2]==1&&ImageSample_Buffer[i][j+3]==1&&ImageSample_Buffer[i][j]==0&&ImageSample_Buffer[i][j-1]==0&&ImageSample_Buffer[i][j-2]==0)
  39. {
  40. start_flag2=1;
  41. right_edge=j; //记录右跳变沿位置
  42. right_line=right_edge;
  43. }  
  44. }//右边搜索结束,找到左右跳变沿
  45. //一行搜索结束

  46. if(start_flag1==1 && start_flag2==1) //1.有左右跳变沿
  47. {
  48. SCI_Write('11') ;
  49. if((right_line - left_line >= WHITE_LINE_MIN0)&&(right_line - left_line <= WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  50. { //@@@@@@@@@过滤过宽的白线和过细的白线
  51. Line_Center_Temp=(byte)((right_line+left_line+1)>>1); //取中心,考虑到了每行的搜索到的最后一个点
  52. Line_Center[i]=Line_Center_Temp;
  53. get_black_cnt++;//找到有效行,加1
  54. }
  55. else
  56. {
  57. black_lost_cnt++;    //丢失行加1
  58. get_black_cnt=0;    //继续从头再找
  59. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  60. }
  61. }
  62. else if(start_flag1==0 && start_flag2==1) //2.只有右跳变沿,黑线向左弯
  63. {
  64. SCI_Write('22') ;
  65. if((right_line >= WHITE_LINE_MIN0) && (right_line <=WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  66. {
  67. Line_Center_Temp=(byte)(right_line>>1);
  68. Line_Center[i]=Line_Center_Temp;
  69. get_black_cnt++;
  70. }
  71. else
  72. {
  73. black_lost_cnt++;   //丢失行加1
  74. get_black_cnt=0;    //继续从头再找
  75. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  76. }
  77. }
  78. else if(start_flag1==1 && start_flag2==0) //3.只有左跳变沿,黑线向右弯
  79. {
  80. SCI_Write('33') ;
  81. if((IMAGE_COL - left_line >= WHITE_LINE_MIN0) && (IMAGE_COL - left_line <= WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  82. {
  83. Line_Center_Temp=(byte)((left_line+IMAGE_COL)>>1);
  84. Line_Center[i]=Line_Center_Temp;
  85. get_black_cnt++;//找到有效行,加1
  86. }
  87. else
  88. {
  89. black_lost_cnt++;  //丢失行加1
  90. get_black_cnt=0;    //继续从头再找
  91. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  92. }
  93. }
  94. else if(start_flag1==0 && start_flag2==0) //4.无左右跳变沿,这行舍弃,计数加1
  95. {
  96. SCI_Write('44') ;
  97. black_lost_cnt++; //丢失行加1
  98. get_black_cnt=0;    //继续从头再找
  99. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  100. }


  101. /*******判断是否为基准行**************/
  102. if(get_black_cnt>=4)//找到有效行,跳到下一个循环
  103.   {
  104.     if(fabs(Line_Center[i]-Line_Center[i+1]) <COM_NUM &&
  105.    fabs(Line_Center[i+1]-Line_Center[i+2])<COM_NUM &&
  106.     fabs(Line_Center[i+2]-Line_Center[i+3])<COM_NUM )
  107.      { //若4点连续,认为找到基准线了
  108.     base_point_flag=1; //表示基准点已经找到
  109.     Down_Limit=i+1; //最近有效行
  110.     Down_Limit1=Down_Limit;
  111.    break;  //跳出for循环
  112.     }
  113.     else //若不连续,继续全行搜索
  114.     {
  115.     get_black_cnt=0;
  116.     }
  117.   }


  118. if(black_lost_cnt>=15)   //前20行未找到基准行
  119. {
  120. duoji_kongzhi=duoji_kongzhi1;
  121. break;     //跳出for循环
  122. }
  123. }


  124. //是否返回继续找基准行
  125. if(base_point_flag==0)
  126. {
  127. return;
  128. }


  129. //##########################继续往前搜索##########################
  130. for(i=Down_Limit1;i<IMAGE_ROW;i++)
  131. {
  132. start_flag1=0;
  133. start_flag2=0;      //左右标志位置0
  134. left_line1=left_line;
  135. right_line1=right_line;
  136. k=left_line-SER_NUM;        //SER_NUM为搜索范围
  137. if(k<0) k=0;
  138. m=left_line+SER_NUM;
  139. if(m>IMAGE_COL) m=IMAGE_COL;
  140. n=right_line-SER_NUM;
  141. if(n<0) n=0;
  142. o=right_line+SER_NUM;
  143. if(o>IMAGE_COL)o=IMAGE_COL;    //确定左右搜索范围

  144. for(k;k<m;k++) //搜索左边
  145. {
  146. if(ImageSample_Buffer[i][k+1]==0&&ImageSample_Buffer[i][k+2]==0&&ImageSample_Buffer[i][k+3]==0&&ImageSample_Buffer[i][k]==1&&ImageSample_Buffer[i][k-1]==1&&ImageSample_Buffer[i][k-2]==1)
  147. {
  148. start_flag1=1;
  149. left_edge=k; //记录左跳变沿位置
  150. left_line=left_edge;
  151. }
  152. }    //左边搜索结束
  153. for(n;n<o;n++)
  154. {
  155. if(ImageSample_Buffer[i][n+1]==1&&ImageSample_Buffer[i][n+2]==1&&ImageSample_Buffer[i][n+3]==1&&ImageSample_Buffer[i][n]==0&&ImageSample_Buffer[i][n-1]==0&&ImageSample_Buffer[i][n-2]==0)
  156. {
  157. start_flag2=1;
  158. right_edge=n; //记录右跳变沿位置
  159. right_line=right_edge;
  160. }
  161. }        //右边搜索结束

  162. //按照基准行做相同判断
  163. if(start_flag1==1 && start_flag2==1) //1.有左右跳变沿
  164. {
  165. SCI_Write('55') ;
  166. if((right_line - left_line >= WHITE_LINE_MIN0)&&(right_line - left_line <= WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  167. { //@@@@@@@@@过滤过宽的白线和过细的白线
  168. Line_Center_Temp=(byte)((right_line+left_line+1)>>1); //取中心,考虑到了每行的搜索到的最后一个点
  169. Line_Center[i]=Line_Center_Temp;
  170. get_black_cnt1++;//找到有效行,加1
  171. }
  172. else
  173. {
  174. black_lost_cnt1++;    //丢失行加1
  175. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  176. left_line=left_line1;   //使用上一行的双线标志
  177. right_line=right_line1;
  178. SER_NUM++;//扩大搜索范围
  179. }
  180. }
  181. else if(start_flag1==0 && start_flag2==1) //2.只有右跳变沿,黑线向左弯
  182. {
  183. SCI_Write('66') ;
  184. if((right_line >= WHITE_LINE_MIN0) && (right_line <=WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  185. {
  186. Line_Center_Temp=(byte)(right_line>>1);
  187. Line_Center[i]=Line_Center_Temp;
  188. get_black_cnt1++;
  189. }                                                                                                                                                               
  190. else
  191. {
  192. black_lost_cnt1++;   //丢失行加1
  193. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  194. left_line=left_line1;   //使用上一行的双线标志
  195. right_line=right_line1;
  196. SER_NUM++;//扩大搜索范围
  197. }
  198. }
  199. else if(start_flag1==1 && start_flag2==0) //3.只有左跳变沿,黑线向右弯
  200. {
  201. SCI_Write('77') ;
  202. if((IMAGE_COL - left_line >= WHITE_LINE_MIN0) && (IMAGE_COL - left_line <= WHITE_LINE_MAX0)) //黑线宽度在规定范围内
  203. {
  204. Line_Center_Temp=(byte)((left_line+IMAGE_COL)>>1);
  205. Line_Center[i]=Line_Center_Temp;
  206. get_black_cnt1++;//找到有效行,加1
  207. }
  208. else
  209. {
  210. black_lost_cnt1++;  //丢失行加1
  211. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  212. left_line=left_line1;   //使用上一行的双线标志
  213. right_line=right_line1;
  214. SER_NUM++;//扩大搜索范围
  215. }
  216. }
  217. else if(start_flag1==0 && start_flag2==0) //4.无左右跳变沿,这行舍弃,计数加1
  218. {
  219. SCI_Write('88') ;
  220. black_lost_cnt1++; //丢失行加1
  221. Line_Center[i]=Line_Center[i-1]; //赋值上一行,不赋值则为上一场的值
  222. left_line=left_line1;   //使用上一行的双线标志
  223. right_line=right_line1;
  224. SER_NUM++;//扩大搜索范围
  225. }


  226. if(black_lost_cnt1>=15)   //后25行丢线行数过多,采用上一场值,并跳出
  227. {
  228. duoji_kongzhi=duoji_kongzhi1;
  229. break; //跳出for循环
  230. }


  231. }


  232. }
复制代码

作者: 林牛牛    时间: 2012-6-29 02:07
楼主提取的中线现在稳定嘛?
作者: 璺鋈    时间: 2012-6-29 08:59
林牛牛 发表于 2012-6-29 02:07
楼主提取的中线现在稳定嘛?

不正确

作者: 征服者    时间: 2012-6-29 20:03
楼主跑的怎么样啊
作者: 璺鋈    时间: 2012-6-29 20:20
征服者 发表于 2012-6-29 20:03
楼主跑的怎么样啊

当然不行才在这儿问题呢  还有一个问题   请问你知道为什么有一场的数据会发生上下两部分颠调的情况啊   纠结  导致舵机老是反打

作者: 朱朱朱    时间: 2012-6-29 20:32
你提取了中线吗?提取中线在远处的时候左右边的差值很小字母办

作者: 璺鋈    时间: 2012-6-29 20:38
朱朱朱 发表于 2012-6-29 20:32
你提取了中线吗?提取中线在远处的时候左右边的差值很小字母办

直接舍弃采用上一场的值,现在我们的判断策略是连续的五行采集错误就认为是急弯,系数调大尽量打死

作者: 蜈蚁蝗    时间: 2012-9-7 19:27

作者: chlhyj    时间: 2012-10-17 13:27

作者: 林的0922    时间: 2013-3-30 19:46

作者: HIT120220    时间: 2013-4-25 14:13
请问二值化以后的数据怎么形成的图啊?你的第二张图
作者: 深情、一回头    时间: 2013-6-4 23:20
璺鋈 发表于 2012-6-29 20:20
当然不行才在这儿问题呢  还有一个问题   请问你知道为什么有一场的数据会发生上下两部分颠调的情况啊    ...

这好像是行场中断时序问题吧  我貌似也出现过  不知道怎么又好了
作者: master“小军“    时间: 2016-11-1 19:08
程序想法可以参考一下




欢迎光临 智能车制作 (http://111.231.132.190/) Powered by Discuz! X3.2