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

C++

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:

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

Felipe Brasil

Curtidas 1

Respostas

Felipe Brasil

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

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:

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

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.
GOSTEI 0
POSTAR