Соответствие шаблонов в реальном времени — OpenCV, переполнение стека

Я пытаюсь реализовать отслеживание в режиме реального времени с использованием шаблонов. Я хочу обновить шаблон с каждым кадром. Основные модификации, которые я сделал:

1) разделить шаблон соответствия и minmaxLoc на отдельные модули, а именно, TplMatch () а также мин Макс() функции соответственно.

2) Внутри дорожка () Функция select_flag всегда сохраняется, так что новый шаблон копируется в ‘myTemplate’ с каждой итерацией.

3) последние 3 строки функции дорожка () должны обновить шаблон (roiImg).

4) Также, Я удалил все аргументы дорожка () функция, так как, IMG а также roiImg являются глобальными переменными и, следовательно, нет необходимости передавать их в функции.

Ниже приведен код:

#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;
go_fast = true;
}

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

Mat result  =  TplMatch( img, mytemplate );
Point match =  minmax( result );

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

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

/// latest match is the new template
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);
//  imshow("MOUSE roiImg", roiImg); waitKey(0);
}

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

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

int main()
{
int k;
/*
///open webcam
VideoCapture cap(0);
if (!cap.isOpened())
return 1;*/

///open video file
VideoCapture cap;
cap.open( "Megamind.avi" );
if ( !cap.isOpened() )
{   cout << "Unable to open video file" << endl;    return -1;    }
/*
/// Set video to 320x240
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);*/

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);
//  waitKey(100);   k = waitKey(75);
k = waitKey(go_fast ? 30 : 10000);
if (k == 27)
break;
}

return 0;
}

Обновленный шаблон не отслеживается. Я не могу понять, почему это происходит, так как я обновляю свой шаблон (roiImg) с каждой итерацией. матч значение от мин Макс() Функция каждый раз возвращает одну и ту же точку (координаты). Тестовое видео доступно по адресу: http://www.youtube.com/watch?v=vpnkk7N2E0Q&Функция = youtu.be
Пожалуйста, посмотрите на это и ведите вперед … большое спасибо!

8

Решение

Я получил ваш оригинальный код из этой версии вашего вопроса: https://stackoverflow.com/revisions/20180073/3

Я сделал наименьшее изменение в вашем исходном коде, мой следующий код выглядит следующим образом:

#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;
go_fast = true;
}

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

Mat result  =  TplMatch( img, mytemplate );
Point match =  minmax( result );

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

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

/// latest match is the new template
Rect ROI = cv::Rect( match.x, match.y, mytemplate.cols, mytemplate.rows );
roiImg = img( ROI );
roiImg.copyTo(mytemplate);
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);
roiImg.copyTo(mytemplate);
//  imshow("MOUSE roiImg", roiImg); waitKey(0);
}

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

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

int main()
{
int k;
/*
///open webcam
VideoCapture cap(0);
if (!cap.isOpened())
return 1;*/

///open video file
VideoCapture cap;
cap.open( "Megamind.avi" );
if ( !cap.isOpened() )
{   cout << "Unable to open video file" << endl;    return -1;    }
/*
/// Set video to 320x240
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);*/

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);
//  waitKey(100);   k = waitKey(75);
k = waitKey(go_fast ? 30 : 10000);
if (k == 27)
break;
}

return 0;
}

Видео на https://www.youtube.com/watch?v=rBCopeneCos показывает тест вышеуказанной программы.

Я бы избегал использования глобальных переменных, потому что я думаю, что они не помогают понять, в чем проблема; Кроме того, я бы также обратил внимание на неглубокую и глубокую копию для OpenCV Mat класс, как 1 » написал в своем ответ:

OpenCV-х Mat класс — это просто заголовок для фактических данных изображения,
на который он содержит указатель. operator= копирует указатель
(и другая информация в заголовке, например размеры изображения)
так что оба мата имеют одни и те же данные. Это означает, что изменение
данные в одном мате также изменяют его в другом. Это называется
«мелкая» копия, поскольку копируется только верхний слой (заголовок), а не
нижний слой (данные).

Чтобы сделать копию базовых данных (называемую «глубокой копией»), используйте
clone() метод. Вы можете найти информацию об этом на странице, которая
Вы связаны с.

Редактировать о дрифте:
В комментарии Соответствие шаблонов в реальном времени — OpenCV, C ++, ученик спрашивает про отслеживание дрейфа.
Смотря видео https://www.youtube.com/watch?v=rBCopeneCos мы видим, что в начале видео программа отслеживает правый глаз девушки, в то время как в 0:15 она начинает отслеживать брови девушки, в 0:19 она начинает отслеживать брови мальчика и больше никогда не отслеживает глаз девушки, например, в 0:27 он отслеживает правую бровь девушки, в то время как правый глаз девушки четко виден на снимке

Этот переход от отслеживания глаза к отслеживанию брови является нормальным в простом коде, который я опубликовал, и объяснение довольно простое: посмотрите видео на https://www.youtube.com/watch?v=sGHEu3u9XvI, видео начинается с отслеживания (содержимого черного прямоугольника) игральной карты, затем я удаляю игральную карту со сцены, и отслеживающий черный прямоугольник «дрейфует» в левом нижнем углу сцены; В конце концов, мы постоянно обновляем шаблон, и поэтому поведение корректное: программа останавливает отслеживание игральной карты и начинает отслеживать белый фон, и у вас появляется «дрейф» … другими словами, ваш TplMatch() функция всегда будет возвращать действительный result изображение и ваша текущая реализация minmax() всегда будет возвращать действительный минимум.

13

Другие решения

Вы можете следовать учебнику OpenCV «Шаблон соответствия». Ваш track функция может содержать код для поиска шаблона в текущем кадре; простой код основан на matchTemplate а также minMaxLoc функции.

Интересная проблема, связанная с частью «реального времени» вашего вопроса, заключается в том, чтобы найти совпадение, если оно есть, за время между текущим и следующим кадрами.

редактировать:

Следующий быстрый и грязный код и видео на http://www.youtube.com/watch?v=vpnkk7N2E0Q&Функция = youtu.be показывает, что я имею в виду отслеживание.

Так как у меня нет веб-камеры, я немного изменил ваш код, чтобы просто использовать видео, этот https://code.ros.org/trac/opencv/export/7237/trunk/opencv/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video/Megamind.avi

Я тогда добавляю track функция и некоторая логика, чтобы замедлить видео, пока я не выберу ROI и после этого воспроизведение видео с нормальной скоростью.

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

void track(cv::Mat &img, const cv::Mat &templ, const cv::Rect &r )
{
static int n = 0;

if (select_flag)
{
templ.copyTo(mytemplate);
select_flag = false;
go_fast = true;
}cv::Mat result;
/// Do the Matching and Normalize
matchTemplate( img, mytemplate, result, CV_TM_SQDIFF_NORMED );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

/// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;

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

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

std::cout << matchLoc << "\n";
}

///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 function

int main()
{
int k;
/*
VideoCapture cap(0);
if (!cap.isOpened())
return 1;
*/
VideoCapture cap;
//cap.open("~/Downloads/opencv-2.4.4/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video/Megamind.avi");
cap.open("./Megamind.avi");
if (!cap.isOpened())
{
printf("Unable to open video file\n");
return -1;
}

/*
// Set video to 320x240
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
*/

cap >> img;
imshow("image", img);

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

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

if (select_flag == 1)
imshow("Template", roiImg);

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

}return 0;
}
2

Вы также можете получить общее представление о предмете, начиная с этой страницы википедии. http://en.wikipedia.org/wiki/Video_tracking

0
По вопросам рекламы [email protected]