Find local maxima in grayscale image using OpenCV

前端 未结 10 2326
暗喜
暗喜 2020-11-30 04:44

Does anybody know how to find the local maxima in a grayscale IPL_DEPTH_8U image using OpenCV? HarrisCorner mentions something like that but I\'m actually not i

10条回答
  •  情书的邮戳
    2020-11-30 05:26

    You can go over each pixel and test if it is a local maxima. Here is how I would do it. The input is assumed to be type CV_32FC1

    #include //std::vector
    #include //std::sort
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/core/core.hpp"
    
    //structure for maximal values including position
    struct SRegionalMaxPoint
    {
        SRegionalMaxPoint():
            values(-FLT_MAX),
            row(-1),
            col(-1)
        {}
        float values;
        int row;
        int col;
        //ascending order
        bool operator()(const SRegionalMaxPoint& a, const SRegionalMaxPoint& b)
        {   
            return a.values < b.values;
        }   
    };
    
    //checks if pixel is local max
    bool isRegionalMax(const float* im_ptr, const int& cols )
    {
        float center = *im_ptr;
        bool is_regional_max = true;
        im_ptr -= (cols + 1);
        for (int ii = 0; ii < 3; ++ii, im_ptr+= (cols-3))
        {
            for (int jj = 0; jj < 3; ++jj, im_ptr++)
            {
                if (ii != 1 || jj != 1)
                {
                    is_regional_max &= (center > *im_ptr);
                }
            }
        }
        return is_regional_max;
    }
    
    void imregionalmax(
        const cv::Mat& input, 
        std::vector& buffer)
    {
        //find local max - top maxima
        static const int margin = 1;
        const int rows = input.rows;
        const int cols = input.cols;
        for (int i = margin; i < rows - margin; ++i)
        {
            const float* im_ptr = input.ptr(i, margin);
            for (int j = margin; j < cols - margin; ++j, im_ptr++)
            {
                //Check if pixel is local maximum
                if ( isRegionalMax(im_ptr, cols ) )
                {
                    cv::Rect roi = cv::Rect(j - margin, i - margin, 3, 3);
                    cv::Mat subMat = input(roi);
    
                    float val = *im_ptr;
                    //replace smallest value in buffer
                    if ( val > buffer[0].values )
                    {
                        buffer[0].values = val;
                        buffer[0].row    = i;
                        buffer[0].col    = j;
                        std::sort(buffer.begin(), buffer.end(), SRegionalMaxPoint());
                    }
    
                }
            }
        }
    
    }
    

    For testing the code you can try this:

    cv::Mat temp = cv::Mat::zeros(15, 15, CV_32FC1);
    temp.at(7, 7) = 1;
    temp.at(3, 5) = 6;
    temp.at(8, 10) = 4;
    temp.at(11, 13) = 7;
    temp.at(10, 3) = 8;
    temp.at(7, 13) = 3;
    
    vector buffer_(5);
    imregionalmax(temp, buffer_);
    
    cv::Mat debug;
    cv::cvtColor(temp, debug, cv::COLOR_GRAY2BGR);
    for (auto it = buffer_.begin(); it != buffer_.end(); ++it)
    {
        circle(debug, cv::Point(it->col, it->row), 1, cv::Scalar(0, 255, 0));
    }
    

    This solution does not take plateaus into account so it is not exactly the same as matlab's imregionalmax()

提交回复
热议问题