2012-11-02 89 views
6

Tôi đang cố gắng sử dụng Nhận dạng khuôn mặt trong mẫu video được cung cấp với OpenCV. Sửa đổi duy nhất tôi đã thực hiện là: Thay vì sử dụng các đối số dòng lệnh để cung cấp đường dẫn phân loại CSV và Cascade, tôi đã cung cấp cho chúng trực tiếp trong mã. Đây là mã:Nhận diện khuôn mặt trong video bằng cách sử dụng OpenCV cho ngoại lệ không được xử lý

#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; 
} 

Đây là những gì tập tin CSV train.txt của tôi trông giống như:

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

Tuy nhiên khi tôi cố gắng chạy mẫu (nó xây dựng tốt), tôi nhận được các lỗi này và nó yêu cầu tôi 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. 

lỗi này xảy ra vào thời điểm mà tôi khởi tạo Fisher Recognizer:

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

Tôi đang sử dụng Windows 7 64-bit với Visual Studio 2012 và OpenCV 2.4.2 (Build Cấu hình: x64-Release)

Tôi đã cố gắng nhận diện khuôn mặt và khai thác mặt và họ làm việc tốt trên máy tính của tôi (If anyone wants to check out the code), do đó, dường như không có vấn đề gì với cài đặt dự án Visual Studio của tôi (Linker hoặc C/C++).

There is a similar question here nhưng vẫn không giải quyết được gì.

Có gì sai với những gì tôi đang làm?

+0

Ngoại lệ thường cho biết điều gì sai. Bạn nên xử lý nó và nhìn vào thông điệp của nó. –

+1

@AndreyKamaev Tôi đã cố gắng để gỡ lỗi nó, và có vẻ như vấn đề là với dòng này trong mã 'images.push_back (imread (đường dẫn, 0));' trong 'read_csv()' chức năng. Nó không thêm dữ liệu hình ảnh vào mảng 'hình ảnh', đó là lý do tại sao chức năng huấn luyện và dự đoán Fisher đưa ra một ngoại lệ. Có điều gì sai với việc triển khai 'imread()' hay với định dạng đường dẫn trong tệp CSV không? –

Trả lời

11

Vì chúng tôi đã kết thúc bằng thư. Điều này xảy ra, bởi vì chỉ có một nhãn được cung cấp trong tệp CSV của bạn:

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

Phương thức Fisherfaces cần ít nhất hai lớp để tìm hiểu mô hình. Trường hợp này đáng lẽ phải bị bắt và OpenCV 2.4.2 ném ngoại lệ sau vào hệ thống của tôi:

 
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 

Điều này làm cho lỗi trong dữ liệu huấn luyện khá rõ ràng. Tôi không biết, tại sao ngoại lệ này không được ném vào cài đặt Windows 7 của bạn, nhưng tôi sẽ thiết lập một hệ thống thử nghiệm để tái sản xuất càng sớm càng tốt và sửa cho phù hợp.

+0

Mọi phương án thay thế khi tôi chỉ có một nhãn? – lzt

Các vấn đề liên quan