opencv中HoughLines源码解析

typedef struct CvLinePolar
{
float rho;
float angle;
}
CvLinePolar;

static void
icvHoughLinesStandard( const CvMat* img, float rho, float theta,
int threshold, CvSeq *lines, int linesMax )
{
cv::AutoBuffer _accum, _sort_buf;
cv::AutoBuffer _tabSin, _tabCos;

const uchar* image;
int step, width, height;
int numangle, numrho;
int total = 0;
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); //极坐标空间theta轴细分程度
numrho = cvRound(((width + height) * 2 + 1) / rho); //极坐标空间rho轴细分程度
               //实质最小可以取图像两个对角之间的最大距离,eg: M*N的图片最大距离为sqrt(M^2+N^2)
               //如上计算,显然>sqrt(M^2+N^2), 使得计算分辨率更高
_accum.allocate((numangle+2) * (numrho+2));  //多分配一行一列,主要是方便stage    
   //2中4邻域的比较,否则比较时会溢出
_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) );

float ang = 0;
for(int n = 0; n < numangle; ang += theta, n++ )
{
    tabSin[n] = (float)(sin((double)ang) * irho);    //做好tabSin数组,后面备查
    tabCos[n] = (float)(cos((double)ang) * irho);    //做好tabCos数组,后面备查
}

// stage 1. fill accumulator
for( i = 0; i < height; i++ )
    for( j = 0; j < width; j++ )
    {
        if( image[i * step + j] != 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;               //距离偏移一半,r有负值,防止生成的                       索引                                                      //产生覆盖
                accum[(n+1) * (numrho+2) + r+1]++;   //累加器相应单元+1,
                                                     //n+1是为了第一行空出来
                                                     //numrho+2 是总共的列数
                                                     //r+1把第一列空出来,stage 2需要比较4邻域累加器中值的大小
            }
    }

// stage 2. find local maximums
for(int r = 0; r < numrho; r++ )
    for(int n = 0; n < numangle; n++ )
    {
        int base = (n+1) * (numrho+2) + r+1;         //累加器空间的索引,与stage 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[total++] = base;
    }

// stage 3. sort the detected lines by accumulator value
icvHoughSortDescent32s( sort_buf, total, accum );    //opencv自带排序函数,
                          //降序排列,降序排列后的数据在accum中的序号赋给sort_buf

// stage 4. store the first min(total,linesMax) lines to the output buffer
linesMax = MIN(linesMax, total);
scale = 1./(numrho+2);
for( i = 0; i < linesMax; i++ )
{
    CvLinePolar line;
    int idx = sort_buf[i];   //累加器空间accum的序号
    int n = cvFloor(idx*scale) - 1;   //cvFloor()将浮点数转换为不大于该参数的整数
                                      //除以(numrho + 2)并减1→获得行数
    int r = idx - (n+1)*(numrho+2) - 1;  //获得列数
    line.rho = (r - (numrho - 1)*0.5f) * rho;   //0.5=1/2,距离大小,与之前偏移相对应
    line.angle = n * theta;        //角度大小
    cvSeqPush( lines, &line );     //直线以(ρ,r)装到lines中
}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值