智能车校内赛图像处理

本文介绍了参与北科大智能车校内赛时的图像处理方法,主要基于区域生长思想,寻找最大连通区域。算法着重处理了正十字、斜十字、近弯和远弯等情况,通过寻找拐点并拟合直线来补全图像。在正十字中,根据拐点数量判断是十字前还是中,并补全缺失的线段。对于弯道,通过比较左右边界与理想中心线的距离来识别近弯和远弯。此外,还提出了一种更稳定的补线思路,即通过记录直道时的边界距离来适应各种道路情况。
摘要由CSDN通过智能技术生成

写在最前面:

想不到这么久的文章还有人看,现在回头看自己的代码,觉得写的实在拙劣,诸位后来者看个笑话即可,感谢!

声明:

由于学校代码不宜外泄,本文目的也只是记录生活、分享思路,故将除了变量申明部分保留了一部分外,所有组委会例程代码均被删除,在文中也有标记,剩下部分均为博主自己写出,应该不涉及保密。真有来学习的(不会真有人来吧)同学别看糊涂了。

正文:

博主参加的是北科21年的智能车校内赛,处理方法都是在提供的例程基础上添加的。例程使用的都是【区域生长】思想的搜索框架。基本上都是选用了【最大连通区域】进行主区域的搜索。

以下分享本次我对图像的处理代码,供大家参考学习。注意,每辆车的处理都不完全一样,请主要关注处理思路。而且在结束之后,我才找到一种更为稳定的补线思路。我将放在文末与各位分享。

#include "search.h"

/********	变量声明  ********/
uint8        video_ori[MAX_VIDEO_LINE][MAX_VIDEO_POINT];  //图像原始数据,video_ori[m][n]代表图像的从下数第m行,从左数第n点,0为最黑,255为最白
//==============================图像数据================================//
Int16_point  g_CenterPosition[MAX_POINT_NUM];//中心点数组,下标代表第几个,存储相应中心点的坐标值
Int16_point  g_LeftEdge[MAX_POINT_NUM], g_RightEdge[MAX_POINT_NUM];//左、右边界点数组,下标代表第几个,存储相应边界点的坐标值
float        g_LeftDown_x, g_LeftDown_y, g_LeftUp_x, g_LeftUp_y, g_RightDown_x, g_RightDown_y, g_RightUp_x, g_RightUp_y;//左下、左上、右下、右上拐点数据
int          g_CenterNum;//中心点个数
int			 g_ImageLine,g_sum;
int			 g_Display,DirectionControlLine,DirectionControlWhole;//加权计算控制中心中的权值和项; 加权计算控制中心中的加权和项
int          g_LeftEdgeNum, g_RightEdgeNum;//图像识别结束后为左、右边界点个数
//==============================图像处理用变量==========================//
uint16       g_Start[10], g_End[10], g_SEnum;   //存放当前行各白块起始、结束位置的数组,下标为10意味着每行最多10个白块;白块计数器
uint8        g_SearchFlag=1;//区分当前是否在搜索第一行,值为1表明正在搜索第一行,否则为其余行
int          g_Cover;//白块联通长度
uint8        g_CoverIndex[10],g_CoverNum;//;当前行与前一行左右边界对应白块有重合的白块数
int         banma = 0;
//==============================新添的变量==============================//
int a = 0;
float b = 0;
double c = 0;
//======================================================================//

/*********	search:处理数据即测试算法的函数 ********/
void search()
{	
	g_LeftEdgeNum=0; g_RightEdgeNum=0;
	g_SearchFlag=1;
	int i,line, white_width = 0;
	/*int IMAGE_MIDDLE;
	int j;*//*用于大津法*/

    //=======================图像识别=========================//
	//PS:此时我们的图像已经提取完毕 我们从底部开始,向上识别图像
	//图像识别数据初始化

	//大津法(效果不好,故暂时注释掉)
	//int width = MAX_VIDEO_POINT;
	//int height = MAX_VIDEO_LINE;
	//int pixelCount[GrayScale] = { 0 }; //每个灰度值所占像素个数
	//float pixelPro[GrayScale] = { 0 };//每个灰度值所占总像素比例
	//int pixelSum = width * height; //总像素

	//uint8 * data = video_ori[MAX_VIDEO_LINE]; //指向像素数据的指针

	// //统计灰度级中每个像素在整幅图像中的个数
	//for (i = 0; i < height; i++)
	//{
	//	for (j = 0; j < width; j++)
	//	{
	//		pixelCount[(int)video_ori[i][j]]++; //将像素值作为计数数组的下标
	//	}
	//}

	计算灰度集中每个像素在整幅图像中的比例
	//for (i = 0; i < GrayScale; i++)
	//{
	//	pixelPro[i] = (float)pixelCount[i] / pixelSum;
	//}

	遍历灰度级[0,255]
	//float wf, wb, uftmp, ubtmp, uf, ub, u, deltaTmp, deltaMax = 0;
	//for (i = 0; i < GrayScale; i++) // i作为阈值
	//{
	//	wf = wb = uftmp = ubtmp = uf = ub = u = deltaTmp = 0;

	//	for (j = 0; j < GrayScale; j++)
	//	{
	//		if (j <= i) //背景部分
	//		{
	//			wb += pixelPro[j];//背景像素点占整个图像的比例
	//			ubtmp += j * pixelPro[j];
	//		}
	//		else //前景部分
	//		{
	//			wf += pixelPro[j];//前景像素点占整个图像的比例
	//			uftmp += j * pixelPro[j];
	//		}
	//	}

	//	ub = ubtmp / wb;//背景平均灰度μ0
	//	uf = uftmp / wf;//前景平均灰度μ1

	//	deltaTmp = (float)(wb * wf * (ub - uf)*(ub-uf)); //类间方差公式 g = w1 * w2 * (u1 - u2) ^ 2
	//	if (deltaTmp > deltaMax)
	//	{
	//		deltaMax = deltaTmp;
	//		IMAGE_MIDDLE = i;
	//	}
	//}
	//
	
	g_CenterNum = 0;
	g_LeftEdgeNum = 0;
	g_RightEdgeNum = 0;
	g_SearchFlag=1;
	int banmajishu = 0;
    

//注意,此处删除了寻找画面白块部分!!!!!!!
//下面开始正式补线

	int r_down_flag = 0;//右下拐点标志
	int r_up_flag = 0;//右上拐点标志
	int l_down_flag = 0;//左下拐点标志
	int l_up_flag = 0;//左上拐点标志
	int l_xie_crossroad_jin = 0;//近左斜标志
	int r_xie_crossroad_jin = 0;//近右斜标志
	int straightway = 0;//直道标志
	int before_crossroad = 0;//正十字前标志
	int ing_crossroad = 0;//正十字中标志
	int l_xie_crossroad_yuan = 0;//远左斜标志
	int r_xie_crossroad_yuan = 0;//远右斜标志
	int ing_crossroad_pd = 0;//正十字中与弯道离奇拐点、远斜十字判别标志
	for (i = 0; i < 20; i++)
	{
		if (video_ori[i][0] > IMAGE_MIDDLE && video_ori[i][161] > IMAGE_MIDDLE)
		{
			ing_crossroad_pd++;
		}
	}
	for (i = 5; i < 50; i++)//判断上面拐点类型
	{
		if (g_RightEdge[i].y - g_RightEdge[i + 1].y < 5 && g_RightEdge[i-1].y - g_RightEdge[i].y > 5 && g_RightEdge[i - 2].y - g_RightEdge[i].y > 10 && g_LeftEdge[i - 10].y < 20)
		{
			r_up_flag = 1;
			g_RightUp_x = i;
			g_RightUp_y = g_RightEdge[i].y;
			//break;
			/*printf("%d\n",2);*/
		}
		if (g_LeftEdge[i+1].y - g_LeftEdge[i].y < 5 && g_LeftEdge[i].y - g_LeftEdge[i - 1].y > 5 && g_LeftEdge[i].y - g_LeftEdge[i - 2].y > 10 && g_RightEdge[i - 10].y > 140)
		{
			l_up_flag = 1;
			g_LeftUp_x = i;
			g_LeftUp_y = g_LeftEdge[i].y;
			//break;
			/*printf("%d\n",4);*/
		}
	}
	for (i = 7; i < 40; i++)//判断下面拐点类型
	{
		if (g_RightEdge[i+1].y - g_RightEdge[i].y > 5 && g_RightEdge[i+2].y - g_RightEdge[i].y > 10 && g_RightEdge[i-1].y - g_RightEdge[i].y < 5 && g_RightEdge[i - 4].y - g_RightEdge[i].y >= 0)
		{
			r_down_flag = 1;
			g_RightDown_x = i;
			g_RightDown_y = g_RightEdge[i].y;
			//break;
			/*printf("%d\n",1);*/
		}
		if (g_LeftEdge[i].y - g_LeftEdge[i + 1].y > 5 && g_LeftEdge[i].y - g_LeftEdge[i + 2].y > 10 && g_LeftEdge[i].y - g_LeftEdge[i - 1].y < 5 && g_LeftEdge[i].y - g_LeftEdge[i - 4].y >= 0)
		{
			l_down_flag = 1;
			g_LeftDown_x = i;
			g_LeftDown_y = g_LeftEdge[i].y;
			/*if (g_LeftDown_y > 81)
			{
				l_down_flag = 0;
			}*/
		}
	}
	if (r_down_flag == 1 && r_up_flag == 1 && l_down_flag == 0 && l_up_flag == 0)
	{
		l_xie_crossroad_jin = 1;
	}
	else if (r_down_flag == 0 && r_up_flag == 0 && l_down_flag == 1 && l_up_flag == 1)
	{
		r_xie_crossroad_jin = 1;
	}
	else if (r_down_flag == 1 && r_up_flag == 1 && l_down_flag == 1 && l_up_flag == 1)
	{
		before_crossroad = 1;
	}
	else if (r_down_flag == 0 && r_up_flag == 1 && l_down_flag == 0 && l_up_flag == 1 && ing_crossroad_pd > 10)
	{
		ing_crossroad = 1;
	}
	else 
	{
		r_down_flag = 0, r_up_flag = 0, l_down_flag = 0, l_up_flag = 0;
	}

	
	if (r_down_flag == 0 && r_up_flag == 0 && l_down_flag == 0 && l_up_flag == 0 && l_xie_crossroad_jin == 0 && r_xie_crossroad_jin == 0)//远斜十字拐点判别
	{
		for (i = 0; i < 55; i++)
		{
			if (g_LeftEdge[i + 1].y == 0 && g_RightEdge[i - 1].y > g_RightEdge[i + 1].y && g_RightEdge[i + 2].y > g_RightEdge[i + 1].y && g_RightEdge[i + 1].y < 155 && g_RightEdge[i - 1].y < 155 && g_RightEdge[i + 2].y < 155)
			{
				r_down_flag = 1;
				g_RightDown_x = i + 1;
				g_RightDown_y = g_RightEdge[i + 1].y;
			}
			if (g_LeftEdge[i].y == 0 && g_LeftEdge[i + 1].y == 0 && g_LeftEdge[i + 2].y != 0 && g_LeftEdge[i + 3].y != 0 && g_LeftEdge[i + 2].y > 10)
			{
				r_up_flag = 1;
				g_RightUp_x = i + 2;
				g_RightUp_y = g_LeftEdge[i + 2].y;
			}
			if (g_RightEdge[i + 1].y == 161 && g_LeftEdge[i - 1].y < g_LeftEdge[i + 1].y && g_LeftEdge[i + 2].y < g_LeftEdge[i + 1].y && g_LeftEdge[i + 1].y > 5 && g_LeftEdge[i -1].y > 5 && g_LeftEdge[i + 2].y > 5)
			{
				l_down_flag = 1;
				g_LeftDown_x = i + 1;
				g_LeftDown_y = g_LeftEdge[i + 1].y;
			}
			if (g_RightEdge[i].y == 161 && g_RightEdge[i + 1].y == 161 && g_RightEdge[i + 2].y != 161 && g_RightEdge[i + 3].y != 161 && g_RightEdge[i + 2].y < 151)
			{
				l_up_flag = 1;
				g_LeftUp_x = i + 2;
				g_LeftUp_y = g_RightEdge[i + 2].y;
			}
		}

	}
	
	int x_d = 0, x_u = 0;
	int r_turn_pd = 0;
	int l_turn_pd = 0;
	int r_near_turn = 0;//右近弯标志
	int r_far_turn = 0;//右远弯标志
	int l_near_turn = 0;//左近弯标志
	int l_far_turn = 0;//左远弯标志
	int r_turn_fuzhu = 0;
	int l_turn_fuzhu = 0;
	for (i = 0; i < 60; i++)
	{
		if (g_LeftEdge[i].y == 0 && g_RightEdge[i].y < 161 && g_RightEdge[i].y < g_RightEdge[i - 1].y)
		{
			l_turn_pd++;
		}
		if (g_RightEdge[i].y == 161 && g_LeftEdge[i].y > 0 && g_LeftEdge[i].y > g_LeftEdge[i - 1].y)
		{
			r_turn_pd++;
		}
		if (g_LeftEdge[i].y == 0)
		{
			l_turn_fuzhu++;
		}
		if (g_RightEdge[i].y == 161)
		{
			r_turn_fuzhu++;
		}
	}
	if (l_turn_pd > 30 && video_ori[l_turn_pd][100]< IMAGE_MIDDLE/*&& r_turn_fuzhu < 10*/)
	{
		l_near_turn = 1;
	}
	if (l_turn_pd > 10 && l_turn_pd < 30 && l_turn_fuzhu-l_turn_pd<8)
	{
		l_far_turn = 1;
	}
	if (r_turn_pd > 30 && video_ori[r_turn_pd][60] < IMAGE_MIDDLE/*&& l_turn_fuzhu < 10*/)
	{
		r_near_turn = 1;
	}
	if (r_turn_pd > 10 && r_turn_pd < 30 && r_turn_fuzhu-r_turn_pd<8)
	{
		r_far_turn = 1;
	}
	if (l_far_turn == 1 && r_far_turn == 1)
	{
		l_far_turn = 0;
		r_far_turn = 0;
	}
	
	
	if (l_far_turn == 1)
	{
		for (i = 20; i < 55; i++)
		{
			if (g_LeftEdge[i].y == 0 && g_LeftEdge[i - 1].y > 0)
			{
				x_d = i;
			}
			if (g_LeftEdge[i].y == 0 && g_LeftEdge[i + 1].y > 0)
			{
				x_u = i;
			}
		}
	}
	if (r_far_turn == 1)
	{
		for (i = 25; i < 55; i++)
		{
			if (g_RightEdge[i].y == 161 && g_RightEdge[i - 1].y < 161)
			{
				x_d = i;
			}
			if (g_RightEdge[i].y == 161 && g_RightEdge[i + 1].y < 161)
			{
				x_u = i;
			}
		}
		/*for (i = x_d; i < 55; i++)
		{
			if (g_RightEdge[i].y == 161 && g_RightEdge[i + 1].y < 161)
			{
				x_u = i;
			}
		}*/
	}
	if (x_d == 0 && x_u == 0)
	{
		l_far_turn = 0;
		r_far_turn = 0;
	}

	
	if (r_down_flag == 0 && r_up_flag == 0 && l_down_flag == 0 && l_up_flag == 0)
	{
		straightway = 1;
	}
	else if (r_down_flag == 1 && r_up_flag == 1 && l_down_flag == 0 && l_up_flag == 0 && l_xie_crossroad_jin == 0)
	{
		l_xie_crossroad_yuan = 1;
	}
	else if (r_down_flag == 0 && r_up_flag == 0 && l_down_flag == 1 && l_up_flag == 1 && r_xie_crossroad_jin == 0)
	{
		r_xie_crossroad_yuan = 1;
	}
	if (l_near_turn == 1 && l_xie_crossroad_jin == 1)
	{
		l_xie_crossroad_jin = 0;
	}
	if (r_near_turn == 1 && r_xie_crossroad_jin == 1)
	{
		r_xie_crossroad_jin = 0;
	}

	int l_ku = 0;
	int r_ku = 0;
	int l_ku_qian = 0;
	int l_ku_zhong = 0;
	int l_ku_hou = 0;
	int r_ku_qian = 0;
	int r_ku_zhong = 0;
	int r_ku_hou = 0;
	if (banma == 1)
	{
		l_down_flag = 0;
		l_up_flag = 0;
		r_down_flag = 0;
		r_up_flag = 0;
		int r_ku_pd = 0;
		int l_ku_pd = 0;
		for (i = 0; i < 60; i++)
		{
			if (g_LeftEdge[i].y == 0)
			{
				l_ku_pd++;
			}
			if (g_RightEdge[i].y == 161)
			{
				r_ku_pd++;
			}
		}
		if (l_ku_pd > r_ku_pd)
		{
			l_ku = 1;
		}
		else
		{
			r_ku = 1;
		}
		if (l_ku == 1)
		{
			for (i = 0; i < 30; i++)
			{
				if (g_LeftEdge[i - 1].y < g_LeftEdge[i + 1].y && g_LeftEdge[i + 2].y < g_LeftEdge[i + 1].y)
				{
					l_down_flag = 1;
					g_LeftDown_x = i + 1;
					g_LeftDown_y = g_LeftEdge[i + 1].y;
				}
			}
			for (i = 55; i > 35; i--)
			{
				if (g_LeftEdge[i + 1].y - g_LeftEdge[i].y < 5 && g_LeftEdge[i].y - g_LeftEdge[i - 1].y > 5)
				{
					l_up_flag = 1;
					g_LeftUp_x = i;
					g_LeftUp_y = g_LeftEdge[i].y;
				}
			}
			if (l_down_flag == 1 && l_up_flag == 1&&g_LeftDown_y<g_LeftUp_y)
			{
				l_ku_qian = 1;
			}
			if (l_ku_qian == 0 && l_up_flag == 1)
			{
				l_ku_zhong = 1;
			}
		}
		else if (r_ku == 1)
		{
			for (i = 0; i < 30; i++)
			{
				if (g_RightEdge[i - 1].y > g_RightEdge[i + 1].y && g_RightEdge[i + 2].y > g_RightEdge[i + 1].y)
				{
					r_down_flag = 1;
					g_RightDown_x = i + 1;
					g_RightDown_y = g_RightEdge[i + 1].y;
				}
			}
			for (i = 55; i > 38; i--)
			{
				if (g_RightEdge[i].y - g_RightEdge[i+1].y < 3 && g_RightEdge[i-1].y - g_RightEdge[i].y > 3)
				{
					r_up_flag = 1;
					g_RightUp_x = i;
					g_RightUp_y = g_RightEdge[i].y;
				}
			}
			if (r_down_flag == 1 && r_up_flag == 1&&g_RightUp_y<g_RightDown_y)
			{
				r_ku_qian = 1;
			}
			if (r_ku_qian == 0 && r_up_flag == 1)
			{
				r_ku_zhong = 1;
			}
		}
		r_near_turn = 0;
		l_near_turn = 0;
		r_far_turn = 0;
		l_far_turn = 0;
		r_xie_crossroad_yuan = 0;
		l_xie_crossroad_yuan = 0;
	}


	float b_r, k_r, b_l, k_l;//补线斜率和截距
	if (banma == 1)
	{
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
		for (i = 0; i < g_RightEdgeNum; i++)
		{
			g_CenterPosition[i].x = g_RightEdge[i].x;
			g_CenterPosition[i].y = 81;
		}
	}
	else if (before_crossroad == 1)//正十字前中心求取
	{
		k_r = (g_RightUp_y - g_RightDown_y) / (g_RightUp_x - g_RightDown_x);
		b_r = g_RightDown_y - k_r * g_RightDown_x;
		for (i = g_RightDown_x; i < g_RightUp_x + 1; i++)
		{
			g_RightEdge[i].y = k_r * g_RightEdge[i].x + b_r;
		}
		k_l = (g_LeftUp_y - g_LeftDown_y) / (g_LeftUp_x - g_LeftDown_x);
		b_l = g_LeftDown_y - k_l * g_LeftDown_x;
		for (i = g_LeftDown_x; i < g_LeftUp_x + 1; i++)
		{
			g_LeftEdge[i].y = k_l * g_LeftEdge[i].x + b_l;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (ing_crossroad == 1)//正十字中中心求取
	{
		k_r = (g_RightUp_y - 161) / g_RightUp_x;
		b_r = 161;
		for (i = 0; i < g_RightUp_x + 1; i++)
		{
			g_RightEdge[i].y = k_r * g_RightEdge[i].x +b_r;
		}
		k_l = g_LeftUp_y  / g_LeftUp_x ;
		b_l = 0;
		for (i = 0; i < g_LeftUp_x + 1; i++)
		{
			g_LeftEdge[i].y = k_l * g_LeftEdge[i].x;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (l_xie_crossroad_jin == 1)//近左斜十字中心求取
	{
		k_r = (g_RightUp_y - g_RightDown_y) / (g_RightUp_x - g_RightDown_x);
		b_r = g_RightDown_y - k_r * g_RightDown_x;
		for (i = g_RightDown_x; i < g_RightUp_x + 1; i++)
		{
			g_RightEdge[i].y = k_r * g_RightEdge[i].x + b_r;
		}
		int left_create = g_RightUp_x;
		k_l = -k_r;
		b_l = g_LeftEdge[left_create].y - k_l * g_RightUp_x;
		for (i = left_create; i >= 0; i--)
		{
			g_LeftEdge[i].y = k_l * g_LeftEdge[i].x + b_l;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (r_xie_crossroad_jin == 1)//近右斜十字中心求取
	{
		k_l = (g_LeftUp_y - g_LeftDown_y) / (g_LeftUp_x - g_LeftDown_x);
		b_l = g_LeftDown_y - k_l * g_LeftDown_x;
		for (i = g_LeftDown_x; i < g_LeftUp_x + 1; i++)
		{
			g_LeftEdge[i].y = k_l * g_LeftEdge[i].x + b_l;
		}
		int right_create = g_LeftUp_x;
		k_r = -k_l;
		b_r = g_RightEdge[right_create].y - k_r * g_LeftUp_x;
		for (i = right_create; i >= 0; i--)
		{
			g_RightEdge[i].y = k_r * g_RightEdge[i].x + b_r;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (l_xie_crossroad_yuan == 1)//远左斜十字中心求取
	{
		k_r = (g_RightUp_y - g_RightDown_y) / (g_RightUp_x - g_RightDown_x);
		b_r = g_RightDown_y - k_r * g_RightDown_x;
		for (i = g_RightDown_x; i < g_RightUp_x + 1; i++)
		{
			g_RightEdge[i].y = k_r * g_RightEdge[i].x + b_r;
		}
		g_RightEdgeNum = g_RightUp_x;
		g_LeftEdgeNum = g_RightUp_x;
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = k_r * g_RightEdge[i].x + b_r / 2;
			}
	}
	else if (r_xie_crossroad_yuan == 1)//远右斜十字中心求取
	{
		k_l = (g_LeftUp_y - g_LeftDown_y) / (g_LeftUp_x - g_LeftDown_x);
		b_l = g_LeftDown_y - k_l * g_LeftDown_x;
		for (i = g_LeftDown_x; i < g_LeftUp_x + 1; i++)
		{
			g_LeftEdge[i].y = k_l * g_LeftEdge[i].x + b_l;
		}
		g_RightEdgeNum = g_LeftUp_x;
		g_LeftEdgeNum = g_LeftUp_x;
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_LeftEdge[i].x;
				g_CenterPosition[i].y = k_l * g_LeftEdge[i].x + (161 - b_l) / 2;
			}
	}
	else if (l_near_turn == 1)//左近弯中心求取
	{
		int left_pinyi = g_RightEdge[0].y;
		for (i = 0; i <= l_turn_pd; i++)
		{
			g_LeftEdge[i].y = g_RightEdge[i].y - left_pinyi - 2 * i;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (r_near_turn == 1)//右近弯中心求取
	{
		int right_pinyi = 161 - g_LeftEdge[0].y;
		for (i = 0; i <= r_turn_pd; i++)
		{
			g_RightEdge[i].y = g_LeftEdge[i].y + right_pinyi + 2 * i;
		}
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	else if (l_far_turn == 1)
	{
		g_CenterNum = g_RightEdgeNum;
		g_LeftEdgeNum = x_d;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i <= x_d; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
		k_l = -2 * g_CenterPosition[x_d].y / (x_u - x_d);
		b_l = -k_l * (x_d + x_u) / 2;
		for (i = x_d; i <= g_RightEdgeNum/*(x_d + x_u) / 2*/; i++)
		{
			g_CenterPosition[i].x = i;
			g_CenterPosition[i].y = k_l * i + b_l;
		}
	}
	else if (r_far_turn == 1)
	{
		g_CenterNum = g_LeftEdgeNum;
		g_RightEdgeNum = x_d;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i <= x_d; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
		k_r = 2 * (161 - g_CenterPosition[x_d].y) / (x_u - x_d);
		b_r = 161 - k_r * (x_d + x_u) / 2;
		for (i = x_d; i <= g_RightEdgeNum/*(x_d + x_u) / 2*/; i++)
		{
			g_CenterPosition[i].x = i;
			g_CenterPosition[i].y = k_r * i + b_r;
		}
	}
	//else if (l_ku_qian == 1)
	//{
	//	g_CenterNum = g_LeftUp_x;
	//	g_RightEdgeNum = g_LeftUp_x;
	//	g_LeftEdgeNum = g_LeftDown_x;
	//	DEBUG_VAR(g_CenterNum, d)
	//	int start = g_LeftDown_x;
	//	int end_x = (g_LeftDown_x + g_LeftUp_x) / 2;
	//	int end_y = (g_LeftDown_y + g_LeftUp_y) / 2;
	//	k_l = (g_RightEdge[start].y - g_LeftUp_y) / (start - g_LeftUp_x);
	//	b_l = g_LeftUp_y - k_l * g_LeftUp_x;
	//	for (i = start; i < g_LeftUp_x+1; i++)
	//	{
	//		g_RightEdge[i].y = k_l * i + b_l;
	//	}
	//	for (i = 0; i < start; i++)
	//	{
	//		g_CenterPosition[i].x = i;
	//		g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
	//	}
	//	for (i = start; i < g_LeftUp_x; i++)
	//	{
	//		g_CenterPosition[i].x = i;
	//		g_CenterPosition[i].y = (k_l-1) * i + b_l + 81 - g_RightEdge[start].y;
	//	}
	//	/*for (i = end_x; i < g_LeftUp_x; i++)
	//	{
	//		g_CenterPosition[i].x = i;
	//		g_CenterPosition[i].y =  -i + b_l + 81 - g_RightEdge[start].y;
	//	}*/
 //   }
	//else if (r_ku_qian == 1)
	//{
	//	g_CenterNum = g_RightUp_x;
	//	g_RightEdgeNum = g_RightDown_x;
	//	g_LeftEdgeNum = g_RightUp_x;
	//	DEBUG_VAR(g_CenterNum, d)
	//	int start = g_RightDown_x;
	//	//int end_x = (g_LeftDown_x + g_LeftUp_x) / 2;
	//	//int end_y = (g_LeftDown_y + g_LeftUp_y) / 2;
	//	k_r = (g_LeftEdge[start].y - g_RightUp_y) / (start - g_RightUp_x);
	//	b_r = g_RightUp_y - k_r * g_RightUp_x;
	//	for (i = start; i < g_RightUp_x + 1; i++)
	//	{
	//		g_LeftEdge[i].y = k_r * i + b_r;
	//	}
	//	for (i = 0; i < start; i++)
	//	{
	//		g_CenterPosition[i].x = i;
	//		g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
	//	}
	//	for (i = start; i < g_RightUp_x; i++)
	//	{
	//		g_CenterPosition[i].x = i;
	//		g_CenterPosition[i].y = (k_r + 1) * i + b_r + 81 - g_LeftEdge[start].y;
	//	}
	//}
	//else if (l_ku_zhong == 1)
	//{
	//	g_CenterNum = g_LeftUp_x;
	//	g_RightEdgeNum = g_LeftUp_x;
	//	g_LeftEdgeNum = g_LeftUp_x;
	//	DEBUG_VAR(g_CenterNum, d)
	//	k_l = (161 - g_LeftUp_y) / (-g_LeftUp_x);
	//	b_l = 161;
	//	for (i = 0; i < g_LeftUp_x; i++)
	//	{
	//		g_RightEdge[i].y = k_l * i + b_l;
	//		g_LeftEdge[i].y = k_l * i;
	//	}
	//	for (i = 0; i < g_LeftUp_x; i++)
	//	{
	//		g_CenterPosition[i].x = g_RightEdge[i].x;
	//		g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
	//	}
	//}
	//else if (r_ku_zhong == 1)
	//{
	//	g_CenterNum = g_RightUp_x;
	//	g_RightEdgeNum = g_RightUp_x;
	//	g_LeftEdgeNum = g_RightUp_x;
	//	DEBUG_VAR(g_CenterNum, d)
	//		k_r = g_RightUp_y / g_RightUp_x;
	//	for (i = 0; i < g_RightUp_x; i++)
	//	{
	//		g_LeftEdge[i].y = k_r * i;
	//		g_RightEdge[i].y = k_r * i + 161;
	//	}
	//	for (i = 0; i < g_RightUp_x; i++)
	//	{
	//		g_CenterPosition[i].x = g_RightEdge[i].x;
	//		g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
	//	}
	//}
	else
	{
		g_CenterNum = g_RightEdgeNum;
		DEBUG_VAR(g_CenterNum, d)
			for (i = 0; i < g_RightEdgeNum; i++)
			{
				g_CenterPosition[i].x = g_RightEdge[i].x;
				g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
			}
	}
	/*g_CenterNum = g_RightEdgeNum;
	DEBUG_VAR(g_CenterNum, d)
	for (i = 0; i < g_RightEdgeNum; i ++)
	{
		g_CenterPosition[i].x = g_RightEdge[i].x;
		g_CenterPosition[i].y = (g_RightEdge[i].y + g_LeftEdge[i].y) / 2;
	}*/

}

代码较长,而且图像处理是一个工程文件,这里给出的是search.c文件中内容,即主要的图像处理文件。通过以上代码可以较好地处理包括正十字、斜十字、左右弯道,可以勉强处理车库问题,但由于难以稳定,在上文给出的代码中就被我注释掉了。下面给出处理效果图:

处理思路:

1、正十字:不论是十字前还是十字中,都需要寻找拐点。

(1)找到四个拐点则为正十字中,左右两边分别用上下拐点拟合直线来补出缺线;

(2)找到上面两个拐点则为正十字中,左右分别用上拐点与(0,0)、(0,161)拟合直线来补出缺线。

2、斜十字:

(1)若只找到右边两个拐点,则为左斜十字中(两拐点离车近)。

(2)而左斜十字前,即两“拐点”离车远的情况则不同。在四个拐点都没找到且不为左右斜十字中时,重新扫线二次找拐点(换了要求)。找到右边两个拐点先补出直线,方法与上面类似。再为左边拟合一个镜像的直线,最后再求取中线得出。

(3)右斜十字的方法同上。

3、弯道:

(1)近弯:若判断为左近弯,那么右边边界不变,通过右边界平移出一个y值为负的左边界,之后两者求中值即可。右近弯方法同上。

(2)远弯:判断为左远弯后,扫线找出一个x_d值,在此之下依旧相加除以二,在此之上的中心线拟合为直线。

4、入库

通过找寻斑马线,找到斑马线后找拐点来补线。建议通过控制开环入库,简单好用。

更优处理

自己的思路是无论直道、弯道、还是正、斜十字和车库,都是识别出道路类型后,最后进行处理。但这样多重的识别势必需要不同的辨识点来分辨,最常用的就是拐点。道路类型一多,很容易造成“串道”,比如十字成了弯道、车库成了弯道等等。

为什么会这样呢?是因为采用的中心求取思路非常简单粗糙,因为之前在边沿搜索的时候并没有区分两边,而是直接把一个白块的start认为是左边,end认为是右边 故中心数将与左右边的数相等,而中心位置直接由左右边相加除2所得。

另一种思路,在小车处于直道正中央时,处理这时的图像,此时左右边界线与理想中心线距离时相等的,记录每一行这种边界线与理想中心线之间的距离组成一个数组,姑且称这些距离为视距。这样在处理直道和弯道时可以不用辨识,使用同一种处理方法。直道不必多说,找每一行距离左边界线或者右边界线视距的点,即为中心点;弯道也是类似,但我自己也不清楚了。给出下图,看看有没有天才自己悟出来,哈哈哈哈

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuxuxucq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值