// // MPTSmileController.m // // Created by Andrew Salamon on 9/25/06. // Copyright (c) 2006 Machine Perception Laboratory, // University of California San Diego. All rights reserved. // #import "MPTSmileController.h" #import #import #import #import @interface MPTSmileController(PrivateMethods) - (void)loadFilters; - (void)adjustViews; - (void)setViewRanges:(MPT_AUView *)aView; @end static const int AU = 101; @implementation MPTSmileController - (id)initWithBundle:(NSBundle *)_bundle { if( self = [super initWithBundle:_bundle] ) { smiles = new MPSmile( 2, MPSmile::featuerDetectorWeights ); smiles->setPixelMax( 1.0 ); rotator = new MP_RotateFace( SMD_FACE_SIZE ); //rotator->setEyeLenRate( 0.48 ); patch = new RImage( SMD_FACE_SIZE, SMD_FACE_SIZE ); [self loadFilters]; [self adjustViews]; if( ![NSBundle loadNibNamed:@"SmilePrefView" owner:self] ) NSLog( @"Unable to load pref pane for MPTSmileController." ); } return self; } - (void)dealloc { delete smiles; delete rotator; delete patch; [filters release]; [super dealloc]; } - (id)copyWithZone:(NSZone *)zone { MPTSmileController *cp = [super copyWithZone:zone]; return cp; } - (void)makeThreadsafe { [super makeThreadsafe]; smiles = new MPSmile( 2, MPSmile::featuerDetectorWeights ); smiles->setPixelMax( 1.0 ); rotator = new MP_RotateFace( SMD_FACE_SIZE ); //rotator->setEyeLenRate( 0.48 ); patch = new RImage( SMD_FACE_SIZE, SMD_FACE_SIZE ); filters = nil; [self loadFilters]; } - (NSView *)prefPane { if( [delegate isEvaluation] ) return nil; else return prefView; } - (BOOL)doFilters { return [[self getPrefForKey:@"doFilters"] boolValue]; } - (void)setDoFilters:(BOOL)value { if( [self doFilters] != value ) { [self setPrefForKey:@"doFilters" to:[NSNumber numberWithBool:value]]; if( [views count] > 0 ) [self adjustViews]; } } - (void)adjustViews { NSEnumerator *viewEnum = [views objectEnumerator]; while( MPT_AUView *aView = [viewEnum nextObject] ) { [self setViewRanges:aView]; } } - (BOOL)loadLabels { labels = [[NSArray alloc] initWithObjects:[self localizedName], nil]; return YES; } - (NSString *)pluginID { NSString *ident = [super pluginID]; if( [ident length] > 0 ) return ident; return @"edu.ucsd.mplab.plugins.SmileDetector2"; } - (NSString *)localizedName { return NSLocalizedStringFromTableInBundle(@"Smile Detector 2", nil, [NSBundle bundleForClass:[self class]], @""); } - (NSString *)internalName { return @"smiles2"; } - (NSString *)step { return MPT_PluginStep_AfterFaces; } - (void)setView:(MPT_AUView *)newView forLabel:(NSString *)label { [super setView:newView forLabel:label]; [self setViewRanges:newView]; } - (void)setViewRanges:(MPT_AUView *)aView { [aView resetDynamicRange]; if( [self doFilters] ) { [aView setDefaultMin:0.0]; [aView setDefaultMax:1.0]; } else { [aView setDefaultMin:-0.5]; [aView setDefaultMax:0.5]; } } - (id)processFaces:(EyeFaceList &)faces fromEyefinder:(MPTSlidingWindow *)eyefinder withImage:(RImage &)pixels { RIntegral* pfIntegral = static_cast*>(eyefinder->getIntegralPtr().get()); NSNumber *res = NULL; if( SMD_NO_ERR == smiles->findSmilesGivenEyes( pixels, faces, 1.0f, pfIntegral ) ) { if( faces.size() > 0 ) { double value = faces.begin()->activation; if( [self doFilters] ) { value = [filters filterValue:value forAU:AU face:true]; faces.begin()->activation = value; } res = [NSNumber numberWithDouble:value]; } } if( [self doFilters] && !res ) { [filters filterValue:0.0 forAU:AU face:false]; } return res; } - (id)processFace:(ObjectWithFeatures &)face fromFeatureDetector:(FeatureDetector *)fd withImage:(RImage &)pixels { FeatureAlignment::alignment_method method = FeatureAlignment::procrustes; RIntegral* pfIntegral = static_cast*>(fd->getIntegralPtr().get()); BOOL didRotate; NSNumber *res = NULL; MP_RotateFace::OWFList faces; faces.push_back( face ); try { didRotate = rotator->rotateImageUsingFeatures( fd, &pixels, faces, *patch, method, pfIntegral ); } catch( const char *msg ) { NSLog( @"%s", msg ); } catch(...) { NSLog( @"%@: Unable to align face patch.", [self localizedName] ); } if( didRotate ) { FaceObject tempFace; mp_FDEyes::FaceFromObject( tempFace, face ); smiles->findSmilesFromFace( *patch, tempFace, 1.0f ); face.activation = tempFace.activation; if( [self doFilters] ) { face.activation = [filters filterValue:face.activation forAU:AU face:true]; } res = [NSNumber numberWithDouble:face.activation]; } return res; } - (id)processFace:(FaceObject &)face withImage:(RImage &)pixels { smiles->findSmilesFromFace( pixels, face, 1.0 ); if( [self doFilters] ) { face.activation = [filters filterValue:face.activation forAU:AU face:true]; } return [NSNumber numberWithDouble:face.activation]; } - (void)processNoFace { if( [self doFilters] ) { [filters filterValue:0.0 forAU:AU face:false]; } } - (void)loadFilters { [filters release]; filters = [[MPT_ExpressionFilter alloc] initWithAU:AU]; } @end