用于确定直方图

时间:2016-07-30 12:31:41

标签: c++ opencv

是否有一个OpenCV函数可以给我一个直方图的所有局部最大值的列表?也许有一个函数可以让我指定一个最小峰值/阈值,并告诉我超过该阈值的所有局部最大值的区间。

如果没有,是否有一个功能可以将垃圾箱从最高(最频繁)到最低(最不频繁)排序。然后我可以抓住所有前20个左右的箱子,我有20个最大的局部最大值。

2 个答案:

答案 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.基本上它归结为检测不同邻域大小的局部最大值,然后将它们与相应的邻域大小一起存储,这对某些目的很有帮助。

正如您所看到的,这是一个非常模糊的指南,并且有一个原因:您想要获得的局部最大值的类型和数量很可能取决于您想到的问题。确定该点是否应被视为局部最大值并没有简单易行的规则,因此您应该从一些简单的方法开始,然后针对您的具体情况进行优化。