我在 OpenCV 中使用霍夫变换来检测线条。但是,我事先知道我只需要在非常有限的角度范围内(大约 10 度左右)内的线条。我在对性能非常敏感的设置中执行此操作,因此我想避免在检测其他角度的线条上花费额外的工作,这些线条我事先知道我不关心。
我可以从 OpenCV 中提取 Hough 源代码,然后将其破解以获取 min_rho 和 max_rho 参数,但我想要一种不那么脆弱的方法(必须手动更新我的代码,每次 OpenCV 更新等)。
这里最好的方法是什么?
我在 OpenCV 中使用霍夫变换来检测线条。但是,我事先知道我只需要在非常有限的角度范围内(大约 10 度左右)内的线条。我在对性能非常敏感的设置中执行此操作,因此我想避免在检测其他角度的线条上花费额外的工作,这些线条我事先知道我不关心。
我可以从 OpenCV 中提取 Hough 源代码,然后将其破解以获取 min_rho 和 max_rho 参数,但我想要一种不那么脆弱的方法(必须手动更新我的代码,每次 OpenCV 更新等)。
这里最好的方法是什么?
If you use the Probabilistic Hough transform then the output is in the form of a cvPoint each for lines[0] and lines[1] parameters. We can get x and y co-ordinated for each of the two points by pt1.x, pt1.y and pt2.x and pt2.y. Then use the simple formula for finding slope of a line - (y2-y1)/(x2-x1). Taking arctan (tan inverse) of that will yield that angle in radians. Then simply filter out desired angles from the values for each hough line obtained.
好吧,我已经修改了icvHoughlines
函数以适应一定的角度范围。我确信也有更简洁的方式来处理内存分配,但是对于从 180 度到 60 度的角度范围,我的速度提升从 100 毫秒到 33 毫秒,所以我对此很满意。
请注意,此代码还输出累加器值。另外,我只输出 1 行,因为这符合我的目的,但那里并没有真正的收获。
static void
icvHoughLinesStandard2( const CvMat* img, float rho, float theta,
int threshold, CvSeq *lines, int linesMax )
{
cv::AutoBuffer<int> _accum, _sort_buf;
cv::AutoBuffer<float> _tabSin, _tabCos;
const uchar* image;
int step, width, height;
int numangle, numrho;
int total = 0;
float ang;
int r, n;
int i, j;
float irho = 1 / rho;
double scale;
CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
image = img->data.ptr;
step = img->step;
width = img->cols;
height = img->rows;
numangle = cvRound(CV_PI / theta);
numrho = cvRound(((width + height) * 2 + 1) / rho);
_accum.allocate((numangle+2) * (numrho+2));
_sort_buf.allocate(numangle * numrho);
_tabSin.allocate(numangle);
_tabCos.allocate(numangle);
int *accum = _accum, *sort_buf = _sort_buf;
float *tabSin = _tabSin, *tabCos = _tabCos;
memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );
// find n and ang limits (in our case we want 60 to 120
float limit_min = 60.0/180.0*PI;
float limit_max = 120.0/180.0*PI;
//num_steps = (limit_max - limit_min)/theta;
int start_n = floor(limit_min/theta);
int stop_n = floor(limit_max/theta);
for( ang = limit_min, n = start_n; n < stop_n; ang += theta, n++ )
{
tabSin[n] = (float)(sin(ang) * irho);
tabCos[n] = (float)(cos(ang) * irho);
}
// stage 1. fill accumulator
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
{
if( image[i * step + j] != 0 )
//
for( n = start_n; n < stop_n; n++ )
{
r = cvRound( j * tabCos[n] + i * tabSin[n] );
r += (numrho - 1) / 2;
accum[(n+1) * (numrho+2) + r+1]++;
}
}
int max_accum = 0;
int max_ind = 0;
for( r = 0; r < numrho; r++ )
{
for( n = start_n; n < stop_n; n++ )
{
int base = (n+1) * (numrho+2) + r+1;
if (accum[base] > max_accum)
{
max_accum = accum[base];
max_ind = base;
}
}
}
CvLinePolar2 line;
scale = 1./(numrho+2);
int idx = max_ind;
n = cvFloor(idx*scale) - 1;
r = idx - (n+1)*(numrho+2) - 1;
line.rho = (r - (numrho - 1)*0.5f) * rho;
line.angle = n * theta;
line.votes = accum[idx];
cvSeqPush( lines, &line );
}
我认为使用标准 HoughLines(...) 函数更自然,它直接在 rho 和 theta 项中提供线的集合并从中选择必要的角度范围,而不是从段端点重新计算角度。