简体   繁体   English

模板匹配与模板更新

[英]Template Matching with template update

I am trying to implement real-time tracking using templates in OpenCV/C++. 我正在尝试使用OpenCV / C ++中的模板实施实时跟踪。 I am facing problem to update the template with every frame. 我面临着每帧更新模板的问题。

Following is the code: 以下是代码:

#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>

#include <sstream>


using namespace cv;
using namespace std;

Point point1, point2; /* vertical points of the bounding box */
int drag = 0;
Rect rect; /* bounding box */
Mat img, roiImg; /* roiImg - the part of the image in the bounding box */
int select_flag = 0;
bool go_fast = false;

Mat mytemplate;


///------- template matching -----------------------------------------------------------------------------------------------

Mat TplMatch( Mat &img, Mat &mytemplate )
{
  Mat result;

  matchTemplate( img, mytemplate, result, CV_TM_SQDIFF_NORMED );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  return result;
}


///------- Localizing the best match with minMaxLoc ------------------------------------------------------------------------

Point minmax( Mat &result )
{
  double minVal, maxVal;
  Point  minLoc, maxLoc, matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
  matchLoc = minLoc;

  return matchLoc;
}


///------- tracking --------------------------------------------------------------------------------------------------------

void track()
{
    if (select_flag)
    {
        roiImg.copyTo(mytemplate);
//         select_flag = false;   //select_flag is kept false so that new template can
        go_fast = true;           //copied to 'mytemplate' for each iteration
    }

//     imshow( "mytemplate", mytemplate ); waitKey(0);

    Mat result  =  TplMatch( img, mytemplate );
    Point match =  minmax( result );  //PROBLEM: "match" always returning same value!!!

    rectangle( img, match, Point( match.x + mytemplate.cols , match.y + mytemplate.rows ), CV_RGB(255, 255, 255), 0.5 );

    std::cout << "match: " << match << endl;

    /// template update step
    Rect ROI = cv::Rect( match.x, match.y, mytemplate.cols, mytemplate.rows );
    roiImg = img( ROI );
    imshow( "roiImg", roiImg ); //waitKey(0);
}


///------- MouseCallback function ------------------------------------------------------------------------------------------

void mouseHandler(int event, int x, int y, int flags, void *param)
{
    if (event == CV_EVENT_LBUTTONDOWN && !drag)
    {
        /// left button clicked. ROI selection begins
        point1 = Point(x, y);
        drag = 1;
    }

    if (event == CV_EVENT_MOUSEMOVE && drag)
    {
        /// mouse dragged. ROI being selected
        Mat img1 = img.clone();
        point2 = Point(x, y);
        rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
        imshow("image", img1);
    }

    if (event == CV_EVENT_LBUTTONUP && drag)
    {
        point2 = Point(x, y);
        rect = Rect(point1.x, point1.y, x - point1.x, y - point1.y);
        drag = 0;
        roiImg = img(rect);
    }

    if (event == CV_EVENT_LBUTTONUP)
    {
        /// ROI selected
        select_flag = 1;
        drag = 0;
    }

}



///------- Main() ----------------------------------------------------------------------------------------------------------

int main()
{
    int k;

    ///open video file
    VideoCapture cap;
    cap.open( "Megamind.avi" );
    if ( !cap.isOpened() )
    {   cout << "Unable to open video file" << endl;    return -1;    }

    cap >> img;
    GaussianBlur( img, img, Size(7,7), 3.0 );
    imshow( "image", img );

    while (1)
    {
        cap >> img;
        if ( img.empty() )
            break;

        // Flip the frame horizontally and add blur
        cv::flip( img, img, 1 );
        GaussianBlur( img, img, Size(7,7), 3.0 );

        if ( rect.width == 0 && rect.height == 0 )
            cvSetMouseCallback( "image", mouseHandler, NULL );
        else
            track();

        imshow("image", img);
        k = waitKey(go_fast ? 30 : 10000);
        if (k == 27)
            break;
    }

    return 0;
}

The updated template is not being tracked. 不会跟踪更新的模板。 I am not able to figure out why this is happening since I am updating my template (roiImg) with each iteration. 我无法弄清楚为什么会发生这种情况,因为我每次迭代都更新模板(roiImg)。 The match value from minmax() function is returning the same value (coordinates) every-time. minmax()函数的匹配值每次都返回相同的值(坐标)。 Test video is availbale at: Megamind Please look into it and guide ahead...thanks a lot! 测试视频可在以下位置找到: Megamind请仔细研究并指导前进...非常感谢!

EDIT: if you run the code (with the video) you will see the white bounding-box is always at the same position. 编辑:如果您运行代码(与视频),您将看到白色边框始终位于同一位置。 This is because, the minmax() is returning same "match" value all the time. 这是因为minmax()一直都在返回相同的“ match”值。 This value should change with every update. 该值应随每次更新而更改。 Try running code with select_flag = false; 尝试使用select_flag = false运行代码 (uncommitted). (未提交)。 The bounding-box is moving according to template. 边界框根据模板移动。 But in this case no template update takes place. 但是在这种情况下,不会进行模板更新。

The problem is in this section: 问题在此部分中:

if (select_flag)
{
    roiImg.copyTo(mytemplate);
    // select_flag = false;   //select_flag is kept false so that new template can
    // ^^^^^^^^^^^ WRONG
    go_fast = true;           //copied to 'mytemplate' for each iteration
}

You actually need to set select_flag to be false on the first iteration. 实际上,您需要在第一次迭代中将select_flag设置为false Otherwise, you're just copying what's in the current image on that frame into your template, and of course you find it in exactly the same place! 否则,您只是将该帧上当前图像中的内容复制到模板中,当然您可以在完全相同的位置找到它!

Once that's done, make sure you move your template update to after the tracking is done on that frame. 完成此操作后,请确保在该框架上完成跟踪后将模板更新移动到。 I'd also recommend not drawing on the original image (your rectangle ) until after all image accesses are done. 我还建议您在完成所有图像访问后,才在原始图像( rectangle )上进行绘制。 You were actually drawing the rectangle into your image before copying out of it. 您实际上是在复制矩形之前将矩形绘制到图像中。 Here's my adjusted function with template update: 这是我通过模板更新调整后的功能:

void track()
{
  std::cout << select_flag << std::endl;

    if (select_flag)
    {
        roiImg.copyTo(mytemplate);
        select_flag = false;   //select_flag is kept false so that new template can
        go_fast = true;           //copied to 'mytemplate' for each iteration

    }

//     imshow( "mytemplate", mytemplate ); waitKey(0);

    Mat result  =  TplMatch( img, mytemplate );

    imshow("match", result);

    Point match =  minmax( result );  //PROBLEM: "match" always returning same value!!!

    std::cout << "match: " << match << endl;

    /// template update step
    Rect ROI = cv::Rect( match.x, match.y, mytemplate.cols, mytemplate.rows );

    std::cout << ROI << std::endl;

    roiImg = img( ROI );
    imshow( "roiImg", roiImg ); //waitKey(0);

    // Update the template AFTER tracking has occurred to carry it over to the next frame
    roiImg.copyTo(mytemplate);
    imshow("mytemplate", mytemplate);

    // Draw onto the image AFTER all accesses are performed
    rectangle( img, match, Point( match.x + mytemplate.cols , match.y + mytemplate.rows ), CV_RGB(255, 255, 255), 0.5 );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM