Opencv com c++ Reconhecimento facial com algoritimo fisherface sempre reconhece a mesma pessoa pra todas as pessoas mesmo com imagem identica de entrada e reconstroi uma imagem preta
Olá, estou fazendo um trabalho de faculdade pra reconhecimento facial utilizando o opencv na linguagem c++ e fazendo interface com Windows forms, basicamente eu tenho o código que coleta as fotos e salva cada pessoa com suas fotos e depois recupera as imagens, isso ele não apresenta erros pq eu já testei todos esses retornos da recuperação e não esta nada errado, o problema é o seguinte, quando eu faço o programa reconhecer uma imagem mesmo sendo a mesma imagem q utilizei pra poder tratar o rosto e salvar pra identificação posterior, ele me diz q é sempre igual ao primeiro rosto que ele recuperou dos arquivos, e como eu falei, ele recupera todas as imagens dos arquivos então não tem erro na recuperação, e quando chega no momento de identificação ele recupera as informações do Modelo do reconhecimento facial e reconstrói essa imagem pra verificar semelhança com a imagem q deve ser identificada, porem ao fazer essa recuperação do próprio modelo que já recebeu treinamento corretamente antes, ele retorna uma imagem completamente preta, a questão é o seguinte eu acredito q tenha algo de errado em relação ao Modelo do reconhecimento facial, não sei se é a declaração ou oque esta acontecendo, mas algo esta dando errado nele, pq esse mesmo código funciona em um projeto de teste que fiz rodando apenas no console, sem interface do Windows forms, ele reconhece a imagem correta e reconstrói sem erros mas esse com interface apresenta esses erros que não consigo identificar!
Segue o código da função principal que é a que executa o loop pra identificação do rosto e de acordo com as entradas recebidas pelo Windows forms, o programa executa uma atividade:
Segue o código da função principal que é a que executa o loop pra identificação do rosto e de acordo com as entradas recebidas pelo Windows forms, o programa executa uma atividade:
void RecognitionAlgo::Running() { // Create the cascade classifier object used for the face detection cv::CascadeClassifier face_cascade; // Use the haarcascade frontalface_alt.xml library if (!face_cascade.load("haarcascade_frontalface_alt.xml")) { Log("Error at face Cascade Load!") } // Setup image files used in the capture process cv::Mat captureFrame; cv::Mat grayscaleFrame; cv::Mat shrinkFrame; // Create a vector to store the face found std::vector<cv::Rect> faces; std::vector<cv::Mat> Preprocessed_Faces; std::vector<cv::string> Preprocessed_Faces_Names; cv::string myname; std::vector<int> faceLabels; // Init the face Recognizer cv::initModule_contrib(); std::string facerecAlgorithm = "FaceRecognizer.Fisherfaces"; cv::Ptr<cv::FaceRecognizer> model; // Use OpenCV's new FaceRecognizer in the "contrib" module; model = cv::Algorithm::create<cv::FaceRecognizer>(facerecAlgorithm); if (model.empty()) { std::cerr << "ERROR: FaceRecognizer" << std::endl; } try { //model->load("TrainedModel.xml"); } catch (const std::exception&) { } // Create a loop to caoture and find faces while (true) { // Capture a new image frame if (swCamera) { captureDevice >> captureFrame; } else { captureFrame = cv::imread("face3.PNG"); } // Shrink the captured image, Convert to gray scale and equalize cv::cvtColor(captureFrame, grayscaleFrame, CV_BGR2GRAY); cv::equalizeHist(grayscaleFrame, grayscaleFrame); shrinkFrame = ShrinkingImage(grayscaleFrame); // Find faces on the shrink image (because it's faster) and store them in the vector array face_cascade.detectMultiScale(shrinkFrame, faces, 1.1, 4, CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30)); if (faces.size() > 0) faces = EnlargeResults(captureFrame, faces); // Draw a rectangle for all found faces in the vector array on original image for (int i = 0; i < faces.size(); i++) { cv::Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height); cv::Point pt2(faces[i].x, faces[i].y); cv::Mat theFace = grayscaleFrame(faces[i]); // try to treat the face by identifying the eyes, if the eyes fail to detect, it returns theface cv::Mat filtered = TreatmentForFace(theFace); // Collecting faces and learning from them. if (starTraining && TrainName != "") { if (colFace) { Preprocessed_Faces.push_back(filtered); if (myname == "") { myname = TrainName; } colFace = false; } } else { if (!starTraining && Preprocessed_Faces.size() > 0) { // create the person folder std::string command = "mkdir "; std::string foldercom = "TrainingFolder\\\\" + myname; command += foldercom; system(command.c_str()); // create a string to access the recent created folder std::string foldername = foldercom.substr(0, foldercom.size() - (myname.size() + 1)); foldername.append("/"); foldername.append(myname); foldername.append("/"); foldername.append(myname); // save the colected faces on the folder for (int i = 0; i < Preprocessed_Faces.size(); i++) { std::ostringstream oss; oss << i; cv::imwrite(foldername + oss.str() + ".PNG", Preprocessed_Faces[i]); } myname = ""; Preprocessed_Faces.clear(); } } if (traiModel) { // read all folders on the images and for each one give an number id // read the images for each folder and add on a vector of images // read the folder name and give to all images to set the label info Preprocessed_Faces.clear(); faceLabels.clear(); Preprocessed_Faces_Names.clear(); std::string folder = "TrainingFolder\\\\"; std::vector<cv::string> foldernames; foldernames = get_all_files_names_within_folder(folder); std::vector<int> labels; for (int f = 0; f < foldernames.size(); f++) { std::string thisfoldername = folder + foldernames[f]; std::vector<cv::string> filenames; cv::glob(thisfoldername, filenames); Preprocessed_Faces_Names.push_back(foldernames[f]); labels.push_back(f + 1); for (int fn = 0; fn < filenames.size(); fn++) { Preprocessed_Faces.push_back(cv::imread(filenames[fn])); //std::cout << filenames[fn] << std::endl; faceLabels.push_back(f + 1); } } cv::imwrite("Traintest.PNG", Preprocessed_Faces[0]); std::map<int, std::string> map1; for (int i = 0; i < Preprocessed_Faces_Names.size(); i++) { map1.insert(std::pair<int, std::string>(labels[i], Preprocessed_Faces_Names[i])); std::cout << Preprocessed_Faces_Names[i] << std::endl; } model->setLabelsInfo(map1); model->train(Preprocessed_Faces, faceLabels); traiModel = false; } if (identif) { // identify the current face looking on the database // Prediction Validation // Get some required data from the FaceRecognizer model. cv::Mat eigenvectors = model->get<cv::Mat>("eigenvectors"); cv::Mat averageFaceRow = model->get<cv::Mat>("mean"); // Project the input image onto the eigenspace. cv::Mat projection = cv::subspaceProject(eigenvectors, averageFaceRow, filtered.reshape(1, 1)); // Generate the reconstructed face back from the eigenspace. cv::Mat reconstructionRow = cv::subspaceReconstruct(eigenvectors, averageFaceRow, projection); // Make it a rectangular shaped image instead of a single row. cv::Mat reconstructionMat = reconstructionRow.reshape(1, filtered.rows); // Convert the floating-point pixels to regular 8-bit uchar. cv::Mat reconstructedFace = cv::Mat(reconstructionMat.size(), CV_8U); reconstructionMat.convertTo(reconstructedFace, CV_8U, 1, 0); cv::imwrite("Teste.PNG", filtered); cv::imwrite("Teste2.PNG", reconstructedFace); int identity = model->predict(filtered); double similarity = getSimilarity(filtered, reconstructedFace); if (similarity > .7f) { //identity = -1; // -1 means that the face is not registred in the trainer } std::cout << "This is: " << identity << " and: " << model->getLabelInfo(identity) << std::endl; identif = false; } } // Print the output cv::resize(captureFrame, captureFrame, cv::Size(800, 600)); cv::imshow("outputCapture", ca
Felipe Brasil
Curtidas 1
Respostas
Felipe Brasil
03/11/2016
o final ali ficou cortado pq n coube no post, mas basicamente é só a exibição da imagem e uma pausa na captura da imagem de 33ms, nada q faça diferença!
GOSTEI 0
Marcos
03/11/2016
Olá, estou fazendo um trabalho de faculdade pra reconhecimento facial utilizando o opencv na linguagem c++ e fazendo interface com Windows forms, basicamente eu tenho o código que coleta as fotos e salva cada pessoa com suas fotos e depois recupera as imagens, isso ele não apresenta erros pq eu já testei todos esses retornos da recuperação e não esta nada errado, o problema é o seguinte, quando eu faço o programa reconhecer uma imagem mesmo sendo a mesma imagem q utilizei pra poder tratar o rosto e salvar pra identificação posterior, ele me diz q é sempre igual ao primeiro rosto que ele recuperou dos arquivos, e como eu falei, ele recupera todas as imagens dos arquivos então não tem erro na recuperação, e quando chega no momento de identificação ele recupera as informações do Modelo do reconhecimento facial e reconstrói essa imagem pra verificar semelhança com a imagem q deve ser identificada, porem ao fazer essa recuperação do próprio modelo que já recebeu treinamento corretamente antes, ele retorna uma imagem completamente preta, a questão é o seguinte eu acredito q tenha algo de errado em relação ao Modelo do reconhecimento facial, não sei se é a declaração ou oque esta acontecendo, mas algo esta dando errado nele, pq esse mesmo código funciona em um projeto de teste que fiz rodando apenas no console, sem interface do Windows forms, ele reconhece a imagem correta e reconstrói sem erros mas esse com interface apresenta esses erros que não consigo identificar!
Segue o código da função principal que é a que executa o loop pra identificação do rosto e de acordo com as entradas recebidas pelo Windows forms, o programa executa uma atividade:
Segue o código da função principal que é a que executa o loop pra identificação do rosto e de acordo com as entradas recebidas pelo Windows forms, o programa executa uma atividade:
void RecognitionAlgo::Running() { // Create the cascade classifier object used for the face detection cv::CascadeClassifier face_cascade; // Use the haarcascade frontalface_alt.xml library if (!face_cascade.load("haarcascade_frontalface_alt.xml")) { Log("Error at face Cascade Load!") } // Setup image files used in the capture process cv::Mat captureFrame; cv::Mat grayscaleFrame; cv::Mat shrinkFrame; // Create a vector to store the face found std::vector<cv::Rect> faces; std::vector<cv::Mat> Preprocessed_Faces; std::vector<cv::string> Preprocessed_Faces_Names; cv::string myname; std::vector<int> faceLabels; // Init the face Recognizer cv::initModule_contrib(); std::string facerecAlgorithm = "FaceRecognizer.Fisherfaces"; cv::Ptr<cv::FaceRecognizer> model; // Use OpenCV's new FaceRecognizer in the "contrib" module; model = cv::Algorithm::create<cv::FaceRecognizer>(facerecAlgorithm); if (model.empty()) { std::cerr << "ERROR: FaceRecognizer" << std::endl; } try { //model->load("TrainedModel.xml"); } catch (const std::exception&) { } // Create a loop to caoture and find faces while (true) { // Capture a new image frame if (swCamera) { captureDevice >> captureFrame; } else { captureFrame = cv::imread("face3.PNG"); } // Shrink the captured image, Convert to gray scale and equalize cv::cvtColor(captureFrame, grayscaleFrame, CV_BGR2GRAY); cv::equalizeHist(grayscaleFrame, grayscaleFrame); shrinkFrame = ShrinkingImage(grayscaleFrame); // Find faces on the shrink image (because it's faster) and store them in the vector array face_cascade.detectMultiScale(shrinkFrame, faces, 1.1, 4, CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30)); if (faces.size() > 0) faces = EnlargeResults(captureFrame, faces); // Draw a rectangle for all found faces in the vector array on original image for (int i = 0; i < faces.size(); i++) { cv::Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height); cv::Point pt2(faces[i].x, faces[i].y); cv::Mat theFace = grayscaleFrame(faces[i]); // try to treat the face by identifying the eyes, if the eyes fail to detect, it returns theface cv::Mat filtered = TreatmentForFace(theFace); // Collecting faces and learning from them. if (starTraining && TrainName != "") { if (colFace) { Preprocessed_Faces.push_back(filtered); if (myname == "") { myname = TrainName; } colFace = false; } } else { if (!starTraining && Preprocessed_Faces.size() > 0) { // create the person folder std::string command = "mkdir "; std::string foldercom = "TrainingFolder\\\\\\\\" + myname; command += foldercom; system(command.c_str()); // create a string to access the recent created folder std::string foldername = foldercom.substr(0, foldercom.size() - (myname.size() + 1)); foldername.append("/"); foldername.append(myname); foldername.append("/"); foldername.append(myname); // save the colected faces on the folder for (int i = 0; i < Preprocessed_Faces.size(); i++) { std::ostringstream oss; oss << i; cv::imwrite(foldername + oss.str() + ".PNG", Preprocessed_Faces[i]); } myname = ""; Preprocessed_Faces.clear(); } } if (traiModel) { // read all folders on the images and for each one give an number id // read the images for each folder and add on a vector of images // read the folder name and give to all images to set the label info Preprocessed_Faces.clear(); faceLabels.clear(); Preprocessed_Faces_Names.clear(); std::string folder = "TrainingFolder\\\\\\\\"; std::vector<cv::string> foldernames; foldernames = get_all_files_names_within_folder(folder); std::vector<int> labels; for (int f = 0; f < foldernames.size(); f++) { std::string thisfoldername = folder + foldernames[f]; std::vector<cv::string> filenames; cv::glob(thisfoldername, filenames); Preprocessed_Faces_Names.push_back(foldernames[f]); labels.push_back(f + 1); for (int fn = 0; fn < filenames.size(); fn++) { Preprocessed_Faces.push_back(cv::imread(filenames[fn])); //std::cout << filenames[fn] << std::endl; faceLabels.push_back(f + 1); } } cv::imwrite("Traintest.PNG", Preprocessed_Faces[0]); std::map<int, std::string> map1; for (int i = 0; i < Preprocessed_Faces_Names.size(); i++) { map1.insert(std::pair<int, std::string>(labels[i], Preprocessed_Faces_Names[i])); std::cout << Preprocessed_Faces_Names[i] << std::endl; } model->setLabelsInfo(map1); model->train(Preprocessed_Faces, faceLabels); traiModel = false; } if (identif) { // identify the current face looking on the database // Prediction Validation // Get some required data from the FaceRecognizer model. cv::Mat eigenvectors = model->get<cv::Mat>("eigenvectors"); cv::Mat averageFaceRow = model->get<cv::Mat>("mean"); // Project the input image onto the eigenspace. cv::Mat projection = cv::subspaceProject(eigenvectors, averageFaceRow, filtered.reshape(1, 1)); // Generate the reconstructed face back from the eigenspace. cv::Mat reconstructionRow = cv::subspaceReconstruct(eigenvectors, averageFaceRow, projection); // Make it a rectangular shaped image instead of a single row. cv::Mat reconstructionMat = reconstructionRow.reshape(1, filtered.rows); // Convert the floating-point pixels to regular 8-bit uchar. cv::Mat reconstructedFace = cv::Mat(reconstructionMat.size(), CV_8U); reconstructionMat.convertTo(reconstructedFace, CV_8U, 1, 0); cv::imwrite("Teste.PNG", filtered); cv::imwrite("Teste2.PNG", reconstructedFace); int identity = model->predict(filtered); double similarity = getSimilarity(filtered, reconstructedFace); if (similarity > .7f) { //identity = -1; // -1 means that the face is not registred in the trainer } std::cout << "This is: " << identity << " and: " << model->getLabelInfo(identity) << std::endl; identif = false; } } // Print the output cv::resize(captureFrame, captureFrame, cv::Size(800, 600)); cv::imshow("outputCapture", ca
GOSTEI 0
Marcos
03/11/2016
Olá, estou fazendo um trabalho de faculdade pra reconhecimento facial utilizando o opencv na linguagem c++ e fazendo interface com Windows forms, basicamente eu tenho o código que coleta as fotos e salva cada pessoa com suas fotos e depois recupera as imagens, isso ele não apresenta erros pq eu já testei todos esses retornos da recuperação e não esta nada errado, o problema é o seguinte, quando eu faço o programa reconhecer uma imagem mesmo sendo a mesma imagem q utilizei pra poder tratar o rosto e salvar pra identificação posterior, ele me diz q é sempre igual ao primeiro rosto que ele recuperou dos arquivos, e como eu falei, ele recupera todas as imagens dos arquivos então não tem erro na recuperação, e quando chega no momento de identificação ele recupera as informações do Modelo do reconhecimento facial e reconstrói essa imagem pra verificar semelhança com a imagem q deve ser identificada, porem ao fazer essa recuperação do próprio modelo que já recebeu treinamento corretamente antes, ele retorna uma imagem completamente preta, a questão é o seguinte eu acredito q tenha algo de errado em relação ao Modelo do reconhecimento facial, não sei se é a declaração ou oque esta acontecendo, mas algo esta dando errado nele, pq esse mesmo código funciona em um projeto de teste que fiz rodando apenas no console, sem interface do Windows forms, ele reconhece a imagem correta e reconstrói sem erros mas esse com interface apresenta esses erros que não consigo identificar!
Muito interessante seu código, provavelmente alguém vai te ajudar a soluciona-lo e quando o fizer me ensine como inserir este seu código dentro do compilado que uso BCC5.5.2 (Borland C++ com API do windows n lib Hamour Minigui Extended)
Agradeceria muito e se já resolveu entre em contato para formalizarmos a venda do mesmo.
abraços.
Muito interessante seu código, provavelmente alguém vai te ajudar a soluciona-lo e quando o fizer me ensine como inserir este seu código dentro do compilado que uso BCC5.5.2 (Borland C++ com API do windows n lib Hamour Minigui Extended)
Agradeceria muito e se já resolveu entre em contato para formalizarmos a venda do mesmo.
abraços.
GOSTEI 0