Skip to content

Commit

Permalink
* add laughing man mode
Browse files Browse the repository at this point in the history
git-svn-id: svn+ssh://svn.dotswitch.net/var/svn/dotswitch/projects/iphone/OpenCVTest@1929 c432a1ab-ec09-0410-8e5f-fb625be92370
  • Loading branch information
niw committed Jul 29, 2008
1 parent 9679d94 commit bcb1f2a
Show file tree
Hide file tree
Showing 5 changed files with 1,161 additions and 85 deletions.
6 changes: 6 additions & 0 deletions Classes/OpenCVTestViewController.h
@@ -1,7 +1,13 @@
#import <UIKit/UIKit.h>

typedef enum {
ActionSheetToSelectTypeOfSource = 1,
ActionSheetToSelectTypeOfMarks
} OpenCVTestViewControllerActionSheetAction;

@interface OpenCVTestViewController : UIViewController <UIActionSheetDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
IBOutlet UIImageView *imageView;
OpenCVTestViewControllerActionSheetAction actionSheetAction;
}

- (IBAction)loadImage:(id)sender;
Expand Down
179 changes: 102 additions & 77 deletions Classes/OpenCVTestViewController.m
@@ -1,7 +1,6 @@
#import "OpenCVTestViewController.h"

#include <opencv/cv.h>
#include <opencv/highgui.h>

@implementation OpenCVTestViewController
@synthesize imageView;
Expand Down Expand Up @@ -56,28 +55,15 @@ - (UIImage *)UIImageFromIplImage:(IplImage *)image {
#pragma mark IBAction

- (IBAction)loadImage:(id)sender {
/* // Testing IplImage <-> UIImage Conversion
cvSetErrMode(CV_ErrModeParent);
NSString *path = [[NSBundle mainBundle] pathForResource:@"lena" ofType:@"jpg"];
// Load UIImage and convert to IplImage
UIImage *uiimage = [UIImage imageWithContentsOfFile:path];
IplImage *img = [self CreateIplImageFromUIImage:uiimage];
// Convert IplImage(BGR) to IplImage(RGB) then convert to UIImage to show
IplImage *image = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
cvCvtColor(img, image, CV_BGR2RGB);
cvReleaseImage(&img);
imageView.image = [self UIImageFromIplImage:image];
cvReleaseImage(&image);
*/
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@""
delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil
otherButtonTitles:@"Use Photo from Library", @"Take Photo with Camera", @"Use Default Lena", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showInView:self.view];
[actionSheet release];
if(!actionSheetAction) {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@""
delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil
otherButtonTitles:@"Use Photo from Library", @"Take Photo with Camera", @"Use Default Lena", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
actionSheetAction = ActionSheetToSelectTypeOfSource;
[actionSheet showInView:self.view];
[actionSheet release];
}
}

- (IBAction)edgeDetect:(id)sender {
Expand Down Expand Up @@ -107,38 +93,14 @@ - (IBAction)edgeDetect:(id)sender {

- (IBAction)faceDetect:(id)sender {
cvSetErrMode(CV_ErrModeParent);
if(imageView.image) {
IplImage *image = [self CreateIplImageFromUIImage:imageView.image];

// Scaling down
IplImage *small_image = cvCreateImage(cvSize(image->width/2,image->height/2), IPL_DEPTH_8U, 3);
cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
int scale = 2;

// Load XML
NSString *path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"];
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL, NULL);
CvMemStorage* storage = cvCreateMemStorage(0);

// Detect faces and draw rectangle on them
CvSeq* faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2f, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(20, 20));
cvReleaseImage(&small_image);

for(int i = 0; i < faces->total; i++) {
CvRect face_rect = *(CvRect*)cvGetSeqElem(faces, i);
cvRectangle(image, cvPoint(face_rect.x * scale, face_rect.y * scale),
cvPoint((face_rect.x + face_rect.width) * scale, (face_rect.y + face_rect.height) * scale), CV_RGB(255, 0, 0), 3, 8, 0);
}
cvReleaseMemStorage(&storage);
cvReleaseHaarClassifierCascade(&cascade);

// Convert BGR to RGB, then show it
IplImage *img = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 3);
cvCvtColor(image, img, CV_BGR2RGB);
cvReleaseImage(&image);

imageView.image = [self UIImageFromIplImage:img];
cvReleaseImage(&img);
if(imageView.image && !actionSheetAction) {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@""
delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil
otherButtonTitles:@"Bounding Box", @"Laughing Man", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
actionSheetAction = ActionSheetToSelectTypeOfMarks;
[actionSheet showInView:self.view];
[actionSheet release];
}
}

Expand All @@ -163,29 +125,92 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
#pragma mark UIActionSheetDelegate

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
UIImagePickerControllerSourceType sourceType;

if (buttonIndex == 0) {
sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
} else if(buttonIndex == 1) {
sourceType = UIImagePickerControllerSourceTypeCamera;
} else if(buttonIndex == 2) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"lena" ofType:@"jpg"];
imageView.image = [UIImage imageWithContentsOfFile:path];
return;
} else {
// Cancel
return;
}

if([UIImagePickerController isSourceTypeAvailable:sourceType]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = sourceType;
picker.delegate = self;
picker.allowsImageEditing = NO;
[self presentModalViewController:picker animated:YES];
[picker release];
switch(actionSheetAction) {
case ActionSheetToSelectTypeOfSource: {
UIImagePickerControllerSourceType sourceType;
if (buttonIndex == 0) {
sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
} else if(buttonIndex == 1) {
sourceType = UIImagePickerControllerSourceTypeCamera;
} else if(buttonIndex == 2) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"lena" ofType:@"jpg"];
imageView.image = [UIImage imageWithContentsOfFile:path];
break;
} else {
// Cancel
break;
}
if([UIImagePickerController isSourceTypeAvailable:sourceType]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = sourceType;
picker.delegate = self;
picker.allowsImageEditing = NO;
[self presentModalViewController:picker animated:YES];
[picker release];
}
break;
}
case ActionSheetToSelectTypeOfMarks: {
if(buttonIndex != 0 && buttonIndex != 1) {
break;
}

NSString *path;
IplImage *image = [self CreateIplImageFromUIImage:imageView.image];

// Scaling down
IplImage *small_image = cvCreateImage(cvSize(image->width/2,image->height/2), IPL_DEPTH_8U, 3);
cvPyrDown(image, small_image, CV_GAUSSIAN_5x5);
int scale = 2;

// Load XML
path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"];
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL, NULL);
CvMemStorage* storage = cvCreateMemStorage(0);

// Detect faces and draw rectangle on them
CvSeq* faces = cvHaarDetectObjects(small_image, cascade, storage, 1.2f, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(20, 20));
cvReleaseImage(&small_image);

// Create canvas to show the results
CGImageRef imageRef = imageView.image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef contextRef = CGBitmapContextCreate(NULL, imageView.image.size.width, imageView.image.size.height,
CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef),
colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
CGContextDrawImage(contextRef, CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height), imageRef);

path = [[NSBundle mainBundle] pathForResource:@"laughing_man" ofType:@"png"];
CGImageRef laughing_man = [UIImage imageWithContentsOfFile:path].CGImage;

// Draw results on the iamge
for(int i = 0; i < faces->total; i++) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// Calc the rect of faces
CvRect cvrect = *(CvRect*)cvGetSeqElem(faces, i);
CGRect face_rect = CGContextConvertRectToDeviceSpace(contextRef, CGRectMake(cvrect.x * scale, cvrect.y * scale, cvrect.width * scale, cvrect.height * scale));

if(buttonIndex == 0) {
CGContextStrokeRect(contextRef, face_rect);
} else if(buttonIndex == 1) {
CGContextDrawImage(contextRef, face_rect, laughing_man);
}

[pool release];
}

imageView.image = [UIImage imageWithCGImage:CGBitmapContextCreateImage(contextRef)];
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);

cvReleaseMemStorage(&storage);
cvReleaseHaarClassifierCascade(&cascade);

break;
}
}
actionSheetAction = 0;
}

#pragma mark -
Expand Down
14 changes: 6 additions & 8 deletions OpenCVTest.xcodeproj/project.pbxproj
Expand Up @@ -16,13 +16,11 @@
540723E30E3DD25B00B598A2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
540723E40E3DD25B00B598A2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5452E0730E3D119700FE4518 /* CoreGraphics.framework */; };
540724030E3DD76A00B598A2 /* libcv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540723FE0E3DD76A00B598A2 /* libcv.a */; };
540724040E3DD76A00B598A2 /* libcvaux.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540723FF0E3DD76A00B598A2 /* libcvaux.a */; };
540724050E3DD76A00B598A2 /* libcxcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540724000E3DD76A00B598A2 /* libcxcore.a */; };
540724060E3DD76A00B598A2 /* libhighgui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540724010E3DD76A00B598A2 /* libhighgui.a */; };
540724070E3DD76A00B598A2 /* libml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540724020E3DD76A00B598A2 /* libml.a */; };
540ABC6B0E3E1C5300E30885 /* haarcascade_frontalface_default.xml in Resources */ = {isa = PBXBuildFile; fileRef = 540ABC6A0E3E1C5300E30885 /* haarcascade_frontalface_default.xml */; };
540ABCF60E3E280700E30885 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 540ABCF50E3E280700E30885 /* Icon.png */; };
549913C70E3E3D2100BD1311 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 549913C60E3E3D2100BD1311 /* Default.png */; };
54FC5BC80E3EAF7900F48645 /* libcxcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 540724000E3DD76A00B598A2 /* libcxcore.a */; };
54FC5BDE0E3EB3EB00F48645 /* laughing_man.png in Resources */ = {isa = PBXBuildFile; fileRef = 54FC5BDD0E3EB3EB00F48645 /* laughing_man.png */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -46,6 +44,7 @@
5452E0090E3D08AA00FE4518 /* lena.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = lena.jpg; sourceTree = "<group>"; };
5452E0730E3D119700FE4518 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
549913C60E3E3D2100BD1311 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
54FC5BDD0E3EB3EB00F48645 /* laughing_man.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = laughing_man.png; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand All @@ -58,10 +57,7 @@
540723E30E3DD25B00B598A2 /* UIKit.framework in Frameworks */,
540723E40E3DD25B00B598A2 /* CoreGraphics.framework in Frameworks */,
540724030E3DD76A00B598A2 /* libcv.a in Frameworks */,
540724040E3DD76A00B598A2 /* libcvaux.a in Frameworks */,
540724050E3DD76A00B598A2 /* libcxcore.a in Frameworks */,
540724060E3DD76A00B598A2 /* libhighgui.a in Frameworks */,
540724070E3DD76A00B598A2 /* libml.a in Frameworks */,
54FC5BC80E3EAF7900F48645 /* libcxcore.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -112,6 +108,7 @@
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
54FC5BDD0E3EB3EB00F48645 /* laughing_man.png */,
540ABCF50E3E280700E30885 /* Icon.png */,
540ABC6A0E3E1C5300E30885 /* haarcascade_frontalface_default.xml */,
5452E0090E3D08AA00FE4518 /* lena.jpg */,
Expand Down Expand Up @@ -191,6 +188,7 @@
540ABC6B0E3E1C5300E30885 /* haarcascade_frontalface_default.xml in Resources */,
540ABCF60E3E280700E30885 /* Icon.png in Resources */,
549913C70E3E3D2100BD1311 /* Default.png in Resources */,
54FC5BDE0E3EB3EB00F48645 /* laughing_man.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
1,047 changes: 1,047 additions & 0 deletions laughing_man.ai

Large diffs are not rendered by default.

Binary file added laughing_man.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit bcb1f2a

Please sign in to comment.