码迷,mamicode.com
首页 > 其他好文 > 详细

opencv霍夫变换源码及注释

时间:2016-05-07 10:12:49      阅读:564      评论:0      收藏:0      [点我收藏+]

标签:

终于鼓起勇气看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));
    }
}


至此,  应该算是完整的注释了,  如果有什么错误欢迎留言  



/** @brief  Automatically Allocated Buffer Class
 The class is used for temporary buffers in functions and methods.
 If a temporary buffer is usually small (a few K‘s of memory),
 but its size depends on the parameters, it makes sense to create a small
 fixed-size array on stack and use it if it‘s large enough. If the required buffer size
 is larger than the fixed size, another buffer of sufficient size is allocated dynamically
 and released after the processing. Therefore, in typical cases, when the buffer size is small,
 there is no overhead associated with malloc()/free().
 At the same time, there is no limit on the size of processed data.
 This is what AutoBuffer does. The template takes 2 parameters - type of the buffer elements and
 the number of stack-allocated elements. Here is how the class is used:


 \code
 void my_func(const cv::Mat& m)
 {
    cv::AutoBuffer<float> buf; // create automatic buffer containing 1000 floats
    buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used,
                          // otherwise the buffer of "m.rows" floats will be allocated
                          // dynamically and deallocated in cv::AutoBuffer destructor
    ...
 }
 \endcode
*/



template<typename _Tp, size_t fixed_size = 1024/sizeof(_Tp)+8> class AutoBuffer
{
public:
    typedef _Tp value_type;


    //! the default constructor
    AutoBuffer();
    //! constructor taking the real buffer size
    AutoBuffer(size_t _size);


    //! the copy constructor
    AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf);
    //! the assignment operator
    AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf);


    //! destructor. calls deallocate()
    ~AutoBuffer();


    //! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used
    void allocate(size_t _size);
    //! deallocates the buffer if it was dynamically allocated
    void deallocate();
    //! resizes the buffer and preserves the content
    void resize(size_t _size);
    //! returns the current buffer size
    size_t size() const;
    //! returns pointer to the real buffer, stack-allocated or head-allocated
    operator _Tp* ();
    //! returns read-only pointer to the real buffer, stack-allocated or head-allocated
    operator const _Tp* () const;


protected:
    //! pointer to the real buffer, can point to buf if the buffer is small enough
    _Tp* ptr;
    //! size of the real buffer
    size_t sz;
    //! pre-allocated buffer. At least 1 element to confirm C++ standard reqirements
    _Tp buf[(fixed_size > 0) ? fixed_size : 1];
};

opencv霍夫变换源码及注释

标签:

原文地址:http://blog.csdn.net/traumland/article/details/51319644

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!