标签:
终于鼓起勇气看hough变换源码了, 之前自己还瞎写了一个检测椭圆中心的 =_=! 不过还好大致一样
static void
HoughLinesStandard( const Mat& img, float rho, float theta,
int threshold, std::vector<Vec2f>& lines, int linesMax,
double min_theta, double max_theta )
{
int i, j;
float irho = 1 / rho;
CV_Assert( img.type() == CV_8UC1 ); //检测输入的是否为 单通道 8-bit图像
const uchar* image = img.ptr(); //读取img
int step = (int)img.step;
int width = img.cols;
int height = img.rows;
if (max_theta < min_theta ) { //check if max_theta > min_theta
CV_Error( CV_StsBadArg, "max_theta must be greater than min_theta" );
}
int numangle = cvRound((max_theta - min_theta) / theta); //对于angle提供多少个‘格子‘
int numrho = cvRound(((width + height) * 2 + 1) / rho); //对于 rho 提供多少个‘格子‘
//至于(width + height) * 2 + 1)我不太理解,数学上最少格子数吧
//theta --Angle resolution of the accumulator in radians.
//rho --Distance resolution of the accumulator in pixels
AutoBuffer<int> _accum((numangle+2) * (numrho+2)); //关于AutoBuffer请看最下面
//(numangle+2) * (numrho+2) 行*列
std::vector<int> _sort_buf; //为后面排序的
AutoBuffer<float> _tabSin(numangle);
AutoBuffer<float> _tabCos(numangle);
int *accum = _accum;
float *tabSin = _tabSin, *tabCos = _tabCos; //创建sin cos 表
memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) ); //分配内存? 并置零
float ang = static_cast<float>(min_theta); // min_theta转成float 并赋值给ang
for(int n = 0; n < numangle; ang += theta, n++ ) //初始化sin , cos 表
{
tabSin[n] = (float)(sin((double)ang) * irho);
tabCos[n] = (float)(cos((double)ang) * irho);
}
// stage 1. fill accumulator
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
{
if( image[i * step + j] != 0 ) //当某像素值不为0时
for(int n = 0; n < numangle; n++ )
{
int r = cvRound( j * tabCos[n] + i * tabSin[n] ); // ρ = x cos θ + y sin θ
r += (numrho - 1) / 2; //哈哈,这里让我想了好久
// 为什么这样安排呢? 可能是因为θ、ρ正负问题
accum[(n+1) * (numrho+2) + r+1]++; //对应的accumulator +1
// n+1是为了第一行空出来
//numrho+2 是总共的列数
// r+1 是为了把第一列空出来
} //因为程序后面要比较前一行与前一列的数据, 这样省的越界
} //因此空出首行和首列
// stage 2. find local maximums
for(int r = 0; r < numrho; r++ )
for(int n = 0; n < numangle; n++ ) //与theta对应的n
{
int base = (n+1) * (numrho+2) + r+1; //(n+1) * (numrho+2) + r+1 同前
if( accum[base] > threshold &&
accum[base] > accum[base - 1] &&
accum[base] >= accum[base + 1] &&
accum[base] > accum[base - numrho - 2] &&
accum[base] >= accum[base + numrho + 2] )
_sort_buf.push_back(base);
}
// stage 3. sort the detected lines by accumulator value
std::sort(_sort_buf.begin(), _sort_buf.end(), hough_cmp_gt(accum));
// stage 4. store the first min(total,linesMax) lines to the output buffer
linesMax = std::min(linesMax, (int)_sort_buf.size());
double scale = 1./(numrho+2);
for( i = 0; i < linesMax; i++ )
{
LinePolar line;
int idx = _sort_buf[i]; // 第i个line对应的base,
//也就是对应accumulator的位置
int n = cvFloor(idx*scale) - 1; //(numangle+2) * (numrho+2) 行*列
//对应numangle +1
int r = idx - (n+1)*(numrho+2) - 1; // r
= idx - (n+1)*(numrho+2) - 1 同前
line.rho = (r - (numrho - 1)*0.5f) * rho; //ρ
line.angle = static_cast<float>(min_theta) + n * theta; // θ
lines.push_back(Vec2f(line.rho, line.angle));
}
}
至此, 应该算是完整的注释了, 如果有什么错误欢迎留言
标签:
原文地址:http://blog.csdn.net/traumland/article/details/51319644