【数字图像处理】霍夫变换——传统方法车道线检测C++

前言

利用霍夫变换提取图像中的直线, 具体代码如下所示。霍夫变换的原理在此不多赘述,重点想讲述一下直线筛选的过程。
由于霍夫变换之后得到的直线数量很多,为了得到符合条件的直线,我们有必要对直线进行一定的筛选。在 draw_lane()函数种对直线进行比较精确地筛选,首先根据车道线的淘汰画面中较为平行的直线,接着设定 rho 和 angle 的阈值,淘汰重复的直线,使得每条车道仅有一条直线保留。


应用

话不多说直接上代码

输入

传入的参数为cv::Mat img 和阈值 threshold
在我的车道线检测项目中传入边缘提取后的二值图像
【数字图像处理】霍夫变换——传统方法车道线检测C++_第1张图片

具体代码

std::vector<int> hough_line_detect(cv::Mat img, int threshold)
{
	int row, col;
	int i, k;
	//参数空间的参数极角angle(角度),极径p;
	int angle, p;
	//累加器
	int** socboard;
	int* buf;
	int w, h;
	w = img.cols;
	h = img.rows;
	int Size;
	int offset;
	std::vector<int> lines;
	//申请累加器空间并初始化
	Size = w * w + h * h;
	Size = 2 * sqrt(Size) + 100;
	offset = Size / 2;
	cout << "offset: " << offset << endl;
	socboard = (int**)malloc(Size * sizeof(int*));
	if (!socboard)
	{
		printf("mem err\n");
		return lines;
	}
	for (i = 0; i < Size; i++)
	{
		socboard[i] = (int*)malloc(181 * sizeof(int));
		if (socboard[i] == NULL)
		{
			printf("buf err\n");
			return lines;
		}
		memset(socboard[i], 0, 181 * sizeof(int));
	}
	//遍历图像并投票
	int src_data;
	p = 0;
	for (row = 0; row < img.rows; row++)
	{
		for (col = 0; col < img.cols; col++)
		{
			//获取像素点
			src_data = img.at<uchar>(row, col);
			if (src_data == 255)
			{
				for (angle = 0; angle < 181; angle++)
				{
					p = col * cos(angle * PI / 180.0) + row * sin(angle * PI /180.0) + offset;
					//错误处理
					if (p < 0)
					{
						printf("at (%d,%d),angle:%d,p:%d\n", col, row, angle, p);
						printf("warrning!");
						printf("size:%d\n", Size / 2);
						continue;
					}
				//投票计分
				socboard[p][angle]++;
				}
			}
		}
	}
	//遍历计分板,选出符合阈值条件的直线
	//int count = 0;
	int Max = 0;
	int kp, kt, r;
	kp = 0;
	kt = 0;
	for (i = 0; i < Size; i++)//p
	{
		for (k = 0; k < 181; k++)//角度0-180
		{
			if (socboard[i][k] > Max)
			{
				Max = socboard[i][k];
				kp = i - offset;
				kt = k;
			}
			if (socboard[i][k] >= threshold)
			{
				r = i - offset;
				lines.push_back(i - Size / 2);//rho
				lines.push_back(k);//angle
			}
		}
	}
	//释放资源
	for (int e = 0; e < Size; e++)
	{
		free(socboard[e]);
	}
	free(socboard);
	return lines;
}

效果

【注】threshold需要自己好好调一调

附录

  1. 查看完整车道线检测项目代码
  2. 查看完整车道线检测项目思路

你可能感兴趣的:(图像处理,计算机视觉,图像处理,c++)