OpenCV Max位置

时间:2011-11-16 18:00:29

标签: opencv

我正在开发一个OpenCV项目并使用cvMatchTemplate来定位图像的一部分然后我使用cvMinMaxLoc来查找最大区域,因此最匹配,我的问题是cvMinMaxLoc只返回一个最大位置,因为可能存在一张图片中有多个匹配。

是否有办法将所有最大位置返回到特定阈值以上

对于每个位置>阈 将位置添加到数组

我是OpenCV的新手,不知道这样的事情是否已经存在,但到目前为止我还没有找到任何东西

任何帮助非常感谢

2 个答案:

答案 0 :(得分:3)

我修改了matchTemplate教程以帮助您入门。它基本上使用queue来跟踪前X个匹配点,然后绘制所有这些匹配点。希望有帮助!

#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;
}

答案 1 :(得分:0)

尝试cvThreshold(src,dst,threshold,CV_THRESH_BINARY)

这会在dst中返回一个图像,其中所有像素都高于阈值为白色,其他所有像素为黑色。然后,您将遍历所有像素并检查它是否大于0,那么这是您想要的位置。像这样的东西

   char* data = dst->imageData;
   int size = (dst->height) * (dst->width)

   for (int i=0; i<size; i++)
   {
       if(data[i] > 0)
          //copy i into your array
   }