标准hough变换的具体实现

hough直线检测的原理就是采用积分图来统计直线上响应的点数,从而通过设定阈值获取响应较大的直线作为最终的直线,关于太具体的理论可自行查阅。关于hough直线检测之前也写过一篇博文hough直线检测初探,本博文也类似于之前博文,若有不当之处,望指教,谢谢!

#ifndef _HOUGH_JL_H_
#define _HOUGH_JL_H_

#include <iostream>
#include <math.h>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

#define PI 3.1415926
#define UCHAR unsigned char
#define bcolor Scalar(255,0,0)
#define gcolor Scalar(0,255,0)
#define rcolor Scalar(0,0,255)


#define AngleNum 180
#define perangle (CV_PI/180)

typedef struct
{
	vector<Vec4i> left_line_ePt;
	vector<int> left_line_count;
	vector<Vec4i> right_line_ePt;
	vector<int> right_line_count;
}hough_line;

hough_line hough_standard(Mat src,Mat roi_edges, int T);


#endif;
#include "hough_JL.h"


//统计每条直线出现的频数;
hough_line hough_standard(Mat src,Mat roi_edges, int T)
{
	float angle = 0.;
	int dis = 0.;

	Mat test = Mat::zeros(src.size(),src.type());
	int len = (int)sqrt(H * H + W * W);
	int numrho = int(len * 2 + 1);
	int numangle = int(CV_PI / perangle);
	int* left_number = (int*)malloc(numrho * numangle * sizeof(int));
	int* right_number = (int*)malloc(numrho * numangle * sizeof(int));
	int* left_buf = (int*)malloc(numrho * numangle * sizeof(int));
	int* right_buf = (int*)malloc(numrho * numangle * sizeof(int));
	

	for (int i = 0; i < numrho * numangle; i++)
	{
		left_number[i] = 0;
		right_number[i] = 0;
	}

	//提前计算好sin和cos,避免重复计算
	float* tabsin = (float*)malloc(numangle * sizeof(float));
	float* tabcos = (float*)malloc(numangle * sizeof(float));

	float ang = 0;
	for (int i = 0; i < numangle; i++, ang += perangle)
	{
		tabsin[i] = float(sin(ang));
		tabcos[i] = float(cos(ang));
	}


	//统计每条直线出现的频数;
	for (int i = vanishingPt; i < roi_edges.rows - 30; i++)
	{
		for (int j = 0; j < roi_edges.cols; j++)
		{
			if (roi_edges.ptr<uchar>(i)[j])
			{
				for (int n = 0; n < numangle; n++)
				{
					if (n >= 25 && n <= 65)
					{
						dis = 0;
						dis = (int)(i * tabsin[n] + j * tabcos[n]);
						dis += (numrho - 1) / 2;
						left_number[dis * numangle + n]++;
					}
					else if (n >= 70 && n <= 165)
					{   
						dis = 0;
						dis = (int)(i * tabsin[n] + j * tabcos[n]);
						dis += (numrho - 1) / 2;
						right_number[dis * numangle + n]++;
					}
				}
			}
		}
	}

	//非极大值抑制
	int totall = 0;
	int totalr = 0;

	for (int r = 1; r < numrho - 1; r++)
	{
		for (int n = 1; n < numangle - 1; n++)
		{
			int base = r * numangle + n;
			if ((left_number[base] > T) && (left_number[base] > left_number[base + 1]) && (left_number[base] > left_number[base - 1])
				&& (left_number[base] > left_number[base - numangle]) && (left_number[base] > left_number[base + numangle]))
			{
				left_buf[totall++] = base;
			}
			
			if ((right_number[base] > T) && (right_number[base] > right_number[base + 1]) && (right_number[base] > right_number[base - 1])
				&& (right_number[base] > right_number[base - numangle]) && (right_number[base] > right_number[base + numangle]))
			{
				right_buf[totalr++] = base;
			}
		}
	}


	//获取直线的端点;
	hough_line m_lines;
	const int EP = 1000;

	for (int i = 0; i < totall; i++)
	{
		int rho = left_buf[i] / numangle;
		rho = rho - (numrho - 1) / 2;
		float theta = left_buf[i] % numangle * perangle;

		float a = cos(theta), b = sin(theta);
		float x0 = rho * a;
		float y0 = rho * b;

		float tao = PI / 2 + theta;
		float kk = tan(tao);

		float bb = y0 - kk * x0;

		int yb = 0;// H - 30;
		int yt = H - 1;// vanishingPt;

		int xb = (yb - bb) / kk;
		int xt = (yt - bb) / kk;

		line(src, Point(xb, yb), Point(xt, yt), gcolor);

		Vec4i vec;
		vec[0] = xb;
		vec[1] = yb;
		vec[2] = xt;
		vec[3] = yt;

		m_lines.left_line_ePt.push_back(vec);
		m_lines.left_line_count.push_back(left_number[left_buf[i]]);
	}

	for (int i = 0; i < totalr; i++)
	{
		int rho = right_buf[i] / numangle;
		rho = rho - (numrho - 1) / 2;
		float theta = right_buf[i] % numangle * perangle;

		float a = cos(theta), b = sin(theta);
		float x0 = rho * a;
		float y0 = rho * b;

		float tao = PI / 2 + theta;
		float kk = tan(tao);

		float bb = y0 - kk * x0;

		int yb = 0;// H - 30;
		int yt = H;// vanishingPt;

		int xb = (yb - bb) / kk;
		int xt = (yt - bb) / kk;

		line(src, Point(xb, yb), Point(xt, yt), gcolor);

		Vec4i vec;
		vec[0] = xb;
		vec[1] = yb;
		vec[2] = xt;
		vec[3] = yt;

		m_lines.left_line_ePt.push_back(vec);
		m_lines.left_line_count.push_back(right_number[right_buf[i]]);
	}

	free(left_number);
	free(right_number);
	free(tabsin);
	free(tabcos);
	free(left_buf);
	free(right_buf);
	
	imshow("src",src);
	waitKey(10);

	return m_lines;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值