使用OpenCV在视频中进行人脸识别会产生未处理的异常 [英] Face Recognition in Video using OpenCV gives unhandled exception

查看:112
本文介绍了使用OpenCV在视频中进行人脸识别会产生未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在OpenCV随附的视频示例中使用面部识别.我所做的唯一修改是:我没有使用命令行参数来提供CSV和Cascade分类器路径,而是直接在代码中给了它们.这是代码:

I am trying to use the Face Recognition in video sample provided with OpenCV. The only modification I've done is: Instead of using command line arguments to provide CSV and Cascade classifier paths, I have given them directly in the code. This is the code:

#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"

#include <iostream>
#include <fstream>
#include <sstream>

using namespace cv;
using namespace std;

static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
    std::ifstream file(filename.c_str(), ifstream::in);
    if (!file) {
        string error_message = "No valid input file was given, please check the given filename.";
        CV_Error(CV_StsBadArg, error_message);
    }
    string line, path, classlabel;
    while (getline(file, line)) {
        stringstream liness(line);
        getline(liness, path, separator);
        getline(liness, classlabel);
        if(!path.empty() && !classlabel.empty()) {
            images.push_back(imread(path, 0));
            labels.push_back(atoi(classlabel.c_str()));
        }
    }
}

int main(int argc, const char *argv[]) {
// Check for valid command line arguments, print usage
// if no arguments were given.
if (argc != 4) {
    cout << "usage: " << argv[0] << " </path/to/haar_cascade> </path/to/csv.ext> </path/to/device id>" << endl;
    cout << "\t </path/to/haar_cascade> -- Path to the Haar Cascade for face detection." << endl;
    cout << "\t </path/to/csv.ext> -- Path to the CSV file with the face database." << endl;
    cout << "\t <device id> -- The webcam device id to grab frames from." << endl;
    //exit(1);
}
// Get the path to your CSV:
string fn_haar = "C:\\OpenCV-2.4.2\\opencv\\data\\haarcascades\\haarcascade_frontalface_default.xml";
string fn_csv = "C:\\Users\\gaspl\\Desktop\\train.txt";
int deviceId = 1;
// These vectors hold the images and corresponding labels:
vector<Mat> images;
vector<int> labels;
// Read in the data (fails if no valid input filename is given, but you'll get an error message):
try {
    read_csv(fn_csv, images, labels);
} catch (cv::Exception& e) {
    cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
    // nothing more we can do
    exit(1);
}
// Get the height from the first image. We'll need this
// later in code to reshape the images to their original
// size AND we need to reshape incoming faces to this size:
int im_width = images[0].cols;
int im_height = images[0].rows;
// Create a FaceRecognizer and train it on the given images:
Ptr<FaceRecognizer> model = createFisherFaceRecognizer();
model->train(images, labels);
// That's it for learning the Face Recognition model. You now
// need to create the classifier for the task of Face Detection.
// We are going to use the haar cascade you have specified in the
// command line arguments:
//
CascadeClassifier haar_cascade;
haar_cascade.load(fn_haar);
// Get a handle to the Video device:
VideoCapture cap(deviceId);
// Check if we can use this device at all:
if(!cap.isOpened()) {
    cerr << "Capture Device ID " << deviceId << "cannot be opened." << endl;
    return -1;
}
// Holds the current frame from the Video device:
Mat frame;
for(;;) {
    cap >> frame;
    // Clone the current frame:
    Mat original = frame.clone();
    // Convert the current frame to grayscale:
    Mat gray;
    cvtColor(original, gray, CV_BGR2GRAY);
    // Find the faces in the frame:
    vector< Rect_<int> > faces;
    haar_cascade.detectMultiScale(gray, faces);
    // At this point you have the position of the faces in
    // faces. Now we'll get the faces, make a prediction and
    // annotate it in the video. Cool or what?
    for(int i = 0; i < faces.size(); i++) {
        // Process face by face:
        Rect face_i = faces[i];
        // Crop the face from the image. So simple with OpenCV C++:
        Mat face = gray(face_i);
        // Resizing the face is necessary for Eigenfaces and Fisherfaces. You can easily
        // verify this, by reading through the face recognition tutorial coming with OpenCV.
        // Resizing IS NOT NEEDED for Local Binary Patterns Histograms, so preparing the
        // input data really depends on the algorithm used.
        //
        // I strongly encourage you to play around with the algorithms. See which work best
        // in your scenario, LBPH should always be a contender for robust face recognition.
        //
        // Since I am showing the Fisherfaces algorithm here, I also show how to resize the
        // face you have just found:
        Mat face_resized;
        cv::resize(face, face_resized, Size(im_width, im_height), 1.0, 1.0, INTER_CUBIC);
        // Now perform the prediction, see how easy that is:
        int prediction = model->predict(face_resized);
        // And finally write all we've found out to the original image!
        // First of all draw a green rectangle around the detected face:
        rectangle(original, face_i, CV_RGB(0, 255,0), 1);
        // Create the text we will annotate the box with:
        string box_text = format("Prediction = %d", prediction);
        // Calculate the position for annotated text (make sure we don't
        // put illegal values in there):
        int pos_x = std::max(face_i.tl().x - 10, 0);
        int pos_y = std::max(face_i.tl().y - 10, 0);
        // And now put it into the image:
        putText(original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
    }
    // Show the result:
    imshow("face_recognizer", original);
    // And display it:
    char key = (char) waitKey(20);
    // Exit this loop on escape:
    if(key == 27)
        break;
    }
    return 0;
}

这是我的train.txt CSV文件的样子:

This is what my train.txt CSV file looks like:

C:\\Training\\extract0.jpg;0
C:\\Training\\extract1.jpg;0
C:\\Training\\extract2.jpg;0

但是,当我尝试运行该示例(构建良好)时,出现这些错误,并要求我执行Break:

However when I try to run the sample (it builds fine), I get these errors and it asks me to Break:

First-chance exception at 0x000007FEFE04CAED in facrec.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000025C530.
Unhandled exception at at 0x000007FEFE04CAED in facrec.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000025C530.

该错误发生在我初始化Fisher识别器的位置:

The error occurs at the point where I initialize the Fisher Recognizer:

Ptr<FaceRecognizer> model = createFisherFaceRecognizer();
model->train(images, labels);

我正在将Windows 7 64位与Visual Studio 2012和OpenCV 2.4.2(内部配置:x64发行版)一起使用

I am using Windows 7 64-bit with Visual Studio 2012 and OpenCV 2.4.2 (Build Configuration: x64-Release)

我已经尝试了面部检测和面部提取,它们在我的计算机上可以正常工作(如果有人想检出代码),因此,我的Visual Studio项目设置(链接器或C/C ++)显然没有问题.

I have already tried face detection and face extraction and they work fine on my computer(If anyone wants to check out the code), so there is apparently no problem with my Visual studio project settings (Linker or C/C++).

这里有一个类似的问题,但它仍然无法解决任何问题.

There is a similar question here but it still doesnt solve anything.

我的工作有什么问题吗?

Anything wrong with what I am doing?

推荐答案

我们已经通过邮件得出结论.发生这种情况是因为CSV文件中只给出了一个标签:

As we have already concluded by mail. This happens, because only one label is given in your CSV file:


C:\Training\extract0.jpg;0
C:\Training\extract1.jpg;0
C:\Training\extract2.jpg;0

Fisherfaces方法至少需要两个类来学习模型.这种情况应该已经捕获,并且OpenCV 2.4.2在我的系统上引发以下异常:

The Fisherfaces method needs at least two classes to learn a model. This case should have been caught and OpenCV 2.4.2 throws the following exception on my system:


OpenCV Error: Bad argument (At least two classes are needed to perform a LDA. Reason: Only one class was given!) in lda, file /home/philipp/github/libfacerec/src/subspace.cpp, line 150
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/philipp/github/libfacerec/src/subspace.cpp:150: error: (-5) At least two classes are needed to perform a LDA. Reason: Only one class was given! in function lda

这很清楚训练数据中的错误.我不知道,为什么在Windows 7安装中不会引发此异常,但是我将设置一个测试系统以尽快重现并进行相应的修复.

Which makes the error in the training data quite clear. I don't know, why this exception isn't thrown on your Windows 7 installation, but I'll set up a test system to reproduce as soon as possible and fix accordingly.

这篇关于使用OpenCV在视频中进行人脸识别会产生未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆