直接上代码,代码里分析峰值检测的基本思想:
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不宜设置太大。