void update() { if (!cascade) { cvSetNumThreads(cvRound(threads * 100)); f0r_param_string classifier; get_param_value(&classifier, FACEBL0R_PARAM_CLASSIFIER); if (classifier) { cascade = (CvHaarClassifierCascade*) cvLoad(classifier, 0, 0, 0 ); if (!cascade) fprintf(stderr, "ERROR: Could not load classifier cascade %s\n", classifier); storage = cvCreateMemStorage(0); } else { memcpy(out, in, size * 4); return; } } // copy input image to OpenCV if( !image ) image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 4); memcpy(image->imageData, in, size * 4); // only re-detect periodically to control performance and reduce shape jitter int recheckInt = abs(cvRound(recheck * 1000)); if ( recheckInt > 0 && count % recheckInt ) { // skip detect count++; // fprintf(stderr, "draw-only counter %u\n", count); } else { count = 1; // reset the recheck counter if (objects) // reset the list of objects cvClearSeq(objects); double elapsed = (double) cvGetTickCount(); objects = detect(); // use detection time to throttle frequency of re-detect vs. redraw (automatic recheck) elapsed = cvGetTickCount() - elapsed; elapsed = elapsed / ((double) cvGetTickFrequency() * 1000.0); // Automatic recheck uses an undocumented negative parameter value, // which is not compliant, but technically feasible. if (recheck < 0 && cvRound( elapsed / (1000.0 / (recheckInt + 1)) ) <= recheckInt) count += recheckInt - cvRound( elapsed / (1000.0 / (recheckInt + 1))); // fprintf(stderr, "detection time = %gms counter %u\n", elapsed, count); } draw(); // copy filtered OpenCV image to output memcpy(out, image->imageData, size * 4); cvReleaseImage(&image); }
void FaceBl0r::update() { if (!cascade) { cvSetNumThreads(cvRound(threads * 100)); if (classifier.length() > 0) { if (classifier == old_classifier) { // same as before, avoid repeating error messages memcpy(out, in, size * 4); // of course assuming we are RGBA only return; } else old_classifier = classifier; cascade = (CvHaarClassifierCascade*) cvLoad(classifier.c_str(), 0, 0, 0 ); if (!cascade) { fprintf(stderr, "ERROR in filter facebl0r, classifier cascade not found:\n"); fprintf(stderr, " %s\n", classifier.c_str()); memcpy(out, in, size * 4); return; } storage = cvCreateMemStorage(0); } else { memcpy(out, in, size * 4); return; } } // sanitize parameters recheck = CLAMP(recheck, 0.001, 1.0); search_scale = CLAMP(search_scale, 0.11, 1.0); neighbors = CLAMP(neighbors, 0.01, 1.0); if( !image ) image = cvCreateImage( cvSize(width,height), IPL_DEPTH_8U, 4 ); memcpy(image->imageData, in, size * 4); /* no face* - look for (detect_face) yes face - track face - no more face no face* */ if(face_notfound>0) { if(face_notfound % cvRound(recheck * 1000) == 0) face_rect = detect_face(image, cascade, storage); // if no face detected if (!face_rect) { face_notfound++; } else { //track detected face with camshift if(tracked_obj) destroy_tracked_object(tracked_obj); tracked_obj = create_tracked_object(image, face_rect); face_notfound = 0; face_found++; } } if(face_found>0) { //track the face in the new frame face_box = camshift_track_face(image, tracked_obj); int min = cvRound(smallest * 1000); min = min? min : 10; int max = cvRound(largest * 10000); if( ( face_box.size.width < min ) || (face_box.size.height < min ) || (face_box.size.width > max ) || (face_box.size.height > max ) ) { face_found = 0; face_notfound++; } else { //////////////////////////////////////////////////////////////////////// cvSetImageROI (image, tracked_obj->prev_rect); // cvSmooth (image, image, CV_BLUR, 22, 22, 0, 0); cvSmooth (image, image, CV_BLUR, 23, 23, 0, 0); // cvSmooth (image, image, CV_GAUSSIAN, 11, 11, 0, 0); cvResetImageROI (image); //////////////////////////////////////////////////////////////////////// //outline face ellipse if (ellipse) cvEllipseBox(image, face_box, CV_RGB(255,0,0), 2, CV_AA, 0); face_found++; if(face_found % cvRound(recheck * 1000) == 0) face_notfound = cvRound(recheck * 1000); // try recheck } } memcpy(out, image->imageData, size * 4); cvReleaseImage(&image); }