opencv 简单的实现霍夫变换(改进版)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38204686/article/details/79321240
//霍夫变换  输入单通道二值图像 检测直线数量
void HoughLines(Mat &img,int n)
{
	int i,j;
	//行列
	int row = img.rows;
	int col = img.cols;

	//极径最大值为 对角线+宽
	int max_r = col + cvCeil (sqrt(double(row*row+col*col)));

	//累加器 三角函数
	int *line_cnt[180];
	double sin_[180],cos_[180],rad_ = CV_PI/180;
	for(i = 0; i < 180; i++)
	{
		//初始化累加器为0
		line_cnt[i] = new int[max_r]();
		//初始化三角函数
		sin_[i] = sin(i*rad_);
		cos_[i] = cos(i*rad_);
	}

	//极径 极角
	int r = 0;
	int theta = 0;

	//遍历图像 判断并进行累加
	uchar *p;  
    for( i = 0; i < row; i++)  
    {  
        p = img.ptr<uchar>(i);  
        for ( j = 0; j < col; j++)  
        {
            if(p[j] != 0) 
			{
				for( theta =0; theta < 180 ; theta++)
				{
					//极坐标 直线方程
					r =cvRound(j*cos_[theta]+i*sin_[theta]);
					//偏移 无负值
					r = r + col;
					line_cnt[theta][r]++;
				}
			}
        }  
    } 

	//存放取出最长的n条直线   
	int *line_n[3];
	line_n[0] = new int[n]();//极角
    line_n[1] = new int[n]();//极径
	line_n[2] = new int[n]();//共点数量
	int tt = 0,rr = 0,cnt = 0;
	for(theta = 0; theta < 180; theta++)
	{
		for( r = 0; r < max_r; r++)
		{
			//最少共点 < 这条直线的共点 则替换 并尝试进行冒泡
			if(line_n[2][n-1] < line_cnt[theta][r])
			{
				line_n[0][n-1] = theta;
				//累计的时候偏移过 这里再偏移回来
				line_n[1][n-1] = r - col;
				line_n[2][n-1] = line_cnt[theta][r];
				//冒泡排序
				for(i = n - 1;i > 0; i--)
				{
					//如果大于 则交换
					if(line_n[2][i] > line_n[2][i-1])
					{
						tt = line_n[0][i];
						rr = line_n[1][i];
						cnt = line_n[2][i];
						line_n[0][i] = line_n[0][i-1];
						line_n[1][i] = line_n[1][i-1];
						line_n[2][i] = line_n[2][i-1];
						line_n[0][i-1] = tt;
						line_n[1][i-1] = rr;
						line_n[2][i-1] =cnt;
					}
					else
						break;
				}
			}
		}
	}

	//为了画绿线 单通道转换为三通道
    cvtColor(img, img, CV_GRAY2BGR);

	//画出线段
	for(i = 0; i < n; i++ )  
    {
		Point pt1, pt2;  
		double a = cos_[line_n[0][i]], b = sin_[line_n[0][i]];  
		double x0 = a* line_n[1][i], y0 = b* line_n[1][i];  
		pt1.x = cvRound(x0 + max_r*(-b));  
		pt1.y = cvRound(y0 + max_r*(a));  
		pt2.x = cvRound(x0 - max_r*(-b));  
		pt2.y = cvRound(y0 - max_r*(a)); 
		//绿线
		line(img, pt1, pt2, Scalar(0,255,0), 1, CV_AA); 
    } 

	//-------------------释放内存------------------------
	for(i = 0; i < 180; i++)
	{
		delete []line_cnt[i];
	}
	delete []line_n[0];
	delete []line_n[1];
	delete []line_n[2];
}

猜你喜欢

转载自blog.csdn.net/qq_38204686/article/details/79321240