面部和眼部检测不正常

时间:2015-12-06 14:10:22

标签: c++ opencv

使用下面的代码我想从视频中检测面部和眼睛,

代码运行没有错误,但运行时没有显示视频和检测结果,有什么问题?

我尝试使用图像,它可以在某些图像上正常工作,而其他图像只能检测到脸部。

#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
float EYE_SX = 0.16f;
float EYE_SY = 0.26f;
float EYE_SW = 0.30f;
float EYE_SH = 0.28f;

Mat dest, gray,frame;
VideoCapture capture("m.mp4");


CascadeClassifier detector, eyes_detector;

if (!capture.isOpened())  // check if we succeeded
    return -1;

if(!detector.load("haarcascade_frontalface_alt2.xml"))
    cout << "No se puede abrir clasificador." << endl;

if(!eyes_detector.load("haarcascade_eye_tree_eyeglasses.xml"))
    cout << "No se puede abrir clasificador para los ojos." << endl;
for (;;)
{

    capture >> frame;
    cvtColor(frame, gray, CV_BGR2GRAY);
    equalizeHist(gray, dest);

    vector<Rect> rect;
    detector.detectMultiScale(dest, rect);

    for (Rect rc : rect)
    {
        rectangle(frame,
            Point(rc.x, rc.y),
            Point(rc.x + rc.width, rc.y + rc.height),
            CV_RGB(0, 255, 0), 2);
    }

    if (rect.size() > 0)
    {
        Mat face = dest(rect[0]).clone();
        vector<Rect> leftEye, rightEye;

        int leftX = cvRound(face.cols * EYE_SX);
        int topY = cvRound(face.rows * EYE_SY);
        int widthX = cvRound(face.cols * EYE_SW);
        int heightY = cvRound(face.rows * EYE_SH);
        int rightX = cvRound(face.cols * (1.0 - EYE_SX - EYE_SW));

        Mat topLeftOfFace = face(Rect(leftX, topY, widthX, heightY));
        Mat topRightOfFace = face(Rect(rightX, topY, widthX, heightY));

        eyes_detector.detectMultiScale(topLeftOfFace, leftEye);
        eyes_detector.detectMultiScale(topRightOfFace, rightEye);

        if ((int)leftEye.size() > 0)
        {
            rectangle(frame,
                Point(leftEye[0].x + leftX + rect[0].x, leftEye[0].y + topY + rect[0].y),
                Point(leftEye[0].width + widthX + rect[0].x - 5, leftEye[0].height + heightY + rect[0].y),
                CV_RGB(0, 255, 255), 2);
        }

        if ((int)rightEye.size() > 0)
        {
            rectangle(frame,
                Point(rightEye[0].x + rightX + leftX + rect[0].x, rightEye[0].y + topY + rect[0].y),
                Point(rightEye[0].width + widthX + rect[0].x + 5, rightEye[0].height + heightY + rect[0].y),
                CV_RGB(0, 255, 255), 2);
        }
    }
}
imshow("Ojos", frame);

waitKey(0);
return 1;
}

1 个答案:

答案 0 :(得分:1)

所以,现在,imshow("Ojos", frame);waitKey(0);只能在程序结束前调用。这对图像来说很好,但不适用于视频,因为你希望它每帧发生一次。

如果你向上移动几行,在for循环中(基本上,只需将支架从它下面的一行放一行),它应该开始更好地适用于视频。

但是,您可能需要在代码中调整其他一些内容 - 它只会显示一只右眼和一只左眼。这通常是你想要发生的事情,但是如果你有误报,你可能最终会将某人的头发或皮肤贴上眼睛的标签,而你却不知道如何发生。我建议在lefteye和righteye向量中显示所有项目。这可以通过用

替换那些if语句(if (int)rightEye.size() > 0等)来完成
for (int i = 0; i < rightEye.size(); i++) {
         rectangle(frame,
            Point(rightEye[i].x + rightX + leftX + rect[i].x, 
            rightEye[i].y + topY + rect[i].y),
            Point(rightEye[i].width + widthX + rect[i].x + 5, 
            rightEye[i].height + heightY + rect[i].y),
            CV_RGB(0, 255, 255), 2);
}

如果您遇到误报或否定问题,您可能需要调查detectMultiscale上的参数调整 - 现在,您将所有内容都保留为默认值。 Multiscale有许多参数可以放入。你已经拥有的图像和对象,但还有其他参数,例如:

  • scaleFactor - 指定图像大小的参数 在每个图像尺度下减少。默认值为1.1。越大,规模就越大,这将使级联时间减少,但会出现更多的误报。
  • minNeighbors - 指定方式的参数 许多邻居每个候选矩形都应该保留它。默认值为3.越大,它搜索的邻居越多,误报率越低,但需要的时间越长。调整得太高,它会开始给出假阴性。
  • flags - 具有与旧级联相同含义的参数 function cvHaarDetectObjects。它不用于新的级联。默认值为零,大部分时间都保持为零。
  • minSize - 最小可能的对象大小。小于的对象是 忽略。默认值为Size(0,0)。我倾向于把它碰到一点点。同样,更大意味着它更快,更少误报,但是太大会跳过你正在寻找的任何东西。
  • maxSize - 可能的最大对象大小。大于的对象 被忽略了。默认是我相信传入图像的最大尺寸。我倾向于将其限制为小于此值。较小的这意味着它更快,更少误报,但是太小会跳过你正在寻找的任何东西。

cascade_name.detectMultiScale( frame_gray, frame_rectangle, 1.1, 2, 0, Size(30, 30) );,作为一个例子。