I have a code that detects faces and saves multiple cropped area images of them to a file path. My code doesn't stop saving images of detected faces until I physically close the program. For every one second a face is detected on a webcam, my code saves 6 images of the face.
Is it possible to have it save just one image per face detected? For example, if there is one face, only one image, if two faces, an image of both faces are saved etc. My code is below. Can anyone help me?
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
string face_cascade_name = "C:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml";
CascadeClassifier face_cascade;
string window_name = "Window";
int filenumber;
string filename;
int main(void)
{
VideoCapture capture(0);
if (!capture.isOpened())
return -1;
if (!face_cascade.load(face_cascade_name))
{
cout << "error" << endl;
return (-1);
};
Mat frame;
for (;;)
{
capture >> frame;
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
cout << "error2" << endl;
break;
}
int c = waitKey(10);
if (27 == char(c))
{
break;
}
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
cv::Rect roi_b;
cv::Rect roi_c;
size_t ic = 0;
int ac = 0;
size_t ib = 0;
int ab = 0;
for (ic = 0; ic < faces.size(); ic++)
{
roi_c.x = faces[ic].x;
roi_c.y = faces[ic].y;
roi_c.width = (faces[ic].width);
roi_c.height = (faces[ic].height);
ac = roi_c.width * roi_c.height;
roi_b.x = faces[ib].x;
roi_b.y = faces[ib].y;
roi_b.width = (faces[ib].width);
roi_b.height = (faces[ib].height);
crop = frame(roi_b);
resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR);
cvtColor(crop, gray, CV_BGR2GRAY);
filename = "C:\\Users\\Desktop\\Faces\\face";
stringstream ssfn;
ssfn << filename.c_str() << filenumber << ".jpg";
filename = ssfn.str();
cv::imwrite(filename, res);
filenumber++;
Point pt1(faces[ic].x, faces[ic].y);
Point pt2((faces[ic].x + faces[ic].height), (faces[ic].y + faces[ic].width));
rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
}
sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
text = sstm.str();
if (!crop.empty())
{
imshow("detected", crop);
}
else
destroyWindow("detected");
}
Related
I am new to Realsense & C++. I know this question might be easy on.
However, I cannot solve this even I searched half of day.
I am trying to use Realsense with OpenCV face detection(Haarcascade).
But when I use 'face_cascade,detectMultiScale', the project gets access violation error.
(just like the picture underneath)
and my codes are this :
// License: Apache 2.0.See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
#include <rs.hpp> // Include RealSense Cross Platform API
#include <opencv2/opencv.hpp> // Include OpenCV API
#include "opencv2/objdetect.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace std;
using namespace cv;
//String face_cascade_name;
CascadeClassifier face_cascade;
string window_name = "Face detection";
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
if (frame.empty()) {
printf("error, no data");
}
else {
printf("no problem");
}
//face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
face_cascade.detectMultiScale(frame_gray, faces , 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(500, 500));
for (size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2),
0, 0, 360, Scalar(0, 0, 255), 4, 8, 0);
}
imshow(window_name, frame);
}
int main(int argc, char * argv[]) try
{
// Declare depth colorizer for pretty visualization of depth data
rs2::colorizer color_map;
// Declare RealSense pipeline, encapsulating the actual device and sensors
rs2::pipeline pipe;
face_cascade.load("C:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
//if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading face cascade\n"); };
// Start streaming with default recommended configuration
pipe.start();
const auto window_name = "Display Image";
namedWindow(window_name, WINDOW_AUTOSIZE);
while (waitKey(1) < 0 && cvGetWindowHandle(window_name))
{
rs2::frameset data = pipe.wait_for_frames(); // Wait for next set of frames from the camera
//rs2::frame depth = color_map(data.get_depth_frame());
rs2::frame color = data.get_color_frame();
// Query frame size (width and height)
//const int w = depth.as<rs2::video_frame>().get_width();
//const int h = depth.as<rs2::video_frame>().get_height();
const int color_w = color.as<rs2::video_frame>().get_width();
const int color_h = color.as<rs2::video_frame>().get_height();
// Create OpenCV matrix of size (w,h) from the colorized depth data
//Mat image(Size(w, h), CV_8UC3, (void*)depth.get_data(), Mat::AUTO_STEP);
Mat image(Size(color_w, color_h), CV_8UC3, (void*)color.get_data(), Mat::AUTO_STEP);
// Update the window with new data
//imshow(window_name, image);
detectAndDisplay(image);
}
return EXIT_SUCCESS;
}
catch (const rs2::error & e)
{
std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
return EXIT_FAILURE;
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
enter code here
I'm trying to use solvePnP in a C++ program that detects a chessboard in a video stream. Every time the calibration finishes, I try to run solvePnP, but I keep getting errors that I think are related to the translation and rotation vectors.
This is the error:
The error
This is my code:
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
//Global variables
vector<vector<Point2f> > corner_list;
vector<vector<Point3f> > point_list;
vector<Mat> rotation_vecs, translation_vecs;
int i = 0;
bool calibMode = true, drawMode = false, drawMode2 = false, camMatrixInit = false, calibrated = false;
Mat originalCameraMatrix, cameraMatrix, distCoefficients, frame, gray, rvec, tvec;
//Function declarations
vector<Point3f> genWorldPoints(int cols, int rows);
void printCameraMatrix();
void printDistCoeff();
void printRotVecs();
/*Generates the world points (0, 0, 0), (1, 0, 0), etc. for the camera calibration.*/
vector<Point3f> genWorldPoints(int cols, int rows){
vector<Point3f> ret;
for (int i=0; i<rows; i++) {
for (int j=0; j<cols; j++) {
int tempi = i*(-1);
ret.push_back(Point3f((float)j, (float)tempi, 0.0));
}
}
return ret;
}
/*Print the camera matrix*/
void printCameraMatrix(){
cout << "Original Camera Matrix" << endl << originalCameraMatrix << endl;
cout << "Current Camera Matrix" << endl << cameraMatrix << endl;
}
/*Prints the distortion coefficients*/
void printDistCoeff(){
cout << "Distortion Coefficients:"<< endl << distCoefficients << endl;
}
int main(int argc, char *argv[]){
VideoCapture *capdev;
cameraMatrix = Mat::eye(3, 3, CV_64F);
distCoefficients = Mat::zeros(8, 1, CV_64F);
// open the video device
capdev = new VideoCapture(0);
if (!capdev->isOpened()) {
printf("Unable to open video device\n");
return(-1);
}
namedWindow("Video", 1);
bool found;
*capdev >> frame;
rvec = Mat::zeros(3, 1, CV_64F);
tvec = Mat::zeros(3, 1, CV_64F);
//Initialize camera matrix
cameraMatrix.at<double>(0,2) = (frame.size().width)/2;
cameraMatrix.at<double>(1,2) = (frame.size().height)/2;
cameraMatrix.copyTo(originalCameraMatrix);
printCameraMatrix();
for(;;){
*capdev >> frame;
if (!found) {
imshow("Video", frame);
}
Size patternsize(9,6);
vector<Point2f> corner_set;
vector<Point3f> point_set;
int code = waitKey(10);
cvtColor(frame, gray, CV_BGR2GRAY);
found = findChessboardCorners(gray, patternsize, corner_set, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
//Code to add a calibration frame
if (found && calibMode) {
cornerSubPix(gray, corner_set, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
drawChessboardCorners(frame, patternsize, Mat(corner_set), found);
//s key press
if (code == 115){
printf("Adding calibration frame\n");
printf("Number of corners found: %lu\n", corner_set.size());
printf("Point 0 x: %f\ty: %f\n", corner_set[0].x, corner_set[1].y);
//Add the corner set
corner_list.push_back(corner_set);
//Generate point set
vector<Point3f> point_set = genWorldPoints(9,6);
//Add point set to point set list
point_list.push_back(point_set);
//Save the image
string filename = "../data/images/p4_calib_image_"+to_string(i)+".jpeg";
imwrite(filename, frame);
//if there are more than 5 saved calibration images, run calibration procedure
if (i>4) {
//Calculate the reprojection error by running calibrateCamera
double rpe = calibrateCamera(point_list, corner_list, frame.size(), cameraMatrix,
distCoefficients, rotation_vecs, translation_vecs,
CV_CALIB_FIX_ASPECT_RATIO | CV_CALIB_FIX_K4);
//Print the camera matrix
printCameraMatrix();
printDistCoeff();
//Print the reprojection error
cout << "Reprojection error: " << rpe << endl;
calibrated = true;
}
//Increment i
i++;
}
imshow("Video", frame);
}
else if (found && drawMode){
cout << "Draw mode" << endl;
bool solved = solvePnP(point_list, corner_list, cameraMatrix, distCoefficients,
rvec, tvec);
//rotation_vecs.front(), translation_vecs.front());
}
else if (found && drawMode2){
cout << "Draw mode 2" << endl;
bool solved = solvePnP(point_list, corner_list, cameraMatrix, distCoefficients,
rvec, tvec);
//rotation_vecs.front(), translation_vecs.front());
}
//Switching between drawing modes
if (calibrated && code == 49) {
calibMode = false;
drawMode2 = false;
drawMode = true;
}
else if (calibrated && code == 50){
calibMode = false;
drawMode = false;
drawMode2 = true;
}
//Switch back to calibration mode
else if (calibrated && code == 51){
drawMode = false;
drawMode2 = false;
calibMode = true;
}
if (code == 27) {
printf("Terminating\n");
delete capdev;
return(0);
}
}
capdev = new VideoCapture(0);
printf("Terminating\n");
delete capdev;
return(0);
}
Please excuse the indentation...
The problem is that sovlePnP requires vector<Point2/3f> as input, instead of vector<vector<Point2/3f> >. In your code, "point_list" is vector<vector<Point3f> >, and "corner_list" is vector<vector<Point2f> >.
The documentation of solvePnP can be found here: http://docs.opencv.org/3.0-beta/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
I have a problem with video speed, when I just run a video file in opencv it plays in normal speed.
The problem starts when I apply face and eye detection to the video it plays very slowly. I have tried to change waitKey() values , but the problem still exists.
Why is this happening?
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
// Function Headers
void detectAndDisplay(Mat frame);
// Global variables
// Copy this file from opencv/data/haarscascades to target folder
string face_cascade_name = "haarcascade_frontalface_alt.xml";
string eye_cascade_name = "haarcascade_mcs_eyepair_big.xml";
CascadeClassifier face_cascade;
CascadeClassifier eye_cascade;
string window_name = "Capture - Face detection";
int filenumber; // Number of file to be saved
string filename;
int main(void)
{
VideoCapture capture("m.mp4");
if (!capture.isOpened()) // check if we succeeded
return -1;
// Load the cascade
if (!face_cascade.load(face_cascade_name))
{
printf("--(!)Error loading\n");
return (-1);
}
if (!eye_cascade.load(eye_cascade_name))
{
printf("--(!)Error loading\n eye ");
return (-1);
}
// Read the video stream
Mat frame;
for (;;)
{
capture >> frame;
// Apply the classifier to the frame
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
printf(" --(!) No captured frame -- Break!");
break;
}
waitKey(40);
return 0;
}
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
std::vector<Rect> eyes;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 4, CASCADE_SCALE_IMAGE, Size(20, 20));
// Set Region of Interest
size_t i = 0; // ic is index of current element
for (i = 0; i < faces.size(); i++) // Iterate through all current elements (detected faces)
{
Point pt1(faces[i].x, faces[i].y); // Display detected faces on main window - live stream from camera
Point pt2((faces[i].x + faces[i].height), (faces[i].y + faces[i].width));
rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
// set ROI for the eyes
Rect Roi = faces[i];
Roi.height = Roi.height / 4;
Roi.y = Roi.y + Roi.height;
cv::Mat crop = frame(Roi);
cvtColor(crop, gray, CV_BGR2GRAY);
imshow("ROI", gray);
eye_cascade.detectMultiScale(gray, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(20, 20));
for (size_t j = 0; j < eyes.size(); j++)
{
Rect r(Roi.x + eyes[j].x, Roi.y + eyes[j].y, eyes[j].width, eyes[j].height);
rectangle(frame, r, Scalar(255, 0, 0), 3, 1, 0);
// convert roi to ychannel
Mat eye_region = frame(eyes[j]).clone();
Mat eye_region_YCbCr;
cvtColor(eye_region, eye_region_YCbCr, CV_BGR2YCrCb);
vector<Mat> channels;
split(eye_region_YCbCr, channels);
Mat eye_region_Ychannel = channels[0].clone();
imshow("Y", eye_region_Ychannel);
// end of convert
}
}
// Show image
imshow("original", frame);
if (!crop.empty())
{
imshow("detected", crop);
}
else
{
destroyWindow("detected");
}
}
I want to do eigen face by opencv ,and this is my code.
#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 = ';') {
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[]) {
string fn_haar = string("C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt_tree.xml");
string fn_csv = string("C:/Users/faho0odywbas/Desktop/csv.ext");
int deviceId = atoi("0");
vector<Mat> images;
vector<int> labels;
try {
read_csv(fn_csv, images, labels);
} catch (cv::Exception& e) {
cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
exit(1);
}
int im_width = images[0].cols;
int im_height = images[0].rows;
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(23,2500.0);
CascadeClassifier haar_cascade;
haar_cascade.load(fn_haar);
VideoCapture cap(deviceId);
namedWindow("face_recognizer", CV_WINDOW_AUTOSIZE);
if(!cap.isOpened()) {
cerr << "Capture Device ID " << deviceId << "cannot be opened." << endl;
return -1;
}
vector< Rect_<int> > faces;
Mat frame;
waitKey(1500);
for(;;) {
cap >> frame;
Mat original = frame.clone();
Mat gray;
cvtColor(original, gray, CV_BGR2GRAY);
haar_cascade.detectMultiScale(gray, faces);
for(int i = 0; i < faces.size(); i++) {
Rect face_i = faces[i];
Mat face = gray(face_i);
Mat face_resized;
cv::resize(face, face_resized, Size(im_width, im_height), 1.0, 1.0, INTER_CUBIC);
int prediction = model->predict(face_resized);
rectangle(original, face_i, CV_RGB(255, 0,0), 1);
string box_text = format("Sujeto = %d", prediction);
int pos_x = std::max(face_i.tl().x - 10, 0);
int pos_y = std::max(face_i.tl().y - 10, 0);
putText(original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
}
imshow("face_recognizer", original);
char key = (char) waitKey(1);
if(key == 27){
destroyAllWindows();
break;
}
}
return 0;
}
I'm sure it's right because it was work with my friend's computer, so I think the problem with my visual studio or the windows.
The error that comes to me is
" First-chance exception at 0x74C44598 in Project3.exe: Microsoft C++ exception: cv::Exception at memory location 0x00D7ED2C.
If there is a handler for this exception, the program may be safely continued. "
and when I click break, it shows also to me this error
wkernelbase.pdb not loaded
so, what I have to do ?
I have done this Tools->Options->Debugging->Symbols->Select “Microsoft Symbol Servers”.
but also same error
I have another question which is if I want hit "s" to start recording face for every frame, and hit "d" to end the recording, how can I do that ?
Thanks a lot
I am trying out face detection using OpenCV and am pretty new to OpenCV.
Here's my code:
#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[]) {
string fn_haar = "haarcascade_frontalface_alt2.xml";
string fn_csv = "reader.txt";
int deviceId = 0;
// These vectors hold the images and corresponding labels:
vector<Mat> images;
vector<int> labels;
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);
}
int im_width = images[0].cols;
int im_height = images[0].rows;
Ptr<FaceRecognizer> model = createFisherFaceRecognizer();
model->train(images, labels);
CascadeClassifier haar_cascade;
haar_cascade.load(fn_haar);
VideoCapture cap(deviceId);
if (!cap.isOpened()) {
cerr << "Capture Device ID " << deviceId << "cannot be opened." << endl;
return -1;
}
Mat frame;
while (true) {
cap >> frame;
Mat original = frame.clone();
Mat gray;
cvtColor(original, gray, CV_BGR2GRAY);
vector< Rect_<int> > faces;
haar_cascade.detectMultiScale(gray, faces);
for (int i = 0; i < faces.size(); i++) {
Rect face_i = faces[i];
Mat face = gray(face_i);
Mat face_resized;
cv::resize(face, face_resized, Size(im_width, im_height), 1.0, 1.0, INTER_CUBIC);
int prediction = model->predict(face_resized);
rectangle(original, face_i, CV_RGB(0, 255, 0), 1);
string box_text = format("Prediction = %d", prediction);
int pos_x = std::max(face_i.tl().x - 10, 0);
int pos_y = std::max(face_i.tl().y - 10, 0);
putText(original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0, 255, 0), 2.0);
}
namedWindow("face_recognizer", 1);
imshow("face_recognizer", original);
char key = (char)waitKey(20);
if (key == 27)
break;
}
return 0;
}
And here's my reader.txt file
C:\Users\Hitanshu Dhawan\Documents\Visual Studio 2013\Projects\ConsoleApplication21\ConsoleApplication21\obama\obama1.jpg;0
C:\Users\Hitanshu Dhawan\Documents\Visual Studio 2013\Projects\ConsoleApplication21\ConsoleApplication21\obama\obama2.jpg;0
Now, the problem is my code is not working and it shows some error "Exception at memory location" and "Integer division by zero" and "opencv_core2410d.pdb not loaded"...
I've tried many ways such as adding different lib in Linker > Input.
Also I've checked the Microsoft Symbol Servers.
Also my .xml and .csv files are properly copied into the application folder!
Here are some screenshots: