Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV Max locations

Tags:

opencv

I am working on an OpenCV project and am using cvMatchTemplate to locate part of an image I am then using cvMinMaxLoc to find the maximum area, therefore best match, my problem is that cvMinMaxLoc only returns one max location were as there may be multiple matches in one image.

Is there any way to return all the max locations above a particular threshold

I.e.

for each location > threshold add location to array

I'm new to OpenCV and dont know if something like this already exists but so far I haven't been able to find anything

Any help greatly appreciated

like image 863
Mike Norgate Avatar asked Nov 16 '11 18:11

Mike Norgate


1 Answers

I modified the matchTemplate tutorial to get you started. It basically uses a queue to track the top X match points, and later plots all of them. Hope that is helpful!

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
#include <limits>
#include <queue>

using namespace cv;
using namespace std;

void maxLocs(const Mat& src, queue<Point>& dst, size_t size)
{
    float maxValue = -1.0f * numeric_limits<float>::max();
    float* srcData = reinterpret_cast<float*>(src.data);

    for(int i = 0; i < src.rows; i++)
    {
        for(int j = 0; j < src.cols; j++)
        {
            if(srcData[i*src.cols + j] > maxValue)
            {
                maxValue = srcData[i*src.cols + j];

                dst.push(Point(j, i));

                // pop the smaller one off the end if we reach the size threshold.
                if(dst.size() > size)
                {
                    dst.pop();
                }
            }
        }
    }
}

/// Global Variables
Mat img; Mat templ; Mat result;
string image_window = "Source Image";
string result_window = "Result window";

int match_method;
int max_Trackbar = 5;

/// Function Headers
void MatchingMethod( int, void* );

int main(int argc, char* argv[])
{
    /// Load image and template
    img = imread( "dogs.jpg", 1 );
    templ = imread( "dog_templ.jpg", 1 );

    /// Create windows
    namedWindow( image_window, CV_WINDOW_AUTOSIZE );
    namedWindow( result_window, CV_WINDOW_AUTOSIZE );

    /// Create Trackbar
    string trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
    createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );

    MatchingMethod( 0, 0 );

    waitKey(0);

    return 0;
}

/**
 * @function MatchingMethod
 * @brief Trackbar callback
 */
void MatchingMethod( int, void* )
{
    /// Source image to display
    Mat img_display;
    img.copyTo( img_display );

    /// Create the result matrix
    int result_cols =  img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;

    result.create( result_cols, result_rows, CV_32FC1 );

    /// Do the Matching and Normalize
    matchTemplate( img, templ, result, match_method );
    normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

    /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
    if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    {
        result = 1.0 - result;
    }

    // get the top 100 maximums...
    queue<Point> locations;
    maxLocs(result, locations, 100);

    /// Show me what you got
    while(!locations.empty())
    {
        Point matchLoc = locations.front();
        rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
        rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
        locations.pop();
    }

    imshow( image_window, img_display );
    imshow( result_window, result );

    return;
}
like image 102
mevatron Avatar answered Sep 28 '22 05:09

mevatron