How we can detect faces more accurately - c++

I am doing face detection from video. So I wrote one small code to detect the face.
#include<opencv2/objdetect/objdetect.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include<cv.h>
using namespace std;
using namespace cv;
CvCapture *capture=cvCaptureFromFile("foot.mp4");
double min_face_size=30;
double max_face_size=400;
Mat detectFace(Mat src);
int main( )
{
namedWindow( "window1", 1 );
while(1)
{
Mat frame,frame1;
frame1=cvQueryFrame(capture);;
frame=detectFace(frame1);
imshow( "window1", frame );
if(waitKey(1) == 'c') break;
}
waitKey(0);
return 0;
}
Mat detectFace(Mat image)
{
CascadeClassifier face_cascade( "haarcascade_frontalface_alt2.xml" );
CvPoint ul,lr;
std::vector<Rect> faces;
face_cascade.detectMultiScale( image, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(min_face_size, min_face_size),Size(max_face_size, max_face_size) );
for( int i = 0; i < faces.size(); i++ )
{
min_face_size = faces[i].width*0.8;
max_face_size = faces[i].width*1.2;
ul.x=faces[i].x;
ul.y=faces[i].y;
lr.x=faces[i].x + faces[i].width;
lr.y=faces[i].y + faces[i].height;
rectangle(image,ul,lr,CV_RGB(1,255,0),3,8,0);
}
return image;
}
I took one video for face detection which contains both small and large faces. My problem is using my code, it detects only small faces and also it shows some unwanted detection.
I need to detect both small and large faces in a video. How shall I do this?
Is there any problem with the scaling factor?
Please help me understand this problem.

Try to increase 'double max_face_size', which controls how large faces you want to detect.
You can also increase '2' in the parameters of 'detectMultiScale()', which controls the quality of the faces.

Related

Counting coins using OpenCV

I have been trying to develop a program - written with C++ and using OpenCV -which counts the overall value of coins shown in some image.
I should note that I am new to the opencv platform.
In order to achieve this goal, as far as I understand - there has to be a use of the Hough transform to detect the ratio of the coins. I found this code example on the OpenCV site, but I can't put a value for the coins.
Here is what I have done so far.
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
namespace
{
const std::string windowName = "Coins detection";
const std::string cannyThresholdTrackbarName = "Canny threshold";
const std::string accumulatorThresholdTrackbarName = "Accumulator Threshold";
const int cannyThresholdInitialValue = 41;
const int accumulatorThresholdInitialValue = 87;
const int maxAccumulatorThreshold = 200;
const int maxCannyThreshold = 255;
void HoughDetection(const Mat& src_gray, const Mat& src_display, int cannyThreshold, int accumulatorThreshold)
{
std::vector<Vec3f> circles;
HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, src_gray.rows/8, cannyThreshold, accumulatorThreshold, 0, 0 );
Mat display = src_display.clone();
for( size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle( display, center, 3, Scalar(0,255,0), -1, 8, 0 );
circle( display, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
imshow( windowName, display);
}
}
int main(int argc, char** argv)
{
Mat src, src_gray;
String imageName("c:\\moedas.jpg");
if (argc > 1)
{
imageName = argv[1];
}
src = imread( imageName, IMREAD_COLOR );
if( src.empty() )
{
std::cerr<<"Invalid input image\n";
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
int cannyThreshold = cannyThresholdInitialValue;
int accumulatorThreshold = accumulatorThresholdInitialValue;
namedWindow( windowName, WINDOW_AUTOSIZE );
createTrackbar(cannyThresholdTrackbarName, windowName, &cannyThreshold,maxCannyThreshold);
createTrackbar(accumulatorThresholdTrackbarName, windowName, &accumulatorThreshold, maxAccumulatorThreshold);
char key = 0;
while(key != 'q' && key != 'Q')
{
cannyThreshold = std::max(cannyThreshold, 1);
accumulatorThreshold = std::max(accumulatorThreshold, 1);
HoughDetection(src_gray, src, cannyThreshold, accumulatorThreshold);
key = (char)waitKey(10);
}
return 0;
}
The code you have so far only segments circle shapes in an input image. This is just the first step to count the coins. There are many ways to perform that task, ranging from simple contour counting techniques to complicated deep learning, and the explanation of such techniques is too broad and large in scope to put efficiently and concisely in an SO answer. However, here are some coin detectors/counter implementations/tutorials that you can check:
Implementation 1 in Python. This is the best of the list, although the code file is larger than yours, not too hard to port to C++. It has the best detection/counting performance but deals with Neural Networks, specifically, a Multilayer Perceptron.
Implementation 2 in Python. This is a very small code file, nearly as large as yours and has no idiomatic Python code, porting it to C++ is a no brainer, you should start here. This implementation uses mere contour counting with the aid of the Canny edge detector.
Tutorial 1 in C++. A simple tutorial in C++, but only serves introductory purposes, the implementations listed above are the real thing.

How do I store the captured image in OpenCV (saving the picture to computer)

I am still quite new to OpenCV and c++ programming in general. I am doing on a project that stores image from my webcam. I was able to display camera image and detect faces somehow but I don't know how to save the images.
What should i do in order for the faces that my webcam detects gets captured and store into my computer?
Using my code below, how can i edit it to:
capture an image from the live cam 5 seconds after detecting face
save the images to a folder in jpg format
Thanks so much for any help you can provide!
my code:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// capture from web camera init
VideoCapture cap(0);
cap.open(0);
Mat img;
// Initialize the inbuilt Harr Cascade frontal face detection
// Below mention the path of where your haarcascade_frontalface_alt2.xml file is located
CascadeClassifier face_cascade;
face_cascade.load("C:/OpenCV/sources/data/haarcascades/haarcascade_frontalface_alt2.xml");
// i tried changing this line to match my folder in C Drive
for (;;)
{
// Image from camera to Mat
cap >> img;
// Just resize input image if you want
resize(img, img, Size(1000, 640));
// Container of faces
vector<Rect> faces;
// Detect faces
face_cascade.detectMultiScale(img, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(140, 140));
// error message appears here
//Show the results
// Draw circles on the detected faces
for (int i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5);
ellipse(img, center, Size(faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0);
}
// To draw rectangles around detected faces
/* for (unsigned i = 0; i<faces.size(); i++)
rectangle(img,faces[i], Scalar(255, 0, 0), 2, 1);*/
imshow("wooohooo", img);
int key2 = waitKey(20);
}
return 0;
}
Answering this so we can close this question
The function to use to save an image in C++ opencv is cv::imwrite('image_name.jpg', img).
Add this before or after you cv::imshow() if you want to save the image after every detection.

findChessboardCorners gives unexpected results

Here is my code
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include<opencv2/opencv.hpp>
#include<iostream>
//#include<vector>
using namespace cv;
using namespace std;
int main()
{
VideoCapture cap = VideoCapture(0);
int successes = 0;
int numBoards = 0;
int numCornersHor = 6;
int numCornersVer = 4;
int numSquares = (numCornersHor - 1) * (numCornersVer - 1);
Size board_sz = Size(numCornersHor, numCornersVer);
vector<Point2f> corners;
for (;;)
{
Mat img;
cap >> img;
Mat gray;
cvtColor(img, gray, CV_RGB2GRAY);
if (img.empty()) break; // end of video stream
imshow("this is you, smile! :)", gray);
if (waitKey(1) == 27) break; // stop capturing by pressing ESC
bool found = findChessboardCorners(gray, board_sz, corners, CALIB_CB_ADAPTIVE_THRESH);
if (found == 1)
{
cout << corners.size()<<"\n";
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
drawChessboardCorners(gray, board_sz, corners, found);
}
}
cap.release();
waitKey();
return 0;
}
The code is capturing frames from a webcam. If a chessboard is detected, the total number of found corners is printed out (I did it because I was not getting the same output as in the tutorial code and I wanted to find where the bug is).
The output:
First you should follow some ground rules:
Do not use loose papers -> print/glue the chessboard on a flat plate
Print it with a big white border to improve detection
The chessboard has to be completly inside the image (not as in your example)
Take several images with different positions of your chessboard
Second, you cant draw your contours into a 8-bit grayscale image, use an 8-bit color image instead.
And if i count correctly (count inner corners) your chessboard has the size (8,6).
I have the same problem, the number of corners is HUGE. After some search i found this solution Here.
For some reason findChessboardCorners function resizes the corners vector. I tried the solution above, it worked well with the output corners, but i still have assertion failed problem with cornerSubPix function.

adding two images using opencv

I need to extract L(illuminative component)from RGB frame and obtain the inverted illuminative image (L).
adding the inverted image to the original L image.
My question is how can i add two images (L channel of lab and inverted image)?
Which function can do that?
i think http://answers.opencv.org/question/81947 is your question. so i tried to revise it as far as i understand your question. hope it will help.
source :
result :
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
void split_lab( Mat planes )
{
Mat lab, blurredL;
cvtColor( planes, lab, CV_BGR2Lab );
vector <Mat> splits;
split(lab, splits);
medianBlur( splits[0], blurredL, 31);
blurredL = 255 - blurredL;
cvtColor( blurredL, blurredL, CV_GRAY2BGR );
planes = planes + ( blurredL * 0.5 );
}
int main(int argc, char** argv)
{
Mat src= imread( argv[1] );
split_lab(src);
imshow( "result", src );
waitKey();
return 0;
}

Face tracking issue in Opencv

I'm new to opencv and I was working with colors , thresholds at the beginning and stepped forward to face tracking. Here is the code I have written to implement the face tracking rectangle with the input of my web cam. The problem is the size of the vector filled by the "face_cascade.detectMultiScale" goes to a huge number, resulting an Unhandled exception.
I have included all the libraries and cascade xml files and I don't see any fault I have done. For easy debugging I added a cout after the multiscale method call.
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
//creating the classifier object used for the face detection
CascadeClassifier face_cascade;
//use the haarcascade_frontface_alt.xml library
face_cascade.load("haarcascade_frontalcatface.xml");
//setup camera
VideoCapture captureDevice;
captureDevice.open(0);
//setup image files used in the capture process
Mat capFrame;
Mat grayscaleFrame;
//create a window to present the results
namedWindow("output", 1);
//create a loop to capture and find the faces
while (true)
{
//capture a new image frame
captureDevice >> capFrame;
//convert captured Image to grayscale and equalize
cvtColor(capFrame, grayscaleFrame, CV_BGR2GRAY);
equalizeHist(grayscaleFrame, grayscaleFrame);
//create a vector array to store the faces found
std::vector<Rect> faces;
//find faces and store them in the vector array
face_cascade.detectMultiScale(grayscaleFrame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30));
cout << faces.size();
//draw a rectangle on the face
for (int i = 0; i < faces.size(); i++)
{
Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
Point pt2(faces[i].x, faces[i].y);
rectangle(capFrame, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
}
//print the output
imshow("output", capFrame);
//pause for 33 ms
waitKey(33);
}
return 0;
}
So the output on the console (by the cout) is :
4292486918
I have followed many tutorials on face tracking and everything is similar to this. This is the simplest and even that doesn't work.
p.s : don't worry about the xml file. I have tried with all the xml files and It can't be an issue.
Thank you in advance