2016-07-30 72 views
0

是否有OpenCV函數可以給我一個直方圖的所有局部最大值的列表?也許有一個函數可以讓我指定一個最小峯值/閾值,並且會告訴我所有那些高於該閾值的局部最大值的倉。函數來確定直方圖的所有局部最大值

如果沒有,是否有一個函數可以從最高(最頻繁)到最低(最不頻繁)的分類。然後,我可以抓住所有前20個左右的垃圾桶,並擁有我最大的20個當地最大值。

回答

0

AFAIK OpenCV沒有這樣的功能,但可以自己實現類似的功能。

爲了對直方圖分類進行排序,您可以使用sortIdx,但是因此您將獲得與局部最大值不同的最大分檔列表(這些分檔應該由較小的值「包圍」)。

要獲得局部最大值,可以將每個箱與其鄰居進行比較(1D案例中的2個)。箱應大於具有一定裕度的鄰居以被認爲是局部最大值。

根據容器的大小,您可能希望在此步驟之前過濾直方圖(例如,使用高斯內核進行卷積),否則您會獲得太多這些最大值,特別是對於小容量的容器。如果你已經使用了高斯內核 - 它的西格瑪將會與檢測到的局部最大值是「全局」的鄰域的大小有關。

一旦您檢測到這些點 - 您可能需要執行非最大抑制,以替換與單點非常接近的點組。一個簡單的策略是根據一些標準(例如與鄰居的差異)對這些最大值進行排序,然後取一個最大值並刪除其鄰域中的所有點(其大小可以與高斯內核西格瑪相關),然後取下一個剩餘的最大值,並再次刪除其鄰域內的點等等,直到你用盡點或低於一些有意義的差值。最後,您可能希望通過其剩餘候選點的絕對值(以獲得「最大」局部最大值),或通過與鄰居的差異(以獲得「最銳利的」)來對其餘的候選點進行排序。

您可以嘗試其他方法。我們可以使用this局部最大值的定義來實現一個更簡單的算法:只需沿直方圖移動一個大小爲S的滑動窗口,並在每個位置選擇最大值。這會產生一些問題:

  • 與突出最大的多個窗口中的位置的位置將產生對應於相同的最大點(可以是固定的與非最大抑制),在位置
  • 沒有或小的變化它將返回 半隨機最大值(可以通過 窗口或最大值和相鄰值之間的差異修正閾值),
  • 在具有單調直方圖的區域中,它將返回最大值(不一定是最大值)。

一旦你執行所有的「特殊情況」處理 - 這兩種方法將非常相似,我相信。

要實現的另一件事情可能是「多尺度」方法,如果是這樣的話,可以將其視爲擴展。基本上歸結爲檢測不同鄰域大小的局部最大值,然後將它們與相應的鄰域大小,這可能對某些目的有所幫助。

正如您所看到的,這是一個非常模糊的指南,並且有一個原因:您希望得到的局部最大值的類型和數量很可能取決於您所考慮的問題。決定這個點是否應該被認爲是一個局部最大值並不難,因此你應該從一些簡單的方法開始,然後針對你的具體情況進行細化。

0

Opencv minMaxLoc可以在此上下文中使用滑動窗口。如果最大值的位置在邊緣上,則忽略最大值,否則記錄爲最大值。您可以使用類似下面的函數(注:此代碼更像僞代碼還沒有經過測試

/** 
* 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...);