1 | initial version |
you can have a look here I guess this is what you are looking for. Plus look, to a newer implementation of mine below:
void non_maxima_suppression(const cv::Mat& src, cv::Mat& mask, const bool remove_plateaus)
{
// find pixels that are equal to the local neighborhood not maximum (including 'plateaus')
cv::dilate(src, mask, cv::Mat());
cv::compare(src, mask, mask, cv::CMP_GE);
// optionally filter out pixels that are equal to the local minimum ('plateaus')
if (remove_plateaus) {
cv::Mat non_plateau_mask;
cv::erode(src, non_plateau_mask, cv::Mat());
cv::compare(src, non_plateau_mask, non_plateau_mask, cv::CMP_GT);
cv::bitwise_and(mask, non_plateau_mask, mask);
}
}
// function that finds the peaks of a given hist image
void findHistPeaks(InputArray _src, OutputArray _idx, const float scale = 0.2, const Size& ksize = Size(9, 9), const bool remove_plateus = true)
{
Mat hist = _src.getMat();
// die if histogram image is not the correct type
CV_Assert(hist.type() == CV_32F);
// find the min and max values of the hist image
double min_val, max_val;
minMaxLoc(hist, &min_val, &max_val);
Mat mask;
GaussianBlur(hist, hist, ksize, 0); // smooth a bit in order to obtain better result
non_maxima_suppression(hist, mask, remove_plateus); // extract local maxima
vector<Point> maxima; // output, locations of non-zero pixels
cv::findNonZero(mask, maxima);
for(vector<Point>::iterator it = maxima.begin(); it != maxima.end();)
{
Point pnt = *it;
float pVal = hist.at<float>(/*pnt.x, */pnt.y - 1);
float val = hist.at<float>(/*pnt.x, */pnt.y);
float nVal = hist.at<float>(/*pnt.x, */pnt.y+1);
// filter peaks
if((val > max_val * scale))
++it;
else
it = maxima.erase(it);
}
Mat(maxima).copyTo(_idx);
}
Then you can call the function by either passing a std::vector<point> or a cv::Mat as an output array. If you pass the scale attribute as 0 you will get every peak in the matrix, but if you don't want the small peaks then just leave it as it is or raise it to a higher value.
// vector<Point> peaks; or
Mat peaks;
findHistPeaks(b_hist, peaks);
2 | No.2 Revision |
you can have a look here I guess this is what you are looking for. Plus look, to a newer implementation of mine below:
void non_maxima_suppression(const cv::Mat& src, cv::Mat& mask, const bool remove_plateaus)
{
// find pixels that are equal to the local neighborhood not maximum (including 'plateaus')
cv::dilate(src, mask, cv::Mat());
cv::compare(src, mask, mask, cv::CMP_GE);
// optionally filter out pixels that are equal to the local minimum ('plateaus')
if (remove_plateaus) {
cv::Mat non_plateau_mask;
cv::erode(src, non_plateau_mask, cv::Mat());
cv::compare(src, non_plateau_mask, non_plateau_mask, cv::CMP_GT);
cv::bitwise_and(mask, non_plateau_mask, mask);
}
}
// function that finds the peaks of a given hist image
void findHistPeaks(InputArray _src, OutputArray _idx, const float scale = 0.2, const Size& ksize = Size(9, 9), const bool remove_plateus = true)
{
Mat hist = _src.getMat();
// die if histogram image is not the correct type
CV_Assert(hist.type() == CV_32F);
// find the min and max values of the hist image
double min_val, max_val;
minMaxLoc(hist, &min_val, &max_val);
Mat mask;
GaussianBlur(hist, hist, ksize, 0); // smooth a bit in order to obtain better result
non_maxima_suppression(hist, mask, remove_plateus); // extract local maxima
vector<Point> maxima; // output, locations of non-zero pixels
cv::findNonZero(mask, maxima);
for(vector<Point>::iterator it = maxima.begin(); it != maxima.end();)
{
Point pnt = *it;
float pVal = hist.at<float>(/*pnt.x, */pnt.y - 1);
float val = hist.at<float>(/*pnt.x, */pnt.y);
float nVal = hist.at<float>(/*pnt.x, */pnt.y+1);
// filter peaks
if((val > max_val * scale))
++it;
else
it = maxima.erase(it);
}
Mat(maxima).copyTo(_idx);
}
Then you can call the function by either passing a std::vector<point> an std::vector<Point>
or a cv::Mat cv::Mat
as an output array. If you pass the scale attribute as 0 you will get every peak in the matrix, but if you don't want the small peaks then just leave it as it is or raise it to a higher value.
// vector<Point> peaks; or
Mat peaks;
findHistPeaks(b_hist, peaks);
3 | No.3 Revision |
you can have a look here I guess this is what you are looking for. Plus look, to a newer implementation of mine below:
void non_maxima_suppression(const cv::Mat& src, cv::Mat& mask, const bool remove_plateaus)
{
// find pixels that are equal to the local neighborhood not maximum (including 'plateaus')
cv::dilate(src, mask, cv::Mat());
cv::compare(src, mask, mask, cv::CMP_GE);
// optionally filter out pixels that are equal to the local minimum ('plateaus')
if (remove_plateaus) {
cv::Mat non_plateau_mask;
cv::erode(src, non_plateau_mask, cv::Mat());
cv::compare(src, non_plateau_mask, non_plateau_mask, cv::CMP_GT);
cv::bitwise_and(mask, non_plateau_mask, mask);
}
}
// function that finds the peaks of a given hist image
void findHistPeaks(InputArray _src, OutputArray _idx, const float scale = 0.2, const Size& ksize = Size(9, 9), const bool remove_plateus = true)
{
Mat hist = _src.getMat();
// die if histogram image is not the correct type
CV_Assert(hist.type() == CV_32F);
// find the min and max values of the hist image
double min_val, max_val;
minMaxLoc(hist, &min_val, &max_val);
Mat mask;
GaussianBlur(hist, hist, ksize, 0); // smooth a bit in order to obtain better result
non_maxima_suppression(hist, mask, remove_plateus); // extract local maxima
vector<Point> maxima; // output, locations of non-zero pixels
cv::findNonZero(mask, maxima);
for(vector<Point>::iterator it = maxima.begin(); it != maxima.end();)
{
Point pnt = *it;
float pVal = hist.at<float>(/*pnt.x, */pnt.y - 1);
float val = hist.at<float>(/*pnt.x, */pnt.y);
float nVal = hist.at<float>(/*pnt.x, */pnt.y+1);
// filter peaks
if((val > max_val * scale))
++it;
else
it = maxima.erase(it);
}
Mat(maxima).copyTo(_idx);
}
Then you can call the function by either passing an std::vector<Point>
or a cv::Mat
as an output array. If you pass the scale attribute as 0 you will get every peak in the matrix, but if you don't want the small peaks then just leave it as it is or raise it to a higher value.
// vector<Point> peaks; or
Mat peaks;
findHistPeaks(b_hist, peaks);