/* call-seq: ObjectDetect::detect(model_path, target_path, rescale_size=nil) -> [[x,y,width,height]] Detects objects in the image file +target_path+. +model_path+ needs to point a model file (e.g. /usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml). If +rescale_size+ is specified and the width or height of the image is larger than +rescale_size+, the image is rescaled to fit into the size before processing. */ static VALUE rb_detect(int argc, VALUE *argv, VALUE self) { VALUE model_path, target_path, rescale_size; rb_scan_args(argc, argv, "21", &model_path, &target_path, &rescale_size); Check_Type(model_path, T_STRING); Check_Type(target_path, T_STRING); /* load the model */ CvHaarClassifierCascade* cascade = cvLoad(RSTRING(model_path)->ptr, 0, 0, 0); if( cascade == 0 ) { rb_raise(rb_eArgError, "Can't load the cascade file"); } /* load the target picture */ IplImage *img = cvLoadImage(RSTRING(target_path)->ptr, 1); if( !img ) { cvReleaseHaarClassifierCascade(&cascade); rb_raise(rb_eArgError, "Can't load the image file"); } /* to gray scale */ IplImage *gray = cvCreateImage( cvSize(img->width, img->height), 8, 1); cvCvtColor(img, gray, CV_BGR2GRAY); cvEqualizeHist(gray, gray); /* rescale */ double scale = 1; if(argc == 3 || rescale_size != Qnil) { double limit = (double)NUM2INT(rescale_size); double scale_w, scale_h; scale_w = (double)img->width/limit; scale_h = (double)img->height/limit; scale = (scale_w>scale_h) ? scale_w : scale_h; if(scale < 1) scale = 1; } IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); cvResize( gray, small_img, CV_INTER_LINEAR ); /* detect regions */ CvMemStorage* storage = cvCreateMemStorage(0); CvSeq *faces = cvHaarDetectObjects(small_img, cascade, storage, 1.1, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(0,0) ); /* output */ VALUE results = rb_ary_new(); int i=0; for(i=0; i<(faces?faces->total:0); i++) { CvRect* r = (CvRect*)cvGetSeqElem(faces, i); rb_ary_push(results, rb_ary_new3(4, INT2NUM(r->x*scale), INT2NUM(r->y*scale), INT2NUM(r->width*scale),INT2NUM(r->height*scale) ) ); } /* cleanups */ cvReleaseHaarClassifierCascade(&cascade); cvReleaseMemStorage(&storage); cvReleaseImage(&img); cvReleaseImage(&gray); cvReleaseImage(&small_img); return results; }