📄 黑线提取(浙江大学参考).cpp
字号:
//思路:遇到交叉道上找到与原来已经找到的线偏差最小的线(十字交叉道问题)
char FindCenter(void)
{
int tmp,residual;
int extra=0; //前方黑线的增减值,这是用来做什么的?
int black=0; //黑线等于0
char i,j,p,q,k,lose_flg;
char distance=0; //黑线宽度
char interval=20; //相邻两行的跳变
//int BlackNumber;
char L_column=0; //黑线左侧坐标 从左至右搜索
char R_column=0; //黑线右侧坐标
char L_column2=0; //黑线左侧坐标 从右至左搜索
char R_column2=0; //黑线右侧坐标
char L_next=0; //搜索尾部使用
char R_next=0; //搜索尾部使用
char tolance=8; //断线可以忍受的最长距离
char min_column=0;
int temp_error; //纠正系数,断线后纠正系数
int error[ROW]; //存储错误的行
lose_flg=0; //丢失的标志
S_falg=0;
for(i=ROW-1;i>=40;i--) //表示从尾行开始遍历
{
//BlackNumber=15-(ROW-i)*5/ROW;
//黑线左右坐标初始化
L_column=-1;
R_column=-1;
L_next=-1;
R_next=-1;
for(k=1;k<COLUMN;k++) //从左边第一列开始
{
for(j=k;j<COLUMN;j++) //从当前列开始
{
if((img[i][j])<=100 && img[i-1][j]<=100 && img[i-2][j]<=100)
//连续三行同列的数据均小于阙值,表示在底部找到了连续三行黑点的位置
{
L_next=j; //从左边记录出现此情况的列数
break;
}
}
for(j++;j<COLUMN;j++) //注意分析清楚L_NEXT和R_NEXT的作用,貌似很重要
{
if((img[i][j])>100 || (img[i-1][j])>100 || (img[i-2][j])>100) //向右移动一行,连续三行出现白线
//即:向右移动直至出现白线的情况
{
R_next=j-1; //记录下黑线右边沿
break;
}
}
if(R_next==-1&&L_next!=-1) //have L_next ,but no R_next
//表示没有黑线右边沿
R_next=COLUMN-1; //直接赋值
if(R_next-L_next>=15 || L_next==-1 || R_next-L_next<=0) //不符合要求,进行黑线宽度限定
continue;
else if(R_next-L_next>distance) //大于0
{
R_column=R_next; //黑线左边宽度确定
L_column=L_next; //黑线右边宽度确定
distance=R_next-L_next; //distance确定,本行黑线宽度
}
}
if(distance>2 && distance<15) //在合适的范围内
break;
}
min_column=(L_column+R_column)/2; //
if(i>40) tail=i; //在23行以下,且在5行以上
else return -1; //do not find center
path[tail]=min_column;
distance=15; //黑线宽度
if((R_column==COLUMN-1 || L_column==1/* */||L_column==0) && distance<10)
distance=15;
for(i--;i>0;i--) //再往上搜
{
if(lose_flg==0)
{
p=L_column-8;//-5
q=R_column+8; //+5
if(p<0) p=0;
if(q>=COLUMN) q=COLUMN-1;
}
else
{
p=p-1;
q=q+1;
if(p<0)
p=0;
if(q>=COLUMN)
q=COLUMN-1;
}
L_column=-1;
R_column=-1;
//从左往右搜
//search_flag=0
if(i<=30)
extra=15;
else
extra=0;
for(j=p;j<=q;j++)
{
if(img[i][j]<=BALCKPOINT+extra) //wh
{
L_column=j;
break;
}
} //往上搜
for(j++;j<=q;j++)
{
if(img[i][j]>BALCKPOINT+extra)
{
R_column=j-1;
break;
}
}
if(L_column!=-1&&R_column==-1)
{
for(j=q;j<COLUMN;j++)
if(img[i][j]>BALCKPOINT+extra)
break;
R_column=j-1;
}
if(L_column==p)//L_column is at the most left point,search for the first black
point
{
for(j=p;j>=0;j--)
if(img[i][j]>BALCKPOINT+extra)
break;
L_column=j+1;
}//如果P是黑点,在继续往前搜
//从左往右搜结束
//记录数据
L_column2=-1;
R_column2=-1;
//从右往左搜
for(j=q;j>=p;j--)
{
if(img[i][j]<=BALCKPOINT+extra) //wh
{
R_column2=j;
break;
}
} //往上搜
for(j--;j>=p;j--)
{
if(img[i][j]>BALCKPOINT+extra)
{
L_column2=j+1;
break;
}
}
/****************************************/
if(R_column2!=-1&&L_column2==-1)
{
for(j=p;j>=0;j--)
if(img[i][j]>BALCKPOINT+extra)
break;
L_column2=j+1;
}
/******************************************/
if(R_column2==q)//L_column is at the most left point,search for the first black
point
{
for(j=q;j<COLUMN;j++)
if(img[i][j]>BALCKPOINT+extra)
break;
R_column2=j-1;
}//如果P是黑点,在继续往前搜
//从右往左搜结束
//左右已采稳
tmp=-1;
min_column=(R_column+L_column)/2;
if(L_column!=-1&&L_column2!=-1&&R_column!=-1&&R_column2!=-1&&(R_column!=R_colum
n2||L_column!=L_column2))
{
if(fabs((L_column+R_column)/2-path[i+1+lose_flg])>fabs((L_column2+R_column2)/2-
path[i+1+lose_flg]) )
{
min_column=(R_column2+L_column2)/2;
R_column=R_column2;
L_column=L_column2;
}
}
if(R_column-L_column<=(distance+5<15 ? distance+5:15)
&&R_column-L_column>=0 && min_column-path[i+1+lose_flg]<=10 &&
min_column-path[i+1+lose_flg]>=-10&& L_column!=-1)
{
path[i]=min_column;
while(lose_flg>0)
{
path[i+lose_flg]=(path[i]+path[i+lose_flg+1])/2;
lose_flg--;
}
interval=path[i]-path[i+1];
//////////////////////////////////////////////////WH
distance=R_column-L_column;
/***********************************************/
}
else
{
report_data("R_column-L_column-distance",R_column-L_column-distance);
report_data("path[tail]",path[tail]);
report_data("path[i+1+lose_flg]",path[i+1+lose_flg]);
report_data("path[i]",min_column);
if(i<=30)
tolance=6-(40-i)/10;
else
tolance=6;
lose_flg++;
if(lose_flg>=tolance)
break;
}
}
head=i+1+lose_flg;
report_data("head",head);
i=getchar();
if(i=='a')
report_img();
if(StartOn)
find_start();
if(!S_falg)
inc_lose();
for(i=head;i<=tail;i++) //图像修正
{
path[i]=(path[i]-CENTER_WH)*(i*i/4-29*i+950)/100;
}
return tail-head+1;
}
void find_start()
{
unsigned char i;
char j=0;
char p=0;
char q=0;
char n=0;
char LeftFlg=0;
char RightFlg=0;
char BlackFlg=0;
S_falg=0;
if(head+2>20)
n=head+2;
else
n=20;
for(i=tail;i>=n;i--)
{
p=path[i]-15;
q=path[i]+15;
if(p<0)
p=0;
if(q>=COLUMN)
q=COLUMN-1;
LeftFlg=0;
RightFlg=0;
BlackFlg=0;
/* for(j=0;j<10&&(p+j)<path[i]-10&&(q-j)>path[i]+10;j++)
{
if((img[i][p+j]&0x02)+(img[i-1][p+j]&0x02)+(img[i-2][p+j]&0x02)<=4 &&
(img[i][q-j]&0x02)+(img[i-1][q-j]&0x02)+(img[i-2][q-j]&0x02)<=4)
BlackFlg++;
else
BlackFlg=0;
if(BlackFlg>=3)
{
p=p+j;
q=q-j;
break;
}
} */
for(j=p;j<path[i]-7;j++)
if(Is_Black_Point(i,j))
{
BlackFlg++;
p=j;
break;
}
for(j=q;j>path[i]+7;j--)
if(Is_Black_Point(i,j))
{
BlackFlg++;
q=j;
break;
}
// if(Is_Black_Point(i,p) && Is_Black_Point(i,q))
// BlackFlg=1;
//if((img[i][p]&0x02)+(img[i-1][p]&0x02)+(img[i-2][p]&0x02)<=4 &&
(img[i][q]&0x02)+(img[i-1][q]&0x02)+(img[i-2][q]&0x02)<=4)
// BlackFlg=1;
if(BlackFlg>=2)
{
while(!Is_While_Point(i,p) && p<path[i]-2) p++;
while(Is_While_Point(i,p) && p<path[i])
{
LeftFlg++;
p++;
}
while(!Is_While_Point(i,q) && q>path[i]+2) q--;
while(Is_While_Point(i,q) && q>path[i])
{
q--;
RightFlg++;
}
if(LeftFlg>0 && RightFlg>0 && fabs(LeftFlg-RightFlg)<=4 &&
(Is_While_Point(i,1) || Is_While_Point(i,COLUMN-2)))
{
S_falg=1;
// PWMDTY23=0;
// report_data("i",i);
// report_img();
break;
}
}
}
if(!S_falg)
return;
if(lose_start==((int)start_line)*200)// 第 n 次看到起点
{
start_line++;
lose_start++;
if(start_line==rap)
EndFlg=1;
}
}
char Is_Black_Point(int i,int j)
{
if(img[i][j]<=120 || img[i-1][j]<=120 || img[i+1][j]<=120)
return 1;
else
return 0;
}
char Is_While_Point(int i,int j)
{
if(img[i][j]>=140 && img[i-1][j]>=140 && img[i+1][j]>=140)
return 1;
else
return 0;
}
void inc_lose(void)
{
if(lose_start<start_line*200 && lose_start!=0)
{
lose_start++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -