我正在尝试使用OpenCV跟踪一个房间里的人。
我理解通常的程序是:
1)做面部检测
2)查找内部功能
3)创建一个模板(在我的情况下是眼睛对)
4)然后,对以前的位置进行模板匹配,并使用minMaxloc()
评估值
5)如果匹配不正确,请重新检测并存储新模板
但是,我正在努力从minMaxLoc()
中获取有意义的价值。差异太小,跟踪会产生太多的误报。
我尝试了使用不同阈值的最小值和最大值的各种方法,但我无处可去。
也许我需要预处理数据?我尝试了标准化,但它只是使大多数值非常小(大约10e-10)。另外,我应该尝试缩放模板以提高准确性吗? 使用不同的模板匹配方法怎么样?
代码:
使用命名空间std; 使用namespace 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 << "\n\n\n LOST TRACK \n\n";
}
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 face\n"); };
// if (!eye_cascade.load("haarcascades/haarcascade_eye.xml")) { printf("--(!)Error loading eyepair\n"); };
if (!eye_cascade.load(m_eyePair_cascade_file)) { printf("--(!)Error loading eyepair\n"); };
// 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);
}
}
答案 0 :(得分:0)
您是否尝试过使用CV_TM_CCORR_NORMED而不是CV_TM_SQDIFF_NORMED?