Find local maxima in grayscale image using OpenCV

前端 未结 10 2254
暗喜
暗喜 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:45

    The following listing is a function similar to Matlab's "imregionalmax". It looks for at most nLocMax local maxima above threshold, where the found local maxima are at least minDistBtwLocMax pixels apart. It returns the actual number of local maxima found. Notice that it uses OpenCV's minMaxLoc to find global maxima. It is "opencv-self-contained" except for the (easy to implement) function vdist, which computes the (euclidian) distance between points (r,c) and (row,col).

    input is one-channel CV_32F matrix, and locations is nLocMax (rows) by 2 (columns) CV_32S matrix.

    int imregionalmax(Mat input, int nLocMax, float threshold, float minDistBtwLocMax, Mat locations)
    {
        Mat scratch = input.clone();
        int nFoundLocMax = 0;
        for (int i = 0; i < nLocMax; i++) {
            Point location;
            double maxVal;
            minMaxLoc(scratch, NULL, &maxVal, NULL, &location);
            if (maxVal > threshold) {
                nFoundLocMax += 1;
                int row = location.y;
                int col = location.x;
                locations.at<int>(i,0) = row;
                locations.at<int>(i,1) = col;
                int r0 = (row-minDistBtwLocMax > -1 ? row-minDistBtwLocMax : 0);
                int r1 = (row+minDistBtwLocMax < scratch.rows ? row+minDistBtwLocMax : scratch.rows-1);
                int c0 = (col-minDistBtwLocMax > -1 ? col-minDistBtwLocMax : 0);
                int c1 = (col+minDistBtwLocMax < scratch.cols ? col+minDistBtwLocMax : scratch.cols-1);
                for (int r = r0; r <= r1; r++) {
                    for (int c = c0; c <= c1; c++) {
                        if (vdist(Point2DMake(r, c),Point2DMake(row, col)) <= minDistBtwLocMax) {
                            scratch.at<float>(r,c) = 0.0;
                        }
                    }
                }
            } else {
                break;
            }
        }
        return nFoundLocMax;
    }

    0 讨论(0)
  • 2020-11-30 05:46

    Actually after I posted the code above I wrote a better and very very faster one .. The code above suffers even for a 640x480 picture.. I optimized it and now it is very very fast even for 1600x1200 pic. Here is the code :

    void localMaxima(cv::Mat src,cv::Mat &dst,int squareSize)
    {
    if (squareSize==0)
    {
        dst = src.clone();
        return;
    }
    
    Mat m0;
    dst = src.clone();
    Point maxLoc(0,0);
    
    //1.Be sure to have at least 3x3 for at least looking at 1 pixel close neighbours
    //  Also the window must be <odd>x<odd>
    SANITYCHECK(squareSize,3,1);
    int sqrCenter = (squareSize-1)/2;
    
    //2.Create the localWindow mask to get things done faster
    //  When we find a local maxima we will multiply the subwindow with this MASK
    //  So that we will not search for those 0 values again and again
    Mat localWindowMask = Mat::zeros(Size(squareSize,squareSize),CV_8U);//boolean
    localWindowMask.at<unsigned char>(sqrCenter,sqrCenter)=1;
    
    //3.Find the threshold value to threshold the image
        //this function here returns the peak of histogram of picture
        //the picture is a thresholded picture it will have a lot of zero values in it
        //so that the second boolean variable says :
        //  (boolean) ? "return peak even if it is at 0" : "return peak discarding 0"
    int thrshld =  maxUsedValInHistogramData(dst,false);
    threshold(dst,m0,thrshld,1,THRESH_BINARY);
    
    //4.Now delete all thresholded values from picture
    dst = dst.mul(m0);
    
    //put the src in the middle of the big array
    for (int row=sqrCenter;row<dst.size().height-sqrCenter;row++)
        for (int col=sqrCenter;col<dst.size().width-sqrCenter;col++)
        {
            //1.if the value is zero it can not be a local maxima
            if (dst.at<unsigned char>(row,col)==0)
                continue;
            //2.the value at (row,col) is not 0 so it can be a local maxima point
            m0 =  dst.colRange(col-sqrCenter,col+sqrCenter+1).rowRange(row-sqrCenter,row+sqrCenter+1);
            minMaxLoc(m0,NULL,NULL,NULL,&maxLoc);
            //if the maximum location of this subWindow is at center
            //it means we found the local maxima
            //so we should delete the surrounding values which lies in the subWindow area
            //hence we will not try to find if a point is at localMaxima when already found a neighbour was
            if ((maxLoc.x==sqrCenter)&&(maxLoc.y==sqrCenter))
            {
                m0 = m0.mul(localWindowMask);
                                //we can skip the values that we already made 0 by the above function
                col+=sqrCenter;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 05:48

    I think you want to use the

    MinMaxLoc(arr, mask=NULL)-> (minVal, maxVal, minLoc, maxLoc)
    Finds global minimum and maximum in array or subarray
    

    function on you image

    0 讨论(0)
  • 2020-11-30 05:49

    Here's a simple trick. The idea is to dilate with a kernel that contains a hole in the center. After the dilate operation, each pixel is replaced with the maximum of it's neighbors (using a 5 by 5 neighborhood in this example), excluding the original pixel.

    Mat1b kernelLM(Size(5, 5), 1u);
    kernelLM.at<uchar>(2, 2) = 0u;
    Mat imageLM;
    dilate(image, imageLM, kernelLM);
    Mat1b localMaxima = (image > imageLM);
    
    0 讨论(0)
提交回复
热议问题