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

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

void ls::houghPeaks(cv::Mat &H,int numpeaks,double thresh,const int *nhood_size,vector<double> &r,vector<double> &c)
    {
        bool done = false;//峰值检测布尔值
        cv::Mat hnew = H.clone();//备份霍夫变换矩阵
        double max,min;//变换矩阵的最大值
        vector<cv::Point> 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<double>(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<double>(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<double> 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<double> po;
                
                
                //                vector<double>::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<double>::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<double>(ppp,qqq) = 0;
                }
                //直到找到指定的峰值点数,结束
                done = (r.size() == numpeaks);
                pts_.clear();
                
            }
            else
                done = true;
            
        }
        
    }
其中,H是霍夫变换得到的变换矩阵(这个矩阵很关键,直接关系到后面的峰值检测),thresh是与最大值比较的阈值,通常取为变换矩阵中最大值的一半,nhood_size是想要抑制的最大值周围邻域范围,r和c分别是检测到的峰值点的x和y坐标。

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


  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值