MATLAB内置函数转C/C++:能否获取源码实现findpeaks功能?
findpeaks with MinPeakProminence to C++ Great question—let’s break this down into two clear parts since you’ve got two key concerns here.
Can you access the underlying code for MATLAB built-in functions?
Short answer: No, you can’t get the full source code for most MATLAB built-ins. MathWorks keeps these implementations closed-source to protect intellectual property and maintain optimized performance (many are written in low-level, tuned C/Fortran under the hood).
That said, you don’t need the source code to convert findpeaks to C++—MATLAB offers an official tool for this: MATLAB Coder. It can translate MATLAB code (including calls to findpeaks with MinPeakProminence) into standalone C/C++ code, complete with header files and compiled libraries. This is the most reliable way to get an equivalent implementation without reinventing the wheel.
Manual implementation of findpeaks with MinPeakProminence in C++
If you want to build it from scratch (for learning, or to avoid MATLAB dependencies), here’s how to approach it—starting with understanding what MinPeakProminence actually means:
What is peak prominence?
A peak’s prominence measures how "standout" it is from surrounding data. For a peak at index i with value p:
- Left valley: Traverse left from
iuntil you hit a point higher thanp. The minimum value betweeniand that higher point (or the start of the array if no higher point exists) is the left valley. - Right valley: Traverse right from
iuntil you hit a point higher thanp. The minimum value betweeniand that higher point (or the end of the array if no higher point exists) is the right valley. - Prominence:
p - max(left_valley, right_valley)(this takes the highest of the two surrounding valleys, as that’s the "lowest barrier" the peak has to rise above).
Step-by-step C++ implementation
Here’s a simplified, working example that finds peaks meeting a minimum prominence threshold:
#include <vector> #include <algorithm> #include <iostream> // Struct to store peak details: index, value, calculated prominence struct Peak { int index; double value; double prominence; }; // First, find all local peaks in the dataset std::vector<Peak> findLocalPeaks(const std::vector<double>& data) { std::vector<Peak> peaks; int n = data.size(); if (n < 3) return peaks; // Check inner points (not edges) for (int i = 1; i < n - 1; ++i) { if (data[i] > data[i-1] && data[i] > data[i+1]) { peaks.push_back({i, data[i], 0.0}); } } // Optional: handle edge peaks (MATLAB's findpeaks can include these with settings) if (data[0] > data[1]) { peaks.push_back({0, data[0], 0.0}); } if (data.back() > data[n-2]) { peaks.push_back({n-1, data.back(), 0.0}); } return peaks; } // Calculate prominence for a single peak double calculateProminence(const std::vector<double>& data, int peakIndex) { double peakVal = data[peakIndex]; int n = data.size(); // Find left valley double leftValley = peakVal; int leftPtr = peakIndex - 1; bool foundHigherLeft = false; while (leftPtr >= 0) { if (data[leftPtr] > peakVal) { foundHigherLeft = true; break; } if (data[leftPtr] < leftValley) { leftValley = data[leftPtr]; } leftPtr--; } // If no higher point left, use min from start to peak if (!foundHigherLeft) { leftValley = *std::min_element(data.begin(), data.begin() + peakIndex + 1); } // Find right valley double rightValley = peakVal; int rightPtr = peakIndex + 1; bool foundHigherRight = false; while (rightPtr < n) { if (data[rightPtr] > peakVal) { foundHigherRight = true; break; } if (data[rightPtr] < rightValley) { rightValley = data[rightPtr]; } rightPtr++; } // If no higher point right, use min from peak to end if (!foundHigherRight) { rightValley = *std::min_element(data.begin() + peakIndex, data.end()); } // Prominence is peak minus the higher of the two valleys return peakVal - std::max(leftValley, rightValley); } // Filter peaks to only those meeting the minimum prominence threshold std::vector<Peak> filterPeaksByProminence(std::vector<Peak> peaks, const std::vector<double>& data, double minProminence) { std::vector<Peak> filtered; for (auto& peak : peaks) { peak.prominence = calculateProminence(data, peak.index); if (peak.prominence >= minProminence) { filtered.push_back(peak); } } return filtered; } // Example usage int main() { std::vector<double> data = {1.0, 3.0, 0.5, 4.0, 2.0, 5.0, 1.0, 6.0, 0.0}; double minProminence = 2.0; std::vector<Peak> peaks = findLocalPeaks(data); std::vector<Peak> filteredPeaks = filterPeaksByProminence(peaks, data, minProminence); std::cout << "Filtered peaks (prominence >= " << minProminence << "):\n"; for (const auto& peak : filteredPeaks) { std::cout << "Index: " << peak.index << ", Value: " << peak.value << ", Prominence: " << peak.prominence << "\n"; } return 0; }
Notes on this implementation
- This is a simplified version—MATLAB’s
findpeakshas extra features (like handling plateaus, width constraints, and noise reduction) that you can add if your use case requires them. - For large datasets, optimize the
calculateProminencefunction (e.g., precompute prefix/suffix minima to avoid repeated min calculations).
内容的提问来源于stack exchange,提问作者Khalid

