如何提高OpenCV模板跟踪的准确性?要使用的参数

How to improve OpenCV Template Tracking Accuracy? What parameters to use?

本文关键字:参数 准确性 OpenCV 跟踪 何提高      更新时间:2023-10-16

我正试图使用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?