我在 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 项中提供线的集合并从中选择必要的角度范围,而不是从段端点重新计算角度。