I'm pretty new to OpenCV and cascade training. I did train a cascade to recognize "running" motion. I used Haar-like and LBP. For haar-like I used 1181 positive images and 3866 negative images and 12 stages. For LBP I used 2426 positive images and 1031 negative images and 12 staged.
Following, you could see a screenshot of each one.
After a while waiting for training to be finished (around 3-4 hours for each one) I would be able to create the xml files from AdaBoost chart classifiers.
The problem is that when I use them on my code to see how they are working, they don't recognize any of obvious running motions! The code is written with C++ and OpenCV 3.3.
Does anyone have any idea why my cascade xml files after training do not working properly?
C++ code is as below:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
//open from file
VideoCapture video("../data/videos/people_activity/run/run2.mp4");
Mat img;
Mat frmg;
// Load cascate classifier placed in sulution folder
CascadeClassifier bodydetector, rundetector;
string bodycascadeName = "haarcascade_fullbody.xml";
string runcascadeName = "lbpcascade_run.xml";
bool bodyloaded = bodydetector.load(bodycascadeName);
bool runloaded = rundetector.load(runcascadeName);
// Parameters of detectMultiscale Cascade Classifier
int groundThreshold = 1;
double scaleStep = 1.1;
Size minimalObjectSize(40, 40);
Size maximalObjectSize(200, 200);
// Vector of returned bodies and run
std::vector<Rect> bodyfound, runmotion;
while (video.read(img))
{
// Image from video read and store to Mat
video >> img;
if (img.rows == 0)//end of video
break;
// Convert input to greyscale
Mat image_grey;
cvtColor(img, image_grey, CV_BGR2GRAY);
bodyfound.clear();
// Detect bodies
bodydetector.detectMultiScale(image_grey, bodyfound, scaleStep, groundThreshold, 0 | 2, minimalObjectSize, maximalObjectSize);
for (size_t k = 0; k < bodyfound.size(); k++)
{
//draw a rectangle with red color around it
rectangle(img, bodyfound[k].br(), bodyfound[k].tl(), Scalar(0, 0, 0), 1, 8, 0);
Mat bodyROI = img(bodyfound[k]);
//Detect running for bodies if there is any!
rundetector.detectMultiScale(bodyROI, runmotion, scaleStep, groundThreshold, 0 | 2, minimalObjectSize, maximalObjectSize);
//if any were found!
if (runmotion.size() > 0) {
for (size_t i = 0; i < runmotion.size(); i++)
{
//draw a rectangle with red color around it
rectangle(img, runmotion[i].br(), runmotion[i].tl(), Scalar(80, 0, 255), 1, 8, 0);
}
}
}
imshow("result", img);
int c = waitKey(10);
if ((char)c == 27) { break; } // escape
}
return 0;
}
Related
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.
I am currently trying to write a face detection program and i seem to have a slight problem with it even though it is able to build successfully. Any ideas on how to solve this? Below indicates the error that appears when i debug and my code.
detect.cpp:
#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;
// obtain input image from source
cap.retrieve(img, CV_CAP_OPENNI_BGR_IMAGE);
// 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;
}
error message:
Unhandled exception at 0x000007FEFD5CA06D in opencvTry.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000029EE10. occurred
After i looked at my codes one by one, i realized that it was just the back slash that causes the error. The code i used in the above was this :
face_cascade.load("C:\OpenCV\sources\data\haarcascades\haarcascade_frontalface_alt2.xml");
But in actual fact, it should have been this:
face_cascade.load("C:/OpenCV/sources/data/haarcascades/haarcascade_frontalface_alt2.xml");
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.
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
I've been trying to set up a program that uses HSV to detect a specific colour and place a rectangle around the biggest area found of said colour. I am having problems when i get to the vectors and the "findContours" function, which stops the program with an error stating "xxx.exe has triggered a break point".
This only happens when I insert the line
findContours(dilatedBlue,contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
I'm a rookie when it comes to OpenCV and C++ but I'm hoping someone will be able to help. I'm using windows 7 x64, Visual Studio 2012 and OpenCV 2.4.8.
My full code is what follows:
#include "stdafx.h"
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
// Declare Local Variables
int Quit = 0;
Mat imageDiff;
Mat HSVMatrix[3];
Mat erodedBlue;
Mat dilatedBlue;
//Start of search/shoot routine
while( Quit != 'q' ) // For as long as User wishes to continue...
{
Mat image;
cap >> image; // get a new frame from camera
imshow("Original", image);
//GaussianBlur(image, image, Size(3,3), 1.5, 1.5); // Setting up a Gaussian blur using 5x5 grid
cvtColor(image, imageDiff, CV_BGR2HSV);
split(imageDiff,HSVMatrix);
//Setting up saturation values for colour blue
threshold(HSVMatrix[0],HSVMatrix[0],130,255,THRESH_TOZERO_INV); // High value of colour - Dynamic changing of variable to select mode 130
threshold(HSVMatrix[0],HSVMatrix[0],75,255,THRESH_BINARY); // Low value of colour 75
threshold(HSVMatrix[1],HSVMatrix[1],255,255,THRESH_TOZERO_INV); // High saturation value - Modify for varying levels of light
threshold(HSVMatrix[1],HSVMatrix[1],100,255,THRESH_BINARY); // Low saturation value
HSVMatrix[2]=HSVMatrix[1]&HSVMatrix[0];
imshow("HSVblue", HSVMatrix[2]); // Displays binarised image
erode(HSVMatrix[2], HSVMatrix[2], Mat(), Point(-1, -1), 2, 1, 1);
erode(HSVMatrix[2], erodedBlue, Mat(), Point(-1, -1), 2, 1, 1);
imshow("Eroded-Blue", erodedBlue);
dilate(erodedBlue, dilatedBlue, Mat(), Point(-1, -1), 2, 1, 1);
imshow("Dilated-Blue", dilatedBlue);
vector<vector<Point> > contours; // Temporary variables used to hold contour information
vector<Point> approx;
vector<Vec4i> hierarchy;
vector<Rect> boundRect(contours.size());
findContours(dilatedBlue,contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true) * 0.02, true); // Calculation of contours and their approximate size and sides
}
for (int i = 0; i < contours.size(); i++)
{
if ((approx.size() == 4) && (fabs(contourArea(Mat(approx))) > 100)) // The properties that have to be fulfilled in order for the object to be recognized by the computer
{
Rect outline; // If the properties have been fulfilled and the object has been recognized, display an outline around the object
outline = boundingRect(approx);
rectangle(image,Rect(outline),Scalar(0, 255, 255),5,8,0); // The properties of the outline: the colour[bgr] and thickness
}
}
imshow("Target", image);
}
Quit = cvWaitKey(1); // The program waits for the key "q" to be pressed to exit
}
cap.release();
return 0;
}