Initial commit
[jamendo] / branches / nota-show-app / src / facedetect.cpp
1 #define CV_NO_BACKWARD_COMPATIBILITY
2
3 #include "opencv/cv.h"
4 #include "opencv/highgui.h"
5
6 #include <iostream>
7 #include <cstdio>
8
9 #include <unistd.h>
10 #include <netinet/in.h> 
11
12 extern "C" {
13 #include "notaio.h"
14 #include "pdu.h"
15 }
16
17 #ifdef _EiC
18 #define WIN32
19 #endif
20
21 using namespace std;
22 using namespace cv;
23
24 bool detectAndDraw( Mat& img,
25                    CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
26                    double scale);
27
28 String cascadeName = "haarcascades/haarcascade_frontalface_alt.xml";
29 String nestedCascadeName = "haarcascades/haarcascade_mcs_nose.xml";
30
31 void log(const char* text) {
32         cout << text;
33 }
34
35 CascadeClassifier cascade, nestedCascade;
36
37 bool found = false;
38 struct _FACE {
39         int x,y,r;
40 } face;
41
42 void detect(unsigned char* buf,int buf_len) {
43     double scale = 1;
44         Mat image;
45
46         image = imdecode(Mat(1, buf_len, CV_8U, buf), 1);
47
48         if( !image.empty() )
49     {
50         found = detectAndDraw( image, cascade, nestedCascade, scale );
51                 waitKey(10);
52     }
53 }
54
55 const char* result = "NoTA face detection";
56
57 int main( int argc, const char** argv )
58 {
59         /* Service socket to use for connecting to the service node. */
60         HSSockID sockid;
61         HErrorCode err;
62
63         /* The first parameter specifies the service to connect to (SID).
64          * The other parameters are reserved for legacy purposes.
65          */
66         sockid = n_connect(DEFAULT_SID, NULL, NULL);
67
68         /* sockid will be the number of the socket we got (>0), if successful,
69          * or <0 if something went wrong. Let's check:
70          */
71         if (sockid < 0) {
72                 return NULL;
73         }
74
75         ServiceCallbacks callbacks = {0};
76         callbacks.log = &log;
77         callbacks.put_image = &detect;
78
79         ServiceCallbacks* cb=&callbacks;
80         
81         LOG2("Connected socket %d to service '%d'.\n", sockid, DEFAULT_SID);
82
83     if( !cascade.load( cascadeName ) )
84     {
85         cerr << "ERROR: Could not load classifier cascade" << endl;
86         return -1;
87     }
88         nestedCascade.load( nestedCascadeName );
89         
90         cvNamedWindow( result, 1 );
91
92         while(true) {
93                 int smsg_len=0;
94                 ServiceMessage* smsg = pack_pdu(GET_IMAGE, NULL, 0, &smsg_len);
95
96                 err = n_send(sockid, smsg, smsg_len, HSSendBlocking);
97                 free(smsg);
98                 if(err < 0){
99                         return NULL;
100                 }
101
102                 usleep(100000);
103
104                 found = false;
105                 int err = read_smsg(&sockid, HSReceiveNonBlocking, cb); 
106                 if (err < 0)    //error reading service message
107                 {
108                         usleep(100000);
109                 }
110                 if(found) {
111                         struct _FACE f = { htonl(face.x), htonl(face.y), htonl(face.r) };
112                         smsg = pack_pdu(FACE_FOUND,(uns8*)&f,sizeof(f),&smsg_len);
113                         n_send(sockid,smsg,smsg_len,HSSendBlocking);
114                         free(smsg);
115                 }
116                 
117         }
118
119     cvDestroyWindow(result);
120
121     return 0;
122 }
123
124 bool detectAndDraw( Mat& img,
125                    CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
126                    double scale)
127 {
128         bool found = false;
129     int i = 0;
130     double t = 0;
131     vector<Rect> faces;
132     const static Scalar colors[] =  { CV_RGB(0,0,255),
133         CV_RGB(0,128,255),
134         CV_RGB(0,255,255),
135         CV_RGB(0,255,0),
136         CV_RGB(255,128,0),
137         CV_RGB(255,255,0),
138         CV_RGB(255,0,0),
139         CV_RGB(255,0,255)} ;
140     Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
141
142     cvtColor( img, gray, CV_BGR2GRAY );
143     resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
144     equalizeHist( smallImg, smallImg );
145
146     t = (double)cvGetTickCount();
147     cascade.detectMultiScale( smallImg, faces,
148         1.1, 2, 0
149         |CV_HAAR_FIND_BIGGEST_OBJECT
150         //|CV_HAAR_DO_ROUGH_SEARCH
151         |CV_HAAR_SCALE_IMAGE
152         ,
153         Size(30, 30) );
154     t = (double)cvGetTickCount() - t;
155     printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
156     for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
157     {
158                 Mat smallImgROI;
159         vector<Rect> nestedObjects;
160         Point center;
161         Scalar color = colors[i%8];
162         int radius;
163         center.x = cvRound((r->x + r->width*0.5)*scale);
164         center.y = cvRound((r->y + r->height*0.5)*scale);
165         radius = cvRound((r->width + r->height)*0.25*scale);
166
167                 found = true; face.x = center.x; face.y = center.y; face.r = radius;
168                 
169         circle( img, center, radius, color, 3, 8, 0 );
170         if( nestedCascade.empty() )
171             continue;
172         smallImgROI = smallImg(*r);
173         nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
174             1.1, 2, 0
175             //|CV_HAAR_FIND_BIGGEST_OBJECT
176             //|CV_HAAR_DO_ROUGH_SEARCH
177             //|CV_HAAR_DO_CANNY_PRUNING
178             |CV_HAAR_SCALE_IMAGE
179             ,
180             Size(30, 30) );
181         for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
182         {
183             center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
184             center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
185             radius = cvRound((nr->width + nr->height)*0.25*scale);
186             circle( img, center, radius, color, 3, 8, 0 );
187         }
188     }  
189     cv::imshow( result, img );    
190         return found;
191 }
192