是否有一个OpenCV函数可以给我一个直方图的所有局部最大值的列表?也许有一个函数可以让我指定一个最小峰值/阈值,并告诉我超过该阈值的所有局部最大值的区间。
如果没有,是否有一个功能可以将垃圾箱从最高(最频繁)到最低(最不频繁)排序。然后我可以抓住所有前20个左右的箱子,我有20个最大的局部最大值。
答案 0 :(得分:1)
Opencv minMaxLoc
可以在此上下文中使用滑动窗口。如果最大值的位置在边缘上,则忽略最大值,否则记录为最大值。您可以使用类似下面的函数(注意:此代码更像是psuedocode,它尚未经过测试)
/**
* Assumes a 1 channel histogram
*/
vector<int> findMaxima(Mat histogram, int windowsize, int histbins){
vector<int> maximas;
int lastmaxima;
for(int i = 0; i < histbins - windowsize; i++){
//Just some Local variables, only maxloc and maxval are used.
int maxval,minval;
Point* maxloc, maxloc;
//Crop the windows
Rect window(i,0,windowsize,1);
//Get the maxima
minMaxLoc(histogram(window), minval,maxval,maxloc,minloc);
//Check if its not on the side
if(maxloc.x != 0&&maxloc.x != windowsize-1){
//Translate from cropped window into real position
int originalposition = maxloc.x+i;
//Check that this is a new maxima and not already recorded
if(lastmaxima != originalposition){
maximas.push(originalposition);
lastmaxima = originalposition;
}
}
}
return maximas;
}
当然这是一个非常简单的系统。您可能希望使用具有不同滑动窗口大小的多尺度方法。您可能还需要根据数据应用高斯平滑。另一种方法可能是为小窗口大小(如3或4)运行它(您需要最小值为3)。然后你可以使用其他东西进行非最大值抑制。
根据您建议的方法
也许有一个函数可以让我指定一个最小峰值/阈值,并告诉我超过该阈值的所有局部最大值的区间。
您可以在使用上述功能找到最大值之前执行阈值。
threshold(hist,res ...aditional parameters...);
vector<int> maximas = findMaximas(hist, ...other parameters...);
答案 1 :(得分:0)
AFAIK OpenCV没有这样的功能,但可以自己实现类似的功能。
为了对直方图分类进行排序,您可以使用sortIdx,但结果您将获得最大分箱列表,这些分箱与局部最大值不同(那些应该被较小的值“包围”)。 / p>
要获得局部最大值,您可以将每个bin与其邻居进行比较(1D情况下为2)。 bin应该比邻居大,有一些余量被认为是局部最大值。
根据容器的大小,您可能希望在此步骤之前过滤直方图(例如,使用高斯内核对其进行卷积),否则您将获得太多的这些最大值,尤其是对于小容器大小。如果您使用了高斯核 - 它的sigma将与检测到的局部最大值为“全局”的邻域大小相关。
一旦检测到这些点 - 您可能希望执行非最大抑制,以替换与单个点非常接近的点组。一个简单的策略是根据某些标准(例如与邻居的差异)对这些最大值进行排序,然后取一个最大值并移除其邻域中的所有点(其大小可以与高斯核sigma相关),接下来保持最大值并再次删除其邻域中的点,依此类推,直到您用完点数或低于某些有意义的差值。
最后,您可能希望按剩余候选点的绝对值(获得“最大”局部最大值)或与邻居的差异(以获得“最清晰”)对其进行排序。
您可以尝试其他方法。我们可以使用局部最大值的this定义来实现更简单的算法:只需沿直方图移动大小为S的滑动窗口,并在每个位置选择最大值。这会有一些问题:
一旦你执行了所有“特殊情况”处理 - 我相信这两种方法会非常相似。
实现的另一个方法可能是“多尺度”方法,如果那些可以被视为扩展2.基本上它归结为检测不同邻域大小的局部最大值,然后将它们与相应的邻域大小一起存储,这对某些目的很有帮助。
正如您所看到的,这是一个非常模糊的指南,并且有一个原因:您想要获得的局部最大值的类型和数量很可能取决于您想到的问题。确定该点是否应被视为局部最大值并没有简单易行的规则,因此您应该从一些简单的方法开始,然后针对您的具体情况进行优化。