霍夫Hough峰值检测的C++实现

直接上代码,代码里分析峰值检测的基本思想:

void ls::houghPeaks(cv::Mat &H,int numpeaks,double thresh,const int *nhood_size,vector &r,vector &c)
    {
        bool done = false;//峰值检测布尔值
        cv::Mat hnew = H.clone();//备份霍夫变换矩阵
        double max,min;//变换矩阵的最大值
        vector pts_;//最大值点的坐标
        while (!done)
        {
            max = 0.0,min = 0.0;
            //find最大值
            minMaxIdx(hnew, &min,&max);
            int nl = hnew.rows;
            int nc = hnew.cols;
            for (int i = 0; i < nl; i ++)
            {
                double *data = hnew.ptr(i);
                for (int j = 0; j < nc; j ++)
                {
                    if (data[j] == max)
                    {
                        pts_.push_back(cv::Point(i,j));
                    }
                }
            }
            //拿出最大值点集中的第一个点
            int p = pts_[0].x;
            int q = pts_[0].y;
            //与阈值进行比较,
            if (hnew.at(p,q) >= thresh)
            {
                //大于阈值的保留到峰值容器
                r.push_back(p);
                c.push_back(q);
                //suppress this maximum and its close neighbours
                int p1 = p - (nhood_size[0]-1)/2;
                int p2 = p + (nhood_size[0]-1)/2;
                int q1 = q - (nhood_size[1]-1)/2;
                int q2 = q + (nhood_size[1]-1)/2;
                int p11 = MAX(p1, 1);
                int p22 = MIN(p2, H.rows);
                cv::Mat pp;//(rr,cc,CV_8S);
                cv::Mat qq;//(rr,cc,CV_8S);
                //生成最值点指定范围(由nhood_size确定)的领域
                myMeshgrid(q1, q2, p11, p22, qq, pp);
                vector pp_v,qq_v;
                mat2Cvector(pp, pp_v);
                mat2Cvector(qq, qq_v);
                
                //throw away neighbor coordinates that are out of bounds in the rho direction
                //                vector po;
                
                
                //                vector::iterator it;
                //                for (it = pp_v.begin();it != pp_v.end();)
                //                {
                //
                //                    if (*it < 0 || *it > H.rows)
                //                    {
                //                        it = pp_v.erase(it);
                //
                //                    }
                //                    else
                //                        ++it;
                //
                //                }
                //                vector::iterator it1;
                //                for (it1 = qq_v.begin();it1 != qq_v.end();)
                //                {
                //
                //                    if (*it1 < 0 || *it1 > H.rows)
                //                    {
                //                        it1 = qq_v.erase(it1);
                //
                //                    }
                //                    else
                //                        ++it1;
                //
                //                }
                
                //防止超出边界
                for (int j = 0; j < qq_v.size(); j ++)
                {
                    if(qq_v[j] < 0)
                    {
                        qq_v[j] = H.cols + qq_v[j];
                        pp_v[j] = H.rows - pp_v[j] + 1;
                        
                    }
                    if (qq_v[j] > H.cols)
                    {
                        qq_v[j] = qq_v[j] - H.cols;
                        pp_v[j] = H.rows - pp_v[j] + 1;
                    }
                }
                
                //非极大值抑制,置零,并进入下一个循环峰值查找
                for (int num = 0; num < pp_v.size(); num ++)
                {
                    int ppp=floor(pp_v[num]+0.5);
                    int qqq=floor(qq_v[num]+0.5);
                    hnew.at(ppp,qqq) = 0;
                }
                //直到找到指定的峰值点数,结束
                done = (r.size() == numpeaks);
                pts_.clear();
                
            }
            else
                done = true;
            
        }
        
    }
其中,H是霍夫变换得到的变换矩阵(这个矩阵很关键,直接关系到后面的峰值检测),thresh是与最大值比较的阈值,通常取为变换矩阵中最大值的一半,nhood_size是想要抑制的最大值周围邻域范围,r和c分别是检测到的峰值点的x和y坐标。

注意:当图像上要检测的直线密集时,nhood_size不宜设置太大。


你可能感兴趣的:(C/C++,#,OpenCV,#,Image,Processing,Computer,Vision,#,图像处理与计算机视觉)