获取特征
在进行第一遍扫线后,我们当然希望能够尽可能的获取图像的特征,让我们对于当前的图像有个大体的认识,方便我们进行特殊元素的判断。
因此在第一遍扫线结束后,我对获取的左线,右线和中线进行处理,获得如下的特征:
Left_lian[i]//左线第i行到第几行之间是连续的
Right_lian[i]//右线第i行到第几行之间是连续的
L_start//左线最小的非丢线行
R_start//右线最小的非丢线行
low_lose_number//前20行丢线行数
Left_lose[i]//左线到第i行为止的丢线数
Right_lose[i]//右线到第i行为止的丢线数
Left_lose_sum//左线的总丢线数
Right_lose_sum//右线的总丢线数
variance_Left//左线方差
variance_Right//右线方差
variance_Left_40 //左线方差超过40的行数
variance_Right_40 //右线方差超过40的行数
variance_LCenter_40 //中线方差超过40行数
取斜率函数
这个函数用的是比较多的,其实就是最小二乘法求出斜率之后记录下来
byte Get_stright_line(byte rec_1, byte end_1, byte rec_2, byte end_2, byte type)//最小二乘法拟合直线
{
if (rec_1 < 0) rec_1 = 0;
if (end_1 < 0) end_1 = 0;
if (rec_2 < 0) rec_2 = 0;
if (end_2 < 0) end_2 = 0;
byte n = 0;
int x_add = 0;
int y_add = 0;
int xy_add = 0;
int xx_add = 0;
if (type == 0)
{
for (byte i = rec_1; i < 60 && i < end_1; i++)
{
x_add += i;
y_add += L_black[i];
xx_add += i * i;
xy_add += i * L_black[i];
n++;
}
for (byte i = rec_2; i < 60 && i < end_2 && i > end_1; i++)
{
x_add += i;
y_add += L_black[i];
xx_add += i * i;
xy_add += i * L_black[i];
n++;
}
}
else if (type == 1)
{
for (byte i = rec_1; i < 60 && i < end_1; i++)
{
x_add += i;
y_add += R_black[i];
xx_add += i * i;
xy_add += i * R_black[i];
n++;
}
for (byte i = rec_2; i < 60 && i < end_2 && i > end_1; i++)
{
x_add += i;
y_add += R_black[i];
xx_add += i * i;
xy_add += i * R_black[i];
n++;
}
}
else if (type == 2)
{
for (byte i = rec_1; i < 60 && i < end_1; i++)
{
x_add += i;
y_add += LCenter[i];
xx_add += i * i;
xy_add += i * LCenter[i];
n++;
}
for (byte i = rec_2; i < 60 && i < end_2 && i > end_1; i++)
{
x_add += i;
y_add += LCenter[i];
xx_add += i * i;
xy_add += i * LCenter[i];
n++;
}
}
double x_bar = x_add * 1.0 / n;
double y_bar = y_add * 1.0 / n;
double xx_bar = xx_add * 1.0 / n;
double xy_bar = xy_add * 1.0 / n;
if (n < 2)
{
if (type == 0)
{
curve_a = k_left;
curve_b = b_left;
}
else if (type == 1)
{
curve_a = k_right;
curve_b = b_right;
}
else
{
curve_a = k_left + k_right;
curve_b = (b_right + b_left) / 2;
}
return n;
}
curve_a = (float)((xy_bar - x_bar * y_bar) / (xx_bar - x_bar * x_bar)); //拟合直线斜率
curve_b = (float)(y_bar - curve_a * x_bar);//拟合直线的常数项
return n;
}
求方差函数
求方差用的其实就是最小二乘法
首先取一段边线得到左线的斜率,之后求方差
int Get_variance(byte type)//求方差
{
if (type == 0) Get_stright_line(L_start, (byte)(Lose_line * 0.80), 68, 68, type);
else if (type == 1) Get_stright_line(R_start, (byte)(Lose_line * 0.80), 68, 68, type);
else if (type == 2) Get_stright_line(15, 27, 68, 68, type);
if (type == 0)
{
k_left = curve_a;
b_left = curve_b;
}
else if (type == 1)
{
k_right = curve_a;
b_right = curve_b;
}
else if (type == 2)
{
k_middle = curve_a;
b_middle = curve_b;
}
double ans = 0;
for (byte i = 0; i < Lose_line && i < 55; i++)
{
int num = (int)(curve_a * i + curve_b);
if (num > 185) num = 185;
if (num < 0) num = 0;
if (type == 0) ans += (float)(L_black[i] - num) * (L_black[i] - num) / Lose_line;
else if (type == 1) ans += (float)(R_black[i] - num) * (R_black[i] - num) / Lose_line;
else if (type == 2) ans += (float)(LCenter[i] - num) * (LCenter[i] - num) / Lose_line;
if (ans > 10000) break;
if (ans > 40 && variance_Left_40 == 68 && type == 0)
{
variance_Left_40 = i;
// SetText("左超40点" + variance_Left_40);
}
if (ans > 40 && variance_Right_40 == 68 && type == 1)
{
variance_Right_40 = i;
// SetText("右超40点" + variance_Right_40);
}
if (ans > 40 && variance_LCenter_40 == 68 && type == 2)
{
variance_LCenter_40 = i;
// SetText("中线超40" + variance_LCenter_40);
}
}
return (int)ans;
}
完整代码
void image_get_data()
{
for (byte i = 0; i < 69; i++)
{
if (i > 1)
{
if (my_abs(my_abs(L_black[i], L_black[i - 1]), my_abs(L_black[i - 1], L_black[i - 2])) < 3
|| (my_abs(my_abs(L_black[i], L_black[i - 1]), my_abs(L_black[i], L_black[i + 1])) < 3 && my_abs(L_black[i], L_black[i - 1]) < number_lian)) Left_lian[i] = Left_lian[i - 1];
else Left_lian[i] = i;
if (my_abs(my_abs(R_black[i], R_black[i - 1]), my_abs(R_black[i - 1], R_black[i - 2])) < 3
|| (my_abs(my_abs(R_black[i], R_black[i - 1]), my_abs(R_black[i], R_black[i + 1])) < 3 && my_abs(R_black[i], R_black[i - 1]) < number_lian)) Right_lian[i] = Right_lian[i - 1];
else Right_lian[i] = i;
}
if ((L_black[i] != 185 || i > Lose_line) && L_start == 69) L_start = i;
if ((R_black[i] != 0 || i > Lose_line) && R_start == 69) R_start = i;
if (i <= 20 && L_black[i] == 185 && R_black[i] == 0) low_lose_number++;
if (i != 0) Left_lose[i] = Left_lose[i - 1];
if (i != 0) Right_lose[i] = Right_lose[i - 1];
if (L_black[i] == 185 && i < Lose_line)
{
Left_lose[i]++;
Left_lose_sum++;
}
if (R_black[i] == 0 && i < Lose_line)
{
Right_lose[i]++;
Right_lose_sum++;
}
}
variance_Left = Get_variance(0);
variance_Right = Get_variance(1);
}