--- /dev/null
+#define CV_NO_BACKWARD_COMPATIBILITY
+
+#include "opencv/cv.h"
+#include "opencv/highgui.h"
+
+#include <iostream>
+#include <cstdio>
+
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C" {
+#include "notaio.h"
+#include "pdu.h"
+}
+
+#ifdef _EiC
+#define WIN32
+#endif
+
+using namespace std;
+using namespace cv;
+
+bool detectAndDraw( Mat& img,
+ CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
+ double scale);
+
+String cascadeName = "haarcascades/haarcascade_frontalface_alt.xml";
+String nestedCascadeName = "haarcascades/haarcascade_mcs_nose.xml";
+
+void log(const char* text) {
+ cout << text;
+}
+
+CascadeClassifier cascade, nestedCascade;
+
+bool found = false;
+struct _FACE {
+ int x,y,r;
+} face;
+
+void detect(unsigned char* buf,int buf_len) {
+ double scale = 1;
+ Mat image;
+
+ image = imdecode(Mat(1, buf_len, CV_8U, buf), 1);
+
+ if( !image.empty() )
+ {
+ found = detectAndDraw( image, cascade, nestedCascade, scale );
+ waitKey(10);
+ }
+}
+
+const char* result = "NoTA face detection";
+
+int main( int argc, const char** argv )
+{
+ /* Service socket to use for connecting to the service node. */
+ HSSockID sockid;
+ HErrorCode err;
+
+ /* The first parameter specifies the service to connect to (SID).
+ * The other parameters are reserved for legacy purposes.
+ */
+ sockid = n_connect(DEFAULT_SID, NULL, NULL);
+
+ /* sockid will be the number of the socket we got (>0), if successful,
+ * or <0 if something went wrong. Let's check:
+ */
+ if (sockid < 0) {
+ return NULL;
+ }
+
+ ServiceCallbacks callbacks = {0};
+ callbacks.log = &log;
+ callbacks.put_image = &detect;
+
+ ServiceCallbacks* cb=&callbacks;
+
+ LOG2("Connected socket %d to service '%d'.\n", sockid, DEFAULT_SID);
+
+ if( !cascade.load( cascadeName ) )
+ {
+ cerr << "ERROR: Could not load classifier cascade" << endl;
+ return -1;
+ }
+ nestedCascade.load( nestedCascadeName );
+
+ cvNamedWindow( result, 1 );
+
+ while(true) {
+ int smsg_len=0;
+ ServiceMessage* smsg = pack_pdu(GET_IMAGE, NULL, 0, &smsg_len);
+
+ err = n_send(sockid, smsg, smsg_len, HSSendBlocking);
+ free(smsg);
+ if(err < 0){
+ return NULL;
+ }
+
+ usleep(100000);
+
+ found = false;
+ int err = read_smsg(&sockid, HSReceiveNonBlocking, cb);
+ if (err < 0) //error reading service message
+ {
+ usleep(100000);
+ }
+ if(found) {
+ struct _FACE f = { htonl(face.x), htonl(face.y), htonl(face.r) };
+ smsg = pack_pdu(FACE_FOUND,(uns8*)&f,sizeof(f),&smsg_len);
+ n_send(sockid,smsg,smsg_len,HSSendBlocking);
+ free(smsg);
+ }
+
+ }
+
+ cvDestroyWindow(result);
+
+ return 0;
+}
+
+bool detectAndDraw( Mat& img,
+ CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
+ double scale)
+{
+ bool found = false;
+ int i = 0;
+ double t = 0;
+ vector<Rect> faces;
+ const static Scalar colors[] = { CV_RGB(0,0,255),
+ CV_RGB(0,128,255),
+ CV_RGB(0,255,255),
+ CV_RGB(0,255,0),
+ CV_RGB(255,128,0),
+ CV_RGB(255,255,0),
+ CV_RGB(255,0,0),
+ CV_RGB(255,0,255)} ;
+ Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
+
+ cvtColor( img, gray, CV_BGR2GRAY );
+ resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
+ equalizeHist( smallImg, smallImg );
+
+ t = (double)cvGetTickCount();
+ cascade.detectMultiScale( smallImg, faces,
+ 1.1, 2, 0
+ |CV_HAAR_FIND_BIGGEST_OBJECT
+ //|CV_HAAR_DO_ROUGH_SEARCH
+ |CV_HAAR_SCALE_IMAGE
+ ,
+ Size(30, 30) );
+ t = (double)cvGetTickCount() - t;
+ printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
+ for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
+ {
+ Mat smallImgROI;
+ vector<Rect> nestedObjects;
+ Point center;
+ Scalar color = colors[i%8];
+ int radius;
+ center.x = cvRound((r->x + r->width*0.5)*scale);
+ center.y = cvRound((r->y + r->height*0.5)*scale);
+ radius = cvRound((r->width + r->height)*0.25*scale);
+
+ found = true; face.x = center.x; face.y = center.y; face.r = radius;
+
+ circle( img, center, radius, color, 3, 8, 0 );
+ if( nestedCascade.empty() )
+ continue;
+ smallImgROI = smallImg(*r);
+ nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
+ 1.1, 2, 0
+ //|CV_HAAR_FIND_BIGGEST_OBJECT
+ //|CV_HAAR_DO_ROUGH_SEARCH
+ //|CV_HAAR_DO_CANNY_PRUNING
+ |CV_HAAR_SCALE_IMAGE
+ ,
+ Size(30, 30) );
+ for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
+ {
+ center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
+ center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
+ radius = cvRound((nr->width + nr->height)*0.25*scale);
+ circle( img, center, radius, color, 3, 8, 0 );
+ }
+ }
+ cv::imshow( result, img );
+ return found;
+}
+