如何提高OpenCV模板跟踪的准确性?要使用的参数
How to improve OpenCV Template Tracking Accuracy? What parameters to use?
我正试图使用OpenCV跟踪房间里的人。
我知道通常的程序是:1) 进行人脸检测2) 在中查找功能3) 创建一个模板(在我的例子中是眼睛对)4) 然后,对之前的位置进行模板匹配,并使用minMaxloc()
评估值5) 如果匹配不正确,则重新检测并存储新模板
然而,我正在努力从minMaxLoc()
中获得有意义的价值。差异太小,跟踪产生的误报太多。
我尝试了各种方法来使用不同阈值的最小值和最大值,但我一无所获。
也许我需要对数据进行预处理?我尝试过规范化,但它只是使大多数值非常小(大约10e-10)。此外,我应该尝试缩放模板以提高准确性吗?使用不同的模板匹配方法怎么样?
代码:
使用命名空间std;使用命名空间cv;
cv::CascadeClassifier face_cascade;
cv::CascadeClassifier eye_cascade;
cv::Mat other, other2;
int count_val = 0;
double checkVal = -10;
int second_count = 20;
int detectEye(cv::Mat& im, cv::Mat& tpl, cv::Rect& rect)
{
std::vector<cv::Rect> faces, eyes;
face_cascade.detectMultiScale(im, faces, 1.1, 2,
CV_HAAR_SCALE_IMAGE, cv::Size(30, 30));
for (int i = 0; i < faces.size(); i++)
{
cv::Mat face = im(faces[i]);
eye_cascade.detectMultiScale(face, eyes, 1.1, 2,
CV_HAAR_SCALE_IMAGE, cv::Size(20, 20));
if (eyes.size())
{
rect = eyes[0] + cv::Point(faces[i].x, faces[i].y);
if (count_val == 0){
tpl = im(rect);
count_val = 5;
}
else{
count_val--;
}
}
}
return eyes.size();
}
Rect trackEye(cv::Mat& im, cv::Mat& tpl, cv::Rect& rect)
{
cv::Size size(rect.width * 0.5, rect.height * 2);
cv::Rect window(rect + size - cv::Point(size.width / 2, size.height / 2));
window &= cv::Rect(0, 0, im.cols, im.rows);
cv::Mat dst(window.height - tpl.rows + 1, window.width - tpl.cols + 1, CV_32FC1);
cv::matchTemplate(im(window), tpl, dst, CV_TM_SQDIFF_NORMED);
other = dst;
other2 = tpl;
//mormalising makes it really difficult to find a match, the range it too small
//normalize(dst, dst, 0, 1, NORM_MINMAX, -1, Mat());
double minval, maxval;
cv::Point minloc, maxloc;
cv::minMaxLoc(dst, &minval, &maxval, &minloc, &maxloc);
cv::Point target = minloc;
cout << minval << " " << maxval<<" "<< checkVal << endl;
//if (minval <= checkVal || minval == 0|| checkVal == -10)
if (maxval >0.25) //normally you would use the minval, but the range it too small...
//if (minval >0.01)
{
rect.x = window.x + target.x;
rect.y = window.y + target.y;
if (checkVal == -10)
checkVal = minval;
}
else{
rect.x = rect.y = rect.width = rect.height = 0;
cout << "nnn LOST TRACK nn";
}
return window;
}
int main(int argc, const char** argv) {
// Load the cascade classifiers
// Make sure you point the XML files to the right path, or
// just copy the files from [OPENCV_DIR]/data/haarcascades directory
String m_eyePair_cascade_file = "haarcascades/haarcascade_mcs_eyepair_big.xml";
if (!face_cascade.load("haarcascades/haarcascade_frontalface_alt2.xml")) { printf("--(!)Error loading facen"); };
// if (!eye_cascade.load("haarcascades/haarcascade_eye.xml")) { printf("--(!)Error loading eyepairn"); };
if (!eye_cascade.load(m_eyePair_cascade_file)) { printf("--(!)Error loading eyepairn"); };
// Open webcam
//cv::VideoCapture cap(0);
// Check if everything is ok
VideoCapture cap;
if (!cap.open(0)) {
cerr << "Cannot open camera" << endl;
exit(-1);
}
if (face_cascade.empty() || eye_cascade.empty() || !cap.isOpened())
return 1;
// Set video to 320x240
cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
cv::Mat frame, eye_tpl;
cv::Rect eye_bb;
while (cv::waitKey(15) != 'q')
{
second_count--;
cap >> frame;
if (frame.empty())
break;
// Flip the frame horizontally, Windows users might need this
cv::flip(frame, frame, 1);
// Convert to grayscale and
// adjust the image contrast using histogram equalization
cv::Mat gray;
cv::cvtColor(frame, gray, CV_BGR2GRAY);
if (second_count == 0){
eye_bb.width == 0;
count_val = 0;
second_count = 20;
}
//cout << eye_bb << endl;
if (eye_bb.width == 0)
{
// Detection stage
// Try to detect the face and the eye of the user
detectEye(gray, eye_tpl, eye_bb);
}
else
{
// Tracking stage with template matching
Rect r = trackEye(gray, eye_tpl, eye_bb);
// Draw bounding rectangle for the eye
cv::rectangle(frame, eye_bb, CV_RGB(0, 255, 0));
cv::rectangle(frame, r, CV_RGB(255, 255, 0));
}
// Display video
cv::imshow("video2", frame);
if (other.data != nullptr){
cv::imshow("video", other);
cv::imshow("video3", other2);
}
Sleep(400);
}
}
您是否尝试过使用CV_TM_CCOR_NORMED而不是CV_TM_SQDIFF_NORMED?
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何提高OpenCV模板跟踪的准确性?要使用的参数