OpenCV How to get width and height of face from image - opencv

Hi I have a large set of images of faces extracted from videos. I would like to simply measure the width and the height of each face found in the images. When I use the HAAR classifiers it returns square faces detected no matter how fat or thin the face was.
There are some improvements that would be ideal, although I'm happy with just the first step.
As a minimum I'm looking for examples to measure the width and height of faces detected in images.
Ideally these faces would first be rotated to facing forwards to measure the width and height of the actual person's face, rather than the pixel width of a potentially rotated face.
Example code would be much appreciated.

Here is the face-detection code. The below two lines will print the width and height of the detected face.
In the first for loop of "detectAndDisplay" add the two lines.
cout << "face width = " << faces[i].width << endl;
cout << "face Height = " << faces[i].height << endl;
Here is the modified code for you:
#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 */
String face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
/** #function main */
int main( int argc, const char** argv )
{
CvCapture* capture;
Mat frame = imread ( "C:\\Desktop\\1.jpg" );
//-- 1. Load the cascades
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
//-- 3. Apply the classifier to the frame
if( !frame.empty() )
{ detectAndDisplay( frame ); }
else
{ printf(" --(!) No captured frame -- Break!"); }
return 0;
}
/** #function detectAndDisplay */
void detectAndDisplay( Mat frame )
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( int i = 0; i < faces.size(); i++ )
{
cv :: rectangle ( frame, faces[i], Scalar( 255, 0, 255 ), 4 );
cout << "face width = " << faces[i].width << endl;
cout << "face Height = " << faces[i].height << endl;
}
//-- Show what you got
imshow( window_name, frame );
waitKey( 0 );
}

Related

opencv-face detection-save the video

I have code for detection of a face.. How do I save the video which is being captured? I'm posting the code for face detection below..
where do I insert the code which saves the the video?
thhis code works in detecting a face with ubuntu and opencv. Please do help!
#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;
VideoCapture cap;
cv::VideoWriter output_cap("/home/unifyadmin/Documents/MyVideo.avi",
input_cap.get(CV_CAP_PROP_FOURCC),
input_cap.get(CV_CAP_PROP_FPS),
cv::Size(input_cap.get(CV_CAP_PROP_FRAME_WIDTH),
input_cap.get(CV_CAP_PROP_FRAME_HEIGHT)));
if (!output_cap.isOpened())
{
std::cout << "!!! Output video could not be opened" << std::endl;
return;
}
// This part would be similar to your imshow part of your code
while (true)
{
if (!input_cap.read(frame))
break;
output_cap.write(frame);
}
/** Function Headers */
void detectAndDisplay( Mat frame );
/** Global variables */
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
/** #function main */
int main( int argc, const char** argv )
{
CvCapture* capture;
Mat frame;
//-- 1. Load the cascades
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
//-- 2. Read the video stream
capture = cvCaptureFromCAM( 0 );
if( capture )
{
while( true )
{
frame = cvQueryFrame( capture );
//-- 3. Apply the classifier to the frame
if( !frame.empty() )
{ detectAndDisplay( frame ); }
else
{ printf(" --(!) No captured frame -- Break!"); break; }
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
/** #function detectAndDisplay */
void detectAndDisplay( Mat frame )
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t 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( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
//-- In each face, detect eyes
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t j = 0; j < eyes.size(); j++ )
{
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
}
}
//-- Show what you got
imshow( window_name, frame );
}
There are three library methods that you require:
VideoWriter::VideoWriter(const string& filename, int fourcc, double fps, Size frameSize, bool isColor=true)
VideoWriter::open(const string& filename, int fourcc, double fps, Size frameSize, bool isColor=true)
void VideoWriter::write(const Mat& image)
Here is a short example on how to use them:
// Do this near the start of your code
cv::VideoWriter output_cap(C:/MyVideo.avi,
input_cap.get(CV_CAP_PROP_FOURCC),
input_cap.get(CV_CAP_PROP_FPS),
cv::Size(input_cap.get(CV_CAP_PROP_FRAME_WIDTH),
input_cap.get(CV_CAP_PROP_FRAME_HEIGHT)));
if (!output_cap.isOpened())
{
std::cout << "!!! Output video could not be opened" << std::endl;
return;
}
// This part would be similar to your imshow part of your code
while (true)
{
if (!input_cap.read(frame))
break;
output_cap.write(frame);
}
Edit: - My last contribution to this question:
You need your creation of objects into the main function, that includes the VideoWriter
Im not sure how any of this code even works:
VideoCapture cap;
cv::VideoWriter output_cap("/home/unifyadmin/Documents/MyVideo.avi",
input_cap.get(CV_CAP_PROP_FOURCC),
input_cap.get(CV_CAP_PROP_FPS),
cv::Size(input_cap.get(CV_CAP_PROP_FRAME_WIDTH),
input_cap.get(CV_CAP_PROP_FRAME_HEIGHT)));
if (!output_cap.isOpened())
{
std::cout << "!!! Output video could not be opened" << std::endl;
return;
}
// This part would be similar to your imshow part of your code
while (true)
{
if (!input_cap.read(frame))
break;
output_cap.write(frame);
}
You need to think about what you are actually coding and where you are writing code. Don't just take examples from the internet and try and stick them together.

How to detect specific number from image with OPENCV?

I live in Turkey, and in Turkey, TV commercials are making some countdowns which tells us how many minutes left to the tv program or film starts.
What I'am trying to do is catch the 00:59 seconds or just the 2nd "0" on the counter. The alghoritm must understand that the "0" is "0" not any other number.
After that I've tried template matching with template images but it detects wrong numbers too.
So I couldn't figured out which is the best way to do it...
I am trying to detect from these frames:
as you see it detects "1" instead of "0".
Below is my code with template matching;
#include<opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <sstream>
using namespace cv;
using namespace std;
Mat frame;
Mat img;
Mat templ;
Mat templ_resized;
Mat templ_resized_bw;
Mat result;
cv::Mat sel;
cv::Mat img_final;
//**************
int main(int argc, char** argv)
{
VideoCapture cap("/home/semih/Desktop/OPENCV_ON_LINUX/dizifiles/yenisoncalismalar/kanaldkucukaga.avi");
if ( !cap.isOpened() )
{
cout << "Cannot open the video file" << endl;
return -1;
}
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
namedWindow("1",CV_WINDOW_AUTOSIZE);
namedWindow("2",CV_WINDOW_AUTOSIZE);
namedWindow("3",CV_WINDOW_AUTOSIZE);
namedWindow("4",CV_WINDOW_AUTOSIZE);
namedWindow("5",CV_WINDOW_AUTOSIZE);
int counter=0;
int check_counter=0;
std::string s;
cv::Rect myROI(699, 474, 10,16); //location of the countdown Timer
cv::Mat cropped;
templ = imread("/home/semih/Desktop/OPENCV_ON_LINUX/dizifiles/yenisoncalismalar/sifir00.png",CV_LOAD_IMAGE_COLOR);
cv::resize(templ,templ_resized,Size(8,11),CV_INTER_LINEAR); //8 11
Mat cropped_bw;
double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
cv::Mat pic;
while(1)
{
bool bSuccess = cap.read(frame);
if (!bSuccess)
{
cout << "Cannot read the frame from video file" << endl;
break;
}
counter=counter+1;
cv::Mat croppedRef(frame, myROI);
cvtColor(croppedRef,cropped_bw,CV_RGB2GRAY);
cropped_bw = cropped_bw > 200;
cvtColor(templ_resized,templ_resized_bw,CV_RGB2GRAY);
templ_resized_bw=templ_resized_bw>200;
imshow("1",cropped_bw);
imshow("2",frame);
imshow("3",templ);
imshow("4",templ_resized_bw);
int result_cols = cropped_bw.cols - templ_resized_bw.cols + 1;
int result_rows = cropped_bw.rows - templ_resized_bw.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
matchTemplate( cropped_bw,templ_resized_bw, result, CV_TM_SQDIFF_NORMED);
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
matchLoc=minLoc;
int dogrula;
if(matchLoc.x>0){
check_counter=check_counter+1;
}
if(check_counter>20){ // if it stays 20 frames, assume "detected
cout<<"0 number detected"<<endl;
}
rectangle(cropped_bw, matchLoc, Point( matchLoc.x + templ_resized_bw.cols , matchLoc.y + templ_resized_bw.rows ), Scalar::all(100), 1, 8, 0 );
imshow("5",cropped_bw);
if(waitKey(30) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
As I am trying to search specific and same number I found this solution.
Which is comparing two images as if they are same.
#include<opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <sstream>
using namespace cv;
using namespace std;
Mat frame;
Mat img;
Mat templ;
Mat templ_resized;
Mat templ_resized_bw;
Mat result;
cv::Mat sel;
cv::Mat img_final;
//**************
int detect()
{
VideoCapture cap("/home/semih/Desktop/OPENCV_ON_LINUX/dizifiles/yenisoncalismalar/Final/kucukaga2.avi");
if ( !cap.isOpened() )
{
cout << "Cannot open the video file" << endl;
return -1;
}
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
int counter=0;
int check_counter=0;
std::string s;
cv::Rect myROI(702, 476, 11,16); // location of countdown timer
cv::Mat cropped;
templ = imread("/home/semih/Desktop/OPENCV_ON_LINUX/dizifiles/yenisoncalismalar/Final/thresh747.png",CV_LOAD_IMAGE_COLOR);
cv::resize(templ,templ_resized,Size(45,45),CV_INTER_LINEAR); //8 11
Mat cropped_bw;
double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
cv::Mat pic;
while(1)
{
bool bSuccess = cap.read(frame);
if (!bSuccess)
{
cout << "Cannot read the frame from video file" << endl;
break;
}
counter=counter+1;
cv::Mat croppedRef(frame, myROI);
cvtColor(croppedRef,cropped_bw,CV_RGB2GRAY);
cv::resize(cropped_bw,cropped_bw,Size(45,45),CV_INTER_LINEAR);
cropped_bw = cropped_bw > 200;
cvtColor(templ_resized,templ_resized_bw,CV_RGB2GRAY);
templ_resized_bw=templ_resized_bw>200;
cv::Mat result2;
Mat croppedsimilar;
Mat templ_resized_re;
Mat templ_cvt;
cvtColor(templ_resized, templ_cvt, CV_BGR2GRAY);
cv::resize(templ_cvt,templ_resized_re,Size(45,45),CV_INTER_LINEAR);
cv::resize(cropped_bw,croppedsimilar,Size(45,45),CV_INTER_LINEAR);
templ_resized_re=templ_resized_re>200;
croppedsimilar=croppedsimilar>200;
imshow("111",croppedsimilar);
imshow("222",templ_resized_re);
int threshold = (double)(templ_resized_re.rows * templ_resized_re.cols) * 0.97;
// Search for almost same match
cv::compare(croppedsimilar , templ_resized_re , result2 , cv::CMP_EQ );
int similarPixels = countNonZero(result2);
if ( similarPixels > threshold ) {
cout << "number '0' found !!!!!" << endl;
}
if(waitKey(30) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}

How to get better results with OpenCV face recognition Module

I'm trying to use OpenCV's face recognition module to recognize 2 subjects from a video. I cropped 30 face images of the first subject and 20 face images of the second subject from the video and I use these as my training set.
I've tested all three approaches (Eigenfaces, Fisherfaces and LBP histograms), but I'm not getting good results in neither of the approaches. Sometimes the first subject is classified as the second subject and vice-verse, sometimes false detections are classified as one of the two subjects and sometimes other people in the video are classified as one of the two subjects.
How can I improve performance? Would enlarging the training set help in improving the results? Are there any other packages I can consider that performs face recognition in C++? I think it should be an easy task as I'm trying to recognize only two different subjects.
Here is my code (I'm using OpenCV 2.4.7 on windows 8 with VS2012):
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/contrib/contrib.hpp"
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <sstream>
#define EIGEN 0
#define FISHER 0
#define LBPH 1;
using namespace std;
using namespace cv;
/** Function Headers */
void detectAndDisplay( Mat frame , int i,Ptr<FaceRecognizer> model);
static Mat toGrayscale(InputArray _src) {
Mat src = _src.getMat();
// only allow one channel
if(src.channels() != 1) {
CV_Error(CV_StsBadArg, "Only Matrices with one channel are supported");
}
// create and return normalized image
Mat dst;
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
return dst;
}
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()));
}
}
}
/** Global variables */
String face_cascade_name = "C:\\OIM\\code\\OIM2 - face detection\\Debug\\haarcascade_frontalface_alt.xml";
//String face_cascade_name = "C:\\OIM\\code\\OIM2 - face detection\\Debug\\NewCascade.xml";
//String face_cascade_name = "C:\\OIM\\code\\OIM2 - face detection\\Debug\\haarcascade_eye_tree_eyeglasses.xml";
String eyes_cascade_name = "C:\\OIM\\code\\OIM2 - face detection\\Debug\\haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
/** #function main */
int main( int argc, const char** argv )
{
string fn_csv = "C:\\OIM\\faces_org.csv";
// These vectors hold the images and corresponding labels.
vector<Mat> images;
vector<int> labels;
// Read in the data. This can fail if no valid
// input filename is given.
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);
}
// Quit if there are not enough images for this demo.
if(images.size() <= 1) {
string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
CV_Error(CV_StsError, error_message);
}
// Get the height from the first image. We'll need this
// later in code to reshape the images to their original
// size:
int height = images[0].rows;
// The following lines create an Eigenfaces model for
// face recognition and train it with the images and
// labels read from the given CSV file.
// This here is a full PCA, if you just want to keep
// 10 principal components (read Eigenfaces), then call
// the factory method like this:
//
// cv::createEigenFaceRecognizer(10);
//
// If you want to create a FaceRecognizer with a
// confidennce threshold, call it with:
//
// cv::createEigenFaceRecognizer(10, 123.0);
//
//Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
#if EIGEN
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(10,2000000000);
#elif FISHER
Ptr<FaceRecognizer> model = createFisherFaceRecognizer(0, 200000000);
#elif LBPH
Ptr<FaceRecognizer> model =createLBPHFaceRecognizer(1,8,8,8,200000000);
#endif
model->train(images, labels);
Mat frame;
//-- 1. Load the cascades
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
// Get the frame rate
bool stop(false);
int count=1;
char filename[512];
for (int i=1;i<=517;i++){
sprintf(filename,"C:\\OIM\\original_frames2\\image%d.jpg",i);
Mat frame=imread(filename);
detectAndDisplay(frame,i,model);
waitKey(0);
}
return 0;
}
/** #function detectAndDisplay */
void detectAndDisplay( Mat frame ,int i, Ptr<FaceRecognizer> model)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
//face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 1, 0|CV_HAAR_SCALE_IMAGE, Size(10, 10) );
for( size_t i = 0; i < faces.size(); i++ )
{
Rect roi = Rect(faces[i].x,faces[i].y,faces[i].width,faces[i].height);
Mat face=frame_gray(roi);
resize(face,face,Size(200,200));
int predictedLabel = -1;
double confidence = 0.0;
model->predict(face, predictedLabel, confidence);
//imshow("gil",face);
//waitKey(0);
#if EIGEN
int M=10000;
#elif FISHER
int M=500;
#elif LBPH
int M=300;
#endif
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
if ((predictedLabel==1)&& (confidence<M))
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 0, 0, 255 ), 4, 8, 0 );
if ((predictedLabel==0)&& (confidence<M))
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 0), 4, 8, 0 );
if (confidence>M)
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 0, 255, 0), 4, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
//-- In each face, detect eyes
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t j = 0; j < eyes.size(); j++ )
{
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
//circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
}
}
//-- Show what you got
//imshow( window_name, frame );
char filename[512];
sprintf(filename,"C:\\OIM\\FaceRecognitionResults\\image%d.jpg",i);
imwrite(filename,frame);
}
Thanks in advance,
Gil.
First thing, as commented, increase the number of samples if possible. Also include the variations (like illumination, slight poses etc) you expect to be in the video. However, especially for eigenfaces/ fisherfaces so many images will not help to increase performance. Sadly, the best number of training samples can depend on your data.
The more important point is the hardness of the problem is totally depends on your video. If your video contains variations like illumination, pose; then you can't expect using purely appearance based methods(e.g Eigenfaces) and texture descriptor(LBP) will be succesful. First, you might want to detect faces. Then:
You might want to estimate face position and warp to frontal; check
for Active Appearance Model and Active Shape Model
Use histogram of equalization to attenuate illumination problem
Fitting an ellipse to detected face region will help against background noise.
Of course, there are many other methods available in literature; the steps I wrote is implemented in OpenCV and commonly known.
Hope it helps.

opencv cvblob -- render blobs other than white

I am trying to detect objects with cvblob. Somehow, my code only marks the white objects. How to mark objects of other colors, like a can of beer or a bottle of water.
Here is my code:
#include "highgui.h"
#include "cv.h"
#include "cvaux.h"
#include "iostream"
#include <stdio.h>
#include <ctype.h>
#include <cvblob.h>
using namespace cv;
using namespace std;
using namespace cvb;
int main(int argc, char** argv) {
CvTracks tracks;
cvNamedWindow("frame", CV_WINDOW_AUTOSIZE);
cvMoveWindow("frame", 50, 100);
CvCapture* capture;
IplImage* frame = 0;
capture = cvCreateCameraCapture( 0 ); //capture frames from cam on index 0: /dev/video0/
if (!capture) {
return -1;
}
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
frame = cvQueryFrame(capture);
while(frame) {
IplImage *gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
cvCvtColor(frame, gray, CV_BGR2GRAY);
cvThreshold(gray, gray, 150, 255, CV_THRESH_BINARY);
IplImage *labelImg=cvCreateImage(cvGetSize(gray), IPL_DEPTH_LABEL, 1);
CvBlobs blobs;
unsigned int result=cvLabel(gray, labelImg, blobs);
cvFilterByArea(blobs, 500, 1000000);
// cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_BOUNDING_BOX);
cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_CENTROID);
cvUpdateTracks(blobs, tracks, 200., 5);
cvRenderTracks(tracks, frame, frame, CV_TRACK_RENDER_ID|CV_TRACK_RENDER_BOUNDING_BOX);
for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it) {
cout << "Blob #" << it->second->label << ": Area=" << it->second->area << ", Centroid=(" << it->second->centroid.x << ", " << it->second->centroid.y << ")" << endl;
}
cvShowImage("frame", frame);
cout << "----------------------------" << endl;
frame = cvQueryFrame(capture);
char c = cvWaitKey(10);
if(c==27)
break;
}
}
Any tip is appreciated.
Milo
That's the option by default and you cannot change it if you don't change the source code in cvblob library.
If you really want to change this is so easy, you can create a copy of the same method adding a new input var like CvScalar to select output color. It's so easy.
The method cvRenderBlob will be in cvcontour.cpp.
I've been made many improvement in cvblob library and in next months I will push it to the creator.
Try adding:
"cvInRangeS(hsvframe,cvScalar(23,41,133),cvScalar(40,150,255),threshy);//for yellow"
Before Filtering the blobs. Its a range of HSV(instead of RGB) values that defines the threshold of the desire color.
Hope it helps.

Convert IplImage to CvMat

Here is the gpu surf code:
#include <iostream>
#include <iomanip>
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/imgproc/imgproc_c.h>
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
using namespace std;
using namespace cv;
using namespace cv::gpu;
void help()
{
cout << "\nThis program demonstrates using SURF_GPU features detector, descriptor extractor and BruteForceMatcher_GPU" << endl;
cout << "\nUsage:\n\tmatcher_simple_gpu <image1> <image2>" << endl;
}
int main(int argc, char* argv[])
{
GpuMat img1(imread("C:\\OpenCV2.3\\opencv2.3\\bin\\Debug\\tsucuba_left.png", CV_LOAD_IMAGE_GRAYSCALE));
SURF_GPU surf;
// detecting keypoints & computing descriptors
GpuMat keypoints1GPU, keypoints2GPU;
GpuMat descriptors1GPU, descriptors2GPU;
surf(img1, GpuMat(), keypoints1GPU, descriptors1GPU);
cout << "FOUND " << keypoints1GPU.cols << " keypoints on first image" << endl;
//cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl;
CvCapture* capture = cvCaptureFromCAM(0);
int frame_width = (int) cvGetCaptureProperty(capture, 320);
int frame_height = (int) cvGetCaptureProperty(capture, 240);
cout<<"frames done\n";
GpuMat frame_gpu = GpuMat(frame_width, frame_height, CV_8UC3);
GpuMat frame_gpu_cvt = GpuMat(frame_width, frame_height, CV_8UC1);
cout<<"gpu frmes loaded\n";
IplImage* frame;
while(1)
{
frame =cvQueryFrame(capture);
CvMat* image = cvCreateMat(frame->height, frame->width, CV_8UC1);
/*CvMat* image = cvCreateMatHeader(frame->height, frame->width, CV_8UC1);
image->step = 4 * (image->cols * CV_ELEM_SIZE1(image->type) * CV_MAT_CN(image->type) / 4 + 1);//critical
cvCreateData(image);*/
cvInitMatHeader( image, frame->width, frame->height, CV_8UC1,frame->imageData);
// cvConvert( frame, image );
//cvCvtColor( frame, image, CV_RGB2GRAY );
cvConvertImage( frame, image, CV_RGB2GRAY);
namedWindow("aa", 1);
cvShowImage("aa", frame);
frame_gpu.upload(image);
cout<<"frame uploaded\n";
surf(frame_gpu, GpuMat(), keypoints2GPU, descriptors2GPU);
cout<<"surf done\n";
// matching descriptors
BruteForceMatcher_GPU< L2<float> > matcher;
GpuMat trainIdx, distance;
matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);
cout<<"match done\n";
// downloading results
vector<KeyPoint> keypoints1, keypoints2;
vector<float> descriptors1, descriptors2;
vector<DMatch> matches;
surf.downloadKeypoints(keypoints1GPU, keypoints1);
surf.downloadKeypoints(keypoints2GPU, keypoints2);
surf.downloadDescriptors(descriptors1GPU, descriptors1);
surf.downloadDescriptors(descriptors2GPU, descriptors2);
BruteForceMatcher_GPU< L2<float> >::matchDownload(trainIdx, distance, matches);
// drawing the results
Mat img_matches;
drawMatches(img1, keypoints1, frame_gpu, keypoints2, matches, img_matches);
cout<<"match done\n";
namedWindow("matches", 1);
imshow("matches", img_matches);
cvReleaseMat(&image);
frame_gpu.release();
cvReleaseImage(&frame);
img_matches.release();
cout<<"deallocation done\n";
waitKey(0);
}
cvReleaseCapture(&capture);
cout<<"work done";
return 0;
}
We don't get correct image in frame_gpu,so there is problem in getting image from frame,we printed frame using: cvShowImage("aa", frame); but instead of frame if we try image there is just blank screen
Use your IplImage for counting, and then convert it to a Mat (in C++) with this constructor:
Mat(const IplImage* img, bool copyData=false);
So you would just do:
Mat myMat(img);
That would make your matrix. You would use it in the tracking section of your program!
NOTE: Data is not copied. You can set the copyData parameter to true, though, if you want data to be copied.
Try something like this:
IplImage* frame;
// here load your frame with some image
// convert to cv::Mat and show the converted image
cv::Mat image(frame);
cv::imshow("Image Window", image)
That's how IplImage can be converted to cv::Mat and displayed.
For conversion to and from cvMat, you will find all the details here:
http://wangpengnorman.blogspot.com/2009/06/transform-between-cvmat-and-iplimage.html

Resources