首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 直方圖尋峰:一階差分法快速判斷峰值個數

     編輯:程式設計疑難解答

問題:一維陣列儲存直方圖計數,需判斷有幾個峰 (局部最大值)。

核心演算法:一階差分 + 符號變化

峰值定義:`hist[i] > hist[i-1]` 且 `hist[i] > hist[i+1]` (嚴格) 或 `>=` (寬鬆)。

C++ 實作


#include 
#include 

int countPeaks(const std::vector& hist, int threshold = 0) {
    if (hist.size() < 3) return 0;
    int peaks = 0;
    for (size_t i = 1; i + 1 < hist.size(); ++i) {
        if (hist[i] <= threshold) continue; // 忽略過小計數
        bool leftUp   = hist[i] > hist[i-1];
        bool rightDown = hist[i] > hist[i+1];
        if (leftUp && rightDown) ++peaks;
    }
    return peaks;
}

// 進階:允許平頂峰 (連續相等最大值視為一峰)
int countPeaksPlateau(const std::vector& hist, int threshold = 0) {
    int peaks = 0;
    for (size_t i = 1; i + 1 < hist.size(); ) {
        if (hist[i] <= threshold) { ++i; continue; }
        if (hist[i] > hist[i-1] && hist[i] >= hist[i+1]) {
            ++peaks;
            // 跳過平頂
            size_t j = i + 1;
            while (j + 1 < hist.size() && hist[j] == hist[i]) ++j;
            i = j;
        } else {
            ++i;
        }
    }
    return peaks;
}

差分法等價邏輯


// 一階差分
std::vector diff(hist.size()-1);
for (size_t i=0; i 0 && diff[i] < 0) ++peaks;

工程落地建議

  1. 預處理平滑:高斯核/移動平均濾波,抑制雜訊產生的偽峰。
  2. 動態閾值:`threshold = mean + k * std` 或 Otsu 自適應。
  3. 最小峰距**
  4. 邊界處理**

OpenCV 現成函數


cv::Mat hist; // 1D histogram
std::vector peaks;
cv::findPeaks(hist, peaks, threshold, minDist); // OpenCV 4.5+

核心口訣:**一階差分正→負即峰值,加上平滑、閾值、最小峰距三大濾波器,工程可用、抗雜訊強。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved