- Back to Home »
- Face Tracking Haar Cascade Classifier menggunakan Pan/Tilt Camera OpenCV 2.4.9 pada Ubuntu 14.04
Posted by : M yunus
Jumat, 28 Agustus 2015
Haar Cascade Classifier adalah algoritma yang digunakan untuk mengenali fitur wajah manusia. Haar Cascade Classifier atau Penggolong Riam Haar mampu membedakan wajah dan bukan wajah. Haar Cascade Classifier mengklasifikasi gambar kedalam image positif dan image negatif. Image positif bernilai True, sedangkan image negatif bernilai False. Saat ada wajah yang sedang di jajaki oleh kamera dan di proses melalui OpenCV, maka OpenCV akan melakukan traini untuk mengukur image tersebit kedalam image positif dan negatif. keterangan lengkap dan bagaimana Haar Cascade Classifier bekerja dapat dilihat di docs.opencv.org
==================================================
skema rangkaian elektronik:
===================================================
CODE OPENCV:
===================================================
// Include header files
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
// Create memory for calculations
static CvMemStorage* storage = 0;
// Create a new Haar classifier
static CvHaarClassifierCascade* cascade = 0;
// Function prototype for detecting and drawing an object from an image
void detect_and_draw( IplImage* image );
// Create a string that contains the cascade name
const char* cascade_name =
"haarcascade_frontalface_alt.xml";
/* "haarcascade_profileface.xml";*/
// Main function, defines the entry point for the program.
int main( int argc, char** argv )
{
//Serial to Arduino
FILE *file;
file = fopen("/dev/ttyACM0","w");
// Structure for getting video from camera or avi
CvCapture* capture = 0;
/// Images to capture the frame from video or camera or from file
IplImage *frame, *frame_copy = 0;
// Used for calculations
int optlen = strlen("--cascade=");
// Input file name for avi or image file.
const char* input_name;
// Check for the correct usage of the command line
if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
{
cascade_name = argv[1] + optlen;
input_name = argc > 2 ? argv[2] : 0;
}
else
{
fprintf( stderr,
"Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );
return -1;
/*input_name = argc > 1 ? argv[1] : 0;*/
}
// Load the [[HaarClassifierCascade]]
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
// Check whether the cascade has loaded successfully. Else report and error and quit
if( !cascade )
{
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
return -1;
}
// Allocate the memory storage
storage = cvCreateMemStorage(0);
// Find whether to detect the object from file or from camera.
if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
else
capture = cvCaptureFromAVI( input_name );
// Create a new named window with title: result
cvNamedWindow( "result", 1 );
// Find if the capture is loaded successfully or not.
// If loaded succesfully, then:
if( capture )
{
// Capture from the camera.
for(;;)
{
// Capture the frame and load it in [[IplImage]]
if( !cvGrabFrame( capture ))
break;
frame = cvRetrieveFrame( capture );
// If the frame does not exist, quit the loop
if( !frame )
break;
// Allocate framecopy as the same size of the frame
if( !frame_copy )
frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
IPL_DEPTH_8U, frame->nChannels );
// Check the origin of image. If top left, copy the image frame to frame_copy.
if( frame->origin == IPL_ORIGIN_TL )
cvCopy( frame, frame_copy, 0 );
// Else flip and copy the image
else
cvFlip( frame, frame_copy, 0 );
// Call the function to detect and draw the face
// detect_and_draw( frame_copy );
//==========================================================================//
int scale = 1;
// Create a new image based on the input image
IplImage* temp = cvCreateImage( cvSize(frame_copy->width/scale,frame_copy->height/scale), 8, 3 );
// Create two points to represent the face locations
CvPoint pt1, pt2;
int i;
// Clear the memory storage which was used before
cvClearMemStorage( storage );
// Find whether the cascade is loaded, to find the faces. If yes, then:
if( cascade )
{
// There can be more than one face in an image. So create a growable sequence of faces.
// Detect the objects and store them in the sequence
CvSeq* faces = cvHaarDetectObjects( frame_copy, cascade, storage,
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
cvSize(40, 40) );
// Loop the number of faces found.
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
// Create a new rectangle for drawing the face
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
// Find the dimensions of the face,and scale it if necessary
pt1.x = r->x*scale;
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;
//Serial to Arduino data transfer
int a=1,b=2,c=3,d=4;
if((pt1.x<320)&&(pt2.y<240)){
fprintf(file,"%d\n",a);
printf("a\n");
}
else if((pt1.x>320)&&(pt1.y<240)){
fprintf(file,"%d\n",b);
printf("b\n");
}
else if((pt1.x>320)&&(pt1.y>240)){
fprintf(file,"%d\n",c);
printf("c\n");
}
else if((pt1.x< 320)&&(pt1.y>240)){
fprintf(file,"%d\n",d);
printf("d\n");
}
// fclose(file);
// printf("x=%d y=%d\n", pt1.x, pt1.y);
// Draw the rectangle in the input image
cvRectangle( frame_copy, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
}
}
// Show the image in the window named "result"
cvShowImage( "result", frame_copy );
// Release the temp image created.
cvReleaseImage( &temp );
//=====================================================================//
// Wait for a while before proceeding to the next frame
if( cvWaitKey( 10 ) >= 0 )
break;
}
// Release the images, and capture memory
cvReleaseImage( &frame_copy );
cvReleaseCapture( &capture );
}
// If the capture is not loaded succesfully, then:
else
{
// Assume the image to be lena.jpg, or the input_name specified
const char* filename = input_name ? input_name : (char*)"lena.jpg";
// Load the image from that filename
IplImage* image = cvLoadImage( filename, 1 );
// If Image is loaded succesfully, then:
if( image )
{
// Detect and draw the face
// detect_and_draw( image );
// Wait for user input
cvWaitKey(0);
// Release the image memory
cvReleaseImage( &image );
}
}
fclose(file);
// Destroy the window previously created with filename: "result"
cvDestroyWindow("result");
// return 0 to indicate successfull execution of the program
return 0;
}
/*
// Function to detect and draw any faces that is present in an image
void detect_and_draw( IplImage* img )
{
int scale = 1;
// Create a new image based on the input image
IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );
// Create two points to represent the face locations
CvPoint pt1, pt2;
int i;
// Clear the memory storage which was used before
cvClearMemStorage( storage );
// Find whether the cascade is loaded, to find the faces. If yes, then:
if( cascade )
{
// There can be more than one face in an image. So create a growable sequence of faces.
// Detect the objects and store them in the sequence
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
cvSize(40, 40) );
// Loop the number of faces found.
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
// Create a new rectangle for drawing the face
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
// Find the dimensions of the face,and scale it if necessary
pt1.x = r->x*scale;
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;
//Serial to Arduino data transfer
int a=1,b=2,c=3,d=4;
if((pt1.x<320)&&(pt2.y<240)){
fprintf(file,"%d",a);
printf("a\n");
}
else if((pt1.x>320)&&(pt1.y<240)){
fprintf(file,"%d",b);
printf("b\n");
}
else if((pt1.x>320)&&(pt1.y>240)){
fprintf(file,"%d",c);
printf("c\n");
}
else if((pt1.x< 320)&&(pt1.y>240)){
fprintf(file,"%d",d);
printf("d\n");
}
// fclose(file);
// printf("x=%d y=%d\n", pt1.x, pt1.y);
// Draw the rectangle in the input image
cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
}
}
// Show the image in the window named "result"
cvShowImage( "result", img );
// Release the temp image created.
cvReleaseImage( &temp );
}
*/
==================================================
==================================================
ARDUINO CODE:
....>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<...............
#include <Servo.h>
Servo tilt;
Servo pan;
int i=90,j=90;
char incomingByte = 0; // for incoming serial data
void setup(){
tilt.attach(9);
pan.attach(10);
Serial.begin(9600);
tilt.write(90);
pan.write(90);
}
void satu(){
pan.write(i);
tilt.write(j);
i=i+1;
j=j-1;
}
void dua(){
pan.write(i);
tilt.write(j);
i=i-1;
j=j-1;
}
void tiga(){
pan.write(i);
tilt.write(j);
i=i-1;
j=j+1;
}
void empat(){
pan.write(i);
tilt.write(j);
i=i+1;
j=j+1;
}
void loop()
{
// send data only when you receive data:
if (Serial.available() > 0)
{
incomingByte = Serial.read();
switch (incomingByte)
{
case '1':
satu();
delay(10);
break;
case '2':
dua();
delay(10);
break;
case '3':
tiga();
delay(10);
break;
case '4':
empat();
delay(10);
break;
}
}
}
==================================================
==================================================
VIDEO DOKUMENTASI:
Sumber:
OpenCV 2.4.9 Tutorials (User Guide)