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