├── iosscreen.png ├── osxscreen.png ├── FeatureDetection ├── en.lproj │ ├── InfoPlist.strings │ └── Credits.rtf ├── Example Images │ ├── lax-sample.png │ ├── flag-kernel.png │ ├── plane-kernel.png │ ├── shuttle-sample.jpeg │ └── shuttle-sample.png ├── FeatureDetection-Prefix.pch ├── main.m ├── AppDelegate.h ├── FeatureDetection-Info.plist └── AppDelegate.m ├── FeatureDetectionTests ├── en.lproj │ └── InfoPlist.strings ├── FeatureDetectionTests.h ├── FeatureDetectionTests.m └── FeatureDetectionTests-Info.plist ├── iOSFeatureDetection ├── en.lproj │ └── InfoPlist.strings ├── iOSAppDelegate.h ├── iOSFeatureDetection-Prefix.pch ├── main.m ├── iOSFeatureDetection-Info.plist └── iOSAppDelegate.m ├── FeatureDetection.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── nickoneill.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── LAFeatureDetection.h ├── CGImageToBitmap.h ├── CGImageToBitmap.m ├── Readme.md └── LAFeatureDetection.m /iosscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/iosscreen.png -------------------------------------------------------------------------------- /osxscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/osxscreen.png -------------------------------------------------------------------------------- /FeatureDetection/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /FeatureDetectionTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /iOSFeatureDetection/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /FeatureDetection/Example Images/lax-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/FeatureDetection/Example Images/lax-sample.png -------------------------------------------------------------------------------- /FeatureDetection/Example Images/flag-kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/FeatureDetection/Example Images/flag-kernel.png -------------------------------------------------------------------------------- /FeatureDetection/Example Images/plane-kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/FeatureDetection/Example Images/plane-kernel.png -------------------------------------------------------------------------------- /FeatureDetection/Example Images/shuttle-sample.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/FeatureDetection/Example Images/shuttle-sample.jpeg -------------------------------------------------------------------------------- /FeatureDetection/Example Images/shuttle-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickoneill/LAFeatureDetection/HEAD/FeatureDetection/Example Images/shuttle-sample.png -------------------------------------------------------------------------------- /FeatureDetection/FeatureDetection-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'FeatureDetection' target in the 'FeatureDetection' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /FeatureDetection.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FeatureDetection/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FeatureDetection 4 | // 5 | // Created by Nick O'Neill on 4/15/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /FeatureDetectionTests/FeatureDetectionTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // FastImageCorrelationTests.h 3 | // FastImageCorrelationTests 4 | // 5 | // Created by Nick O'Neill on 4/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FastImageCorrelationTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /iOSFeatureDetection/iOSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iOSFeatureDetection 4 | // 5 | // Created by Nick O'Neill on 6/1/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /iOSFeatureDetection/iOSFeatureDetection-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'iOSFeatureDetection' target in the 'iOSFeatureDetection' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /iOSFeatureDetection/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOSFeatureDetection 4 | // 5 | // Created by Nick O'Neill on 6/1/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "iOSAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FeatureDetection/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // FeatureDetection 4 | // 5 | // Created by Nick O'Neill on 4/15/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | @property (assign) IBOutlet NSView *view; 15 | @property (assign) IBOutlet NSScrollView *scrollContent; 16 | 17 | - (void)showImage:(float*)imageArray forWidth:(int)width andHeight:(int)height; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /FeatureDetection/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /FeatureDetectionTests/FeatureDetectionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FastImageCorrelationTests.m 3 | // FastImageCorrelationTests 4 | // 5 | // Created by Nick O'Neill on 4/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "FastImageCorrelationTests.h" 10 | 11 | @implementation FastImageCorrelationTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | STFail(@"Unit tests are not implemented yet in FastImageCorrelationTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /LAFeatureDetection.h: -------------------------------------------------------------------------------- 1 | // 2 | // LAFeatureDetection.h 3 | // 4 | // Created by Nick O'Neill on 4/15/12. 5 | // Copyright (c) 2012 Launch Apps. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #if !(TARGET_IPHONE_SIMULATOR) && !(TARGET_OS_IPHONE) 11 | #define valueWithCGPoint valueWithPoint 12 | #endif 13 | 14 | @interface LAFeatureDetection : NSObject 15 | 16 | @property (nonatomic, weak) id delegate; 17 | // tweak this value if you're getting too many points back 18 | @property (nonatomic) float relatedPointThreshold; 19 | 20 | + (NSArray*)probablePointsForImage:(CGImageRef)kernel inImage:(CGImageRef)sample; 21 | - (NSArray*)probablePointsForImage:(CGImageRef)kernel inImage:(CGImageRef)sample; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /FeatureDetectionTests/FeatureDetectionTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | name.nickoneill.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /FeatureDetection.xcodeproj/xcuserdata/nickoneill.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FeatureDetection.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | iOSFeatureDetection.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | D04A3730153B7E14005621CF 21 | 22 | primary 23 | 24 | 25 | D04A3751153B7E14005621CF 26 | 27 | primary 28 | 29 | 30 | D0ABE8061579AF1400A84A96 31 | 32 | primary 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /FeatureDetection/FeatureDetection-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | name.nickoneill.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSApplicationCategoryType 26 | public.app-category.developer-tools 27 | LSMinimumSystemVersion 28 | ${MACOSX_DEPLOYMENT_TARGET} 29 | NSHumanReadableCopyright 30 | Copyright © 2012 Launch Apps. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /iOSFeatureDetection/iOSFeatureDetection-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | name.nickoneill.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CGImageToBitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * This file based on earlier code by: 5 | * 6 | * Copyright (c) 2011 Paul Solt, PaulSolt@gmail.com 7 | * Modifications Copyright (c) 2011 Joe Osborn, josborn@universalhappymaker.com 8 | * https://github.com/JoeOsborn/UIImage-Conversion 9 | * 10 | * Additional modifications for Feature Recognition by Nick O'Neill, nick.oneill@gmail.com 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | * 30 | */ 31 | 32 | #import 33 | 34 | @interface CGImageToBitmap : NSObject 35 | 36 | + (unsigned char *)bitmapARGB8888FromCGImage:(CGImageRef)image; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CGImageToBitmap.m: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * This file based on earlier code by: 5 | * 6 | * Copyright (c) 2011 Paul Solt, PaulSolt@gmail.com 7 | * Modifications Copyright (c) 2011 Joe Osborn, josborn@universalhappymaker.com 8 | * https://github.com/JoeOsborn/UIImage-Conversion 9 | * 10 | * Additional modifications for Feature Recognition by Nick O'Neill, nick.oneill@gmail.com 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | * 30 | */ 31 | 32 | #import "CGImageToBitmap.h" 33 | 34 | @implementation CGImageToBitmap 35 | 36 | + (unsigned char *)bitmapARGB8888FromCGImage:(CGImageRef)image 37 | { 38 | 39 | CGContextRef context = NULL; 40 | CGColorSpaceRef colorSpace; 41 | uint8_t *bitmapData; 42 | 43 | size_t bitsPerPixel = 32; 44 | size_t bitsPerComponent = 8; 45 | size_t bytesPerPixel = bitsPerPixel / bitsPerComponent; 46 | 47 | size_t width = CGImageGetWidth(image); 48 | size_t height = CGImageGetHeight(image); 49 | 50 | size_t bytesPerRow = width * bytesPerPixel; 51 | size_t bufferLength = bytesPerRow * height; 52 | 53 | colorSpace = CGColorSpaceCreateDeviceRGB(); 54 | 55 | if(!colorSpace) { 56 | NSLog(@"Error allocating color space RGB\n"); 57 | return NULL; 58 | } 59 | 60 | // Allocate memory for image data 61 | bitmapData = (uint8_t *)calloc(bufferLength, sizeof(uint8_t)); 62 | 63 | if(!bitmapData) { 64 | NSLog(@"Error allocating memory for bitmap\n"); 65 | CGColorSpaceRelease(colorSpace); 66 | return NULL; 67 | } 68 | 69 | //Changed this to ARGB8888 70 | CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst; 71 | 72 | //Create bitmap context with this memory block (which we still own, 73 | //although we will transfer ownership to the caller on return). 74 | context = CGBitmapContextCreate(bitmapData, 75 | width, 76 | height, 77 | bitsPerComponent, 78 | bytesPerRow, 79 | colorSpace, 80 | bitmapInfo); // RGBA 81 | 82 | if(!context) { 83 | free(bitmapData); 84 | NSLog(@"Bitmap context not created"); 85 | } 86 | 87 | CGColorSpaceRelease(colorSpace); 88 | 89 | if(!context) { 90 | return NULL; 91 | } 92 | 93 | CGRect rect = CGRectMake(0, 0, width, height); 94 | 95 | // Draw image into the context to get the raw image data 96 | CGContextDrawImage(context, rect, image); 97 | CGContextRelease(context); 98 | 99 | return bitmapData; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /FeatureDetection/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // FeatureDetection 4 | // 5 | // Created by Nick O'Neill on 4/15/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "LAFeatureDetection.h" 11 | #import "CGImageToBitmap.h" 12 | 13 | @implementation AppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize view, scrollContent; 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 19 | { 20 | NSImage *sample = [[NSImage alloc] initByReferencingFile:[[NSBundle mainBundle] pathForResource:@"lax-sample" ofType:@"png"]]; 21 | NSImage *kernel = [[NSImage alloc] initByReferencingFile:[[NSBundle mainBundle] pathForResource:@"plane-kernel" ofType:@"png"]]; 22 | 23 | CGImageSourceRef samplesource = CGImageSourceCreateWithData((__bridge CFDataRef)[sample TIFFRepresentation], nil); 24 | CGImageRef sampleref = CGImageSourceCreateImageAtIndex(samplesource, 0, nil); 25 | 26 | CGImageSourceRef kernelsource = CGImageSourceCreateWithData((__bridge CFDataRef)[kernel TIFFRepresentation], nil); 27 | CGImageRef kernelref = CGImageSourceCreateImageAtIndex(kernelsource, 0, nil); 28 | 29 | NSArray *points = [[[LAFeatureDetection alloc] init] probablePointsForImage:kernelref inImage:sampleref]; 30 | 31 | if (points != nil) { 32 | NSBitmapImageRep *sampleRep = [NSBitmapImageRep imageRepWithData:[sample TIFFRepresentation]]; 33 | 34 | if ([points count] > 8) { 35 | NSLog(@"more than 8 possible points is an unlikely match if looking for a single target"); 36 | } 37 | 38 | // points here are possible locations of the bottom right corner of the kernel 39 | for (int i = 0; i < [points count]; i++) { 40 | CGPoint point = [[points objectAtIndex:i] pointValue]; 41 | NSLog(@"matched point: %f,%f",point.x,point.y); 42 | 43 | NSColor *red = [NSColor colorWithDeviceRed:1 green:0 blue:0 alpha:1]; 44 | for (int i = 0; i < kernel.size.width+1; i++) { 45 | [sampleRep setColor:red atX:(point.x-i) y:point.y]; 46 | [sampleRep setColor:red atX:(point.x-i) y:(point.y-kernel.size.height)]; 47 | } 48 | for (int i = 0; i < kernel.size.height; i++) { 49 | [sampleRep setColor:red atX:point.x y:(point.y-i)]; 50 | [sampleRep setColor:red atX:(point.x-kernel.size.width) y:(point.y-i)]; 51 | } 52 | } 53 | 54 | // for demonstration purposes, surround the kernel with a red box 55 | 56 | NSImage *visual = [[NSImage alloc] initWithCGImage:[sampleRep CGImage] size:[sample size]]; 57 | NSImageView *iv = [[NSImageView alloc] initWithFrame:CGRectMake(0, 0, sample.size.width, sample.size.height)]; 58 | [iv setImage:visual]; 59 | 60 | [scrollContent setDocumentView:iv]; 61 | } 62 | } 63 | 64 | // for debugging results 65 | - (void)showImage:(float*)imageArray forWidth:(int)width andHeight:(int)height 66 | { 67 | NSImage *sample = [[NSImage alloc] initByReferencingFile:[[NSBundle mainBundle] pathForResource:@"shuttle-sample" ofType:@"png"]]; 68 | NSBitmapImageRep *imrep = [NSBitmapImageRep imageRepWithData:[sample TIFFRepresentation]]; 69 | 70 | for (int i = 0; i < height; i++) { 71 | for (int j = 0; j < width; j++) { 72 | int idx = ((width*i)+j); 73 | 74 | NSColor *color; 75 | 76 | color = [NSColor colorWithDeviceRed:imageArray[idx]/255 green:imageArray[idx]/255 blue:imageArray[idx]/255 alpha:1]; 77 | 78 | [imrep setColor:color atX:j y:i]; 79 | } 80 | } 81 | 82 | NSImage *img = [[NSImage alloc] initWithCGImage:[imrep CGImage] size:NSMakeSize(width, height)]; 83 | NSImageView *iv = [[NSImageView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 84 | [iv setImage:img]; 85 | 86 | [scrollContent setDocumentView:iv]; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /iOSFeatureDetection/iOSAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iOSFeatureDetection 4 | // 5 | // Created by Nick O'Neill on 6/1/12. 6 | // Copyright (c) 2012 Launch Apps. All rights reserved. 7 | // 8 | 9 | #import "iOSAppDelegate.h" 10 | #import "LAFeatureDetection.h" 11 | 12 | @implementation AppDelegate 13 | 14 | @synthesize window = _window; 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | self.window.backgroundColor = [UIColor whiteColor]; 21 | [self.window makeKeyAndVisible]; 22 | 23 | UIImage *sample = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"shuttle-sample" ofType:@"png"]]; 24 | 25 | UIImage *kernel = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"flag-kernel" ofType:@"png"]]; 26 | 27 | NSArray *points = [LAFeatureDetection probablePointsForImage:[kernel CGImage] inImage:[sample CGImage]]; 28 | 29 | UIGraphicsBeginImageContext(sample.size); 30 | [sample drawAtPoint:CGPointZero]; 31 | 32 | if (points != nil) { 33 | NSLog(@"points: %@",points); 34 | 35 | for (int i = 0; i < [points count]; i++) { 36 | CGPoint point = [[points objectAtIndex:i] CGPointValue]; 37 | 38 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 39 | [[UIColor redColor] setStroke]; 40 | CGRect pointRect = CGRectMake(point.x-kernel.size.width, point.y-kernel.size.height, kernel.size.width, kernel.size.height); 41 | CGContextStrokeRect(ctx, pointRect); 42 | } 43 | } 44 | 45 | UIImage *resultSample = UIGraphicsGetImageFromCurrentImageContext(); 46 | UIGraphicsEndImageContext(); 47 | 48 | UIImageView *scrollimage = [[UIImageView alloc] initWithImage:resultSample]; 49 | 50 | UIViewController *vc = [[UIViewController alloc] init]; 51 | UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:self.window.frame]; 52 | 53 | [scroll addSubview:scrollimage]; 54 | [scroll setContentSize:sample.size]; 55 | 56 | [vc setView:scroll]; 57 | 58 | [self.window setRootViewController:vc]; 59 | 60 | return YES; 61 | } 62 | 63 | - (void)applicationWillResignActive:(UIApplication *)application 64 | { 65 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 66 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 67 | } 68 | 69 | - (void)applicationDidEnterBackground:(UIApplication *)application 70 | { 71 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 72 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 73 | } 74 | 75 | - (void)applicationWillEnterForeground:(UIApplication *)application 76 | { 77 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 78 | } 79 | 80 | - (void)applicationDidBecomeActive:(UIApplication *)application 81 | { 82 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 83 | } 84 | 85 | - (void)applicationWillTerminate:(UIApplication *)application 86 | { 87 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | This library is designed to use the accelerated vDSP functions for OSX/iOS to perform image correlation by convolution. In short, it allows you to find the location of subimages (or like forms) within a larger sample image without iterating through every pixel in the image. This approach is particularly useful for large sample images, but because of the speed of the Accelerate framework it is applicable to much smaller sizes as well. 2 | 3 | Searching for [this flag](https://github.com/nickoneill/LAFeatureDetection/raw/master/FeatureDetection/Example%20Images/flag-kernel.png) inside of [this image of Discovery](https://github.com/nickoneill/LAFeatureDetection/raw/master/FeatureDetection/Example%20Images/shuttle-sample.png) gives us this visualized result on iOS: 4 | ![Detecting a flag on iOS](https://github.com/nickoneill/LAFeatureDetection/raw/master/iosscreen.png) 5 | 6 | Searching for [this plane](https://github.com/nickoneill/LAFeatureDetection/raw/master/FeatureDetection/Example%20Images/plane-kernel.png) inside of [this aerial image of LAX](https://github.com/nickoneill/LAFeatureDetection/raw/master/FeatureDetection/Example%20Images/lax-sample.png) gives us this visualized result on OSX (note the thicker outline - this is actually a grouping of three high-probability points returned from the detector): 7 | ![Detecting a plane on OS X](https://github.com/nickoneill/LAFeatureDetection/raw/master/osxscreen.png) 8 | 9 | ### Correlation by convolution ### 10 | 11 | Iterative methods for finding an image within another image are accurate but slow. Fortunately, most image processing applications care more about speed than pixel-level accuracy. In fact, the simplest iterative method matches exact pixel values which requires that you know the exact pixel values you're looking for. Convolutions via fourier transform provide an interesting alternative solution. 12 | 13 | Convolution is an image processing term describing a fourier transform of two images, point multiplying the two transforms and performing an inverse fourier transform on the result. It effectively applies a "filter" to the entire sample image and is the basis for the coloring effects found in Photo Booth and plenty of image filters in Photoshop. 14 | 15 | Conveniently, if we convolve some exact subimage with its parent image, the result matrix has a point of maximum intensity that describes the location of the subimage in the parent. Applying an edge-detection or other appropriate filter in advance gives a general solution to finding things that "look like" a subimage - the fuzziness we often desire in image processing. 16 | 17 | The fast fourier transform is often used in digital signal processing and a ton of work has been done to streamline the vector computations used for this purpose. The OSX/iOS Accelerate framework has some of the fastest fourier transforms available but it can be a bit obtuse to understand and use because of the technical steps taken to achieve such speed. 18 | 19 | The goal of this library is to allow anyone with basic Objective-C knowledge to run fast convolutions and find features within image data. 20 | 21 | A few limitations you should be aware of: this method is good at finding features that are similar in size and orientation. Rotated or scaled feature identification requires multiple trips through the FFT to search for each modification. 22 | 23 | ### Using the library ### 24 | 25 | Most users will probably be satisfied by using the default class method `probablePointsForImage:(CGImageRef)kernel inImage:(CGImageRef)sample` which makes some assumptions and returns an array of the most likely locations of the kernel image in the sample (likeliest first). The points returned are the likely location of the bottom right corner of the kernel. 26 | 27 | There are different ways to get a CGImage on iOS and OSX, please check the example code for the differences. 28 | 29 | ### Contributions ### 30 | 31 | I'm open to suggestions or pull requests. Or you can just track progress on [Trello](https://trello.com/board/image-fft-correlation/4f74e20243c8990d7528b36a). 32 | 33 | ### Credits ### 34 | 35 | Many thanks to the Apple Scitech list for answering all sorts of implementation questions, and Thijs Hosman for introducing me to the concept. 36 | 37 | Test images procured from the [USC Signal and Image Processing database](http://sipi.usc.edu/database/database.php) and NASA. -------------------------------------------------------------------------------- /LAFeatureDetection.m: -------------------------------------------------------------------------------- 1 | // 2 | // LAFeatureDetection.m 3 | // 4 | // Created by Nick O'Neill on 4/15/12. 5 | // Copyright (c) 2012 Launch Apps. All rights reserved. 6 | // 7 | 8 | #import "LAFeatureDetection.h" 9 | #import "CGImageToBitmap.h" 10 | 11 | #include 12 | 13 | @implementation LAFeatureDetection 14 | 15 | @synthesize delegate; 16 | 17 | @synthesize relatedPointThreshold; 18 | 19 | - (id)init 20 | { 21 | if (self = [super init]) { 22 | relatedPointThreshold = 0.95; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | + (NSArray*)probablePointsForImage:(CGImageRef)kernel inImage:(CGImageRef)sample 29 | { 30 | LAFeatureDetection *detector = [[LAFeatureDetection alloc] init]; 31 | 32 | return [detector probablePointsForImage:kernel inImage:sample]; 33 | } 34 | 35 | - (NSArray*)probablePointsForImage:(CGImageRef)kernel inImage:(CGImageRef)sample 36 | { 37 | unsigned char *samplebitmap = [CGImageToBitmap bitmapARGB8888FromCGImage:sample]; 38 | 39 | int sampleWidth = CGImageGetWidth(sample); 40 | int sampleHeight = CGImageGetHeight(sample); 41 | 42 | // temp data for edge detection 43 | float *tempSample = malloc(sampleWidth*sampleHeight * sizeof(float)); 44 | 45 | // transfer bitmap in ARGB8888 to planar grayscale 46 | for (int i = 0; i < sampleHeight; i++) { 47 | for (int j = 0; j < sampleWidth; j++) { 48 | int idx = ((sampleWidth*i)+j)*4; 49 | unsigned char gray; 50 | 51 | gray = (float)(samplebitmap[idx+1]*0.2989 + samplebitmap[idx+2]*0.5870 + samplebitmap[idx+3]*0.1140); 52 | 53 | tempSample[(sampleWidth*i)+j] = (float)gray; 54 | } 55 | } 56 | 57 | tempSample = [self applySobel:tempSample forWidth:sampleWidth andHeight:sampleHeight]; 58 | 59 | // [delegate showImage:tempSample forWidth:sampleWidth andHeight:sampleHeight]; 60 | 61 | unsigned char *kernelbitmap = [CGImageToBitmap bitmapARGB8888FromCGImage:kernel]; 62 | 63 | int kernelWidth = CGImageGetWidth(kernel); 64 | int kernelHeight = CGImageGetHeight(kernel); 65 | 66 | // temp data for edge detection 67 | float *tempKernel = malloc((kernelWidth*kernelHeight) * sizeof(float)); 68 | 69 | // transfer bitmap in ARGB8888 to planar grayscale 70 | for (int i = 0; i < kernelHeight; i++) { 71 | for (int j = 0; j < kernelWidth; j++) { 72 | // inverting i and j for the kernel as a quick way to rotate 180 73 | int idx = ((kernelWidth*(kernelHeight-i))+(kernelWidth-j))*4; 74 | unsigned char gray; 75 | 76 | gray = (kernelbitmap[idx+1]*0.2989 + kernelbitmap[idx+2]*0.5870 + kernelbitmap[idx+3]*0.1140); 77 | 78 | tempKernel[(kernelWidth*i)+j] = (float)gray; 79 | } 80 | } 81 | 82 | tempKernel = [self applySobel:tempKernel forWidth:kernelWidth andHeight:kernelHeight]; 83 | 84 | // [delegate showImage:tempKernel forWidth:kernelWidth andHeight:kernelHeight]; 85 | 86 | // build necessary things for fft 87 | COMPLEX_SPLIT sampleComplex,kernelComplex,resultComplex; 88 | FFTSetup setupReal; 89 | uint32_t log2n; 90 | uint32_t n,nOver2,nnOver2; 91 | float *sampleArray,*kernelArray,*resultArray; 92 | float scale; 93 | 94 | NSLog(@"sample size is: %dx%d",sampleWidth,sampleHeight); 95 | NSLog(@"kernel size is: %dx%d",kernelWidth,kernelHeight); 96 | int max_dimension = MAX(MAX(MAX(sampleHeight, sampleWidth), kernelHeight), kernelWidth); 97 | NSLog(@"max dimension is: %d",max_dimension); 98 | 99 | // Check for images that are tiny or big (more big sizes should be easily supported) 100 | if (max_dimension <= 128) { 101 | NSLog(@"Use iteration for sample images smaller than 128"); 102 | return nil; 103 | } 104 | if (max_dimension > 8192) { 105 | NSLog(@"Large image! Not quite supported yet."); 106 | return nil; 107 | } 108 | 109 | if (max_dimension > 128 && max_dimension <= 256) { 110 | log2n = 8; 111 | } 112 | else if (max_dimension > 256 && max_dimension <= 512) { 113 | log2n = 9; 114 | } 115 | else if (max_dimension > 512 && max_dimension <= 1024) { 116 | log2n = 10; 117 | } 118 | else if (max_dimension > 1024 && max_dimension <= 2048) { 119 | log2n = 11; 120 | } 121 | else if (max_dimension > 2048 && max_dimension <= 4096) { 122 | log2n = 12; 123 | } 124 | else if (max_dimension > 4096 && max_dimension <= 8192) { 125 | log2n = 13; 126 | } 127 | 128 | n = (1 << log2n); 129 | nOver2 = n / 2; 130 | nnOver2 = (n*n) / 2; 131 | 132 | // allocate memory 133 | sampleComplex.realp = (float *) malloc(nnOver2 * sizeof(float)); 134 | sampleComplex.imagp = (float *) malloc(nnOver2 * sizeof(float)); 135 | kernelComplex.realp = (float *) malloc(nnOver2 * sizeof(float)); 136 | kernelComplex.imagp = (float *) malloc(nnOver2 * sizeof(float)); 137 | resultComplex.realp = (float *) malloc(nnOver2 * sizeof(float)); 138 | resultComplex.imagp = (float *) malloc(nnOver2 * sizeof(float)); 139 | 140 | sampleArray = (float *)malloc((n*n) * sizeof(float)); 141 | kernelArray = (float *)malloc((n*n) * sizeof(float)); 142 | resultArray = (float *)malloc((n*n) * sizeof(float)); 143 | 144 | // expand images to power of two size, zero all pixels that are outside of data 145 | for (int i = 0; i < n; i++) { 146 | for (int j = 0; j < n; j++) { 147 | if (i < sampleHeight && j < sampleWidth) { 148 | sampleArray[(n*i)+j] = tempSample[(sampleWidth*i)+j]; 149 | } else { 150 | sampleArray[(n*i)+j] = 0.0; 151 | } 152 | 153 | if (i < kernelHeight && j < kernelWidth) { 154 | kernelArray[(n*i)+j] = tempKernel[(kernelWidth*i)+j]; 155 | } else { 156 | kernelArray[(n*i)+j] = 0.0; 157 | } 158 | } 159 | } 160 | 161 | free(tempSample); 162 | free(tempKernel); 163 | 164 | // transfer pixel arrays to split complex format 165 | vDSP_ctoz((COMPLEX *)sampleArray, 2, &sampleComplex, 1, nnOver2); 166 | vDSP_ctoz((COMPLEX *)kernelArray, 2, &kernelComplex, 1, nnOver2); 167 | 168 | // create special fftsetup for our particular size 169 | setupReal = vDSP_create_fftsetup(log2n, kFFTRadix2); 170 | 171 | // run 2d accelerated fft on both complex arrays 172 | vDSP_fft2d_zrip(setupReal, &sampleComplex, 1, 0, log2n, log2n, kFFTDirection_Forward); 173 | vDSP_fft2d_zrip(setupReal, &kernelComplex, 1, 0, log2n, log2n, kFFTDirection_Forward); 174 | 175 | // tricky part: once the complex split value has been run through fft, it's in a very particular format 176 | // which is defined here: http://bit.ly/JHnC0q 177 | // for our multiplication to work properly, we have to multiply the real and imaginary parts of the 178 | // 0 column and real and imaginary parts of 0,0 and 1,0 seperately 179 | 180 | // first, multiply everything which works for most of the data 181 | vDSP_zvmul(&sampleComplex, 1, &kernelComplex, 1, &resultComplex, 1, (n/2)*(n/2), 1); 182 | 183 | // move the real column to new split complex arrays for fast multiplication 184 | DSPSplitComplex sampleRealColumn; 185 | sampleRealColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 186 | sampleRealColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 187 | DSPSplitComplex kernelRealColumn; 188 | kernelRealColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 189 | kernelRealColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 190 | DSPSplitComplex resultRealColumn; 191 | resultRealColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 192 | resultRealColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 193 | 194 | for (int i=0; i < ((nOver2-2)/2); i++) { 195 | int j = (i*2)+2; 196 | 197 | sampleRealColumn.realp[i] = sampleComplex.realp[nOver2*j]; 198 | sampleRealColumn.imagp[i] = sampleComplex.realp[nOver2*(j+1)]; 199 | 200 | kernelRealColumn.realp[i] = kernelComplex.realp[nOver2*j]; 201 | kernelRealColumn.imagp[i] = kernelComplex.realp[nOver2*(j+1)]; 202 | } 203 | 204 | vDSP_zvmul(&sampleRealColumn, 1, &kernelRealColumn, 1, &resultRealColumn, 1, ((nOver2-2)/2), 1); 205 | 206 | for (int i=0; i < ((nOver2-2)/2); i++) { 207 | int j = (i*2)+2; 208 | 209 | resultComplex.realp[nOver2*j] = resultRealColumn.realp[i]; 210 | resultComplex.realp[nOver2*(j+1)] = resultRealColumn.imagp[i]; 211 | } 212 | 213 | // move the imag column to new split complex arrays for fast multiplication 214 | DSPSplitComplex sampleImagColumn; 215 | sampleImagColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 216 | sampleImagColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 217 | DSPSplitComplex kernelImagColumn; 218 | kernelImagColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 219 | kernelImagColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 220 | DSPSplitComplex resultImagColumn; 221 | resultImagColumn.realp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 222 | resultImagColumn.imagp = (float *) malloc(((nOver2-2)/2) * sizeof(float)); 223 | 224 | for (int i=0; i < ((nOver2-2)/2); i++) { 225 | int j = (i*2)+2; 226 | 227 | sampleImagColumn.realp[i] = sampleComplex.imagp[nOver2*j]; 228 | sampleImagColumn.imagp[i] = sampleComplex.imagp[nOver2*(j+1)]; 229 | 230 | kernelImagColumn.realp[i] = kernelComplex.imagp[nOver2*j]; 231 | kernelImagColumn.imagp[i] = kernelComplex.imagp[nOver2*(j+1)]; 232 | } 233 | 234 | vDSP_zvmul(&sampleImagColumn, 1, &kernelImagColumn, 1, &resultImagColumn, 1, ((nOver2-2)/2), 1); 235 | 236 | for (int i=0; i < ((nOver2-2)/2); i++) { 237 | int j = (i*2)+2; 238 | 239 | resultComplex.imagp[nOver2*j] = resultImagColumn.realp[i]; 240 | resultComplex.imagp[nOver2*(j+1)] = resultImagColumn.imagp[i]; 241 | } 242 | 243 | // multiply our four real elements normally 244 | resultComplex.realp[0] = sampleComplex.realp[0] * kernelComplex.realp[0]; 245 | resultComplex.imagp[0] = sampleComplex.imagp[0] * kernelComplex.imagp[0]; 246 | resultComplex.realp[(n/2)] = sampleComplex.realp[(n/2)] * kernelComplex.realp[(n/2)]; 247 | resultComplex.imagp[(n/2)] = sampleComplex.imagp[(n/2)] * kernelComplex.imagp[(n/2)]; 248 | 249 | // invert the fft on our result 250 | vDSP_fft2d_zrip(setupReal, &resultComplex, 1, 0, log2n, log2n, kFFTDirection_Inverse); 251 | 252 | // vdsp scales values when computing fft and inverse fft, we need to unscale them 253 | scale = (float) 1.0 / ((float)n * (float)n * (float)n); 254 | vDSP_vsmul(resultComplex.realp, 1, &scale, resultComplex.realp, 1, nnOver2); 255 | vDSP_vsmul(resultComplex.imagp, 1, &scale, resultComplex.imagp, 1, nnOver2); 256 | 257 | // move out of split complex format into a regular array 258 | vDSP_ztoc(&resultComplex, 1, (COMPLEX *)resultArray, 2, nnOver2); 259 | 260 | // determine max value location 261 | NSMutableArray *points = [NSMutableArray array]; 262 | float max,min = 0; 263 | int maxindex,limit = 0; 264 | for (int i = 0; i < n*n; i++) { 265 | if (resultArray[i] >= max) { 266 | max = resultArray[i]; 267 | maxindex = i; 268 | } 269 | if (resultArray[i] < min) { 270 | min = resultArray[i]; 271 | } 272 | } 273 | 274 | // determine valid points over threshold 275 | limit = floor(max*relatedPointThreshold); 276 | for (int i = 0; i < n*n; i++) { 277 | if (resultArray[i] >= limit) { 278 | int row = floor(i/n); 279 | int col = i-(row*n); 280 | 281 | [points addObject:[NSValue valueWithCGPoint:CGPointMake(col, row)]]; 282 | } 283 | } 284 | 285 | // for debugging the result 286 | // int diff = max-min; 287 | // for (int i = 0; i < n*n; i++) { 288 | // resultArray[i] = ((resultArray[i]-min)/diff)*255; 289 | // } 290 | // [delegate showImage:resultArray]; 291 | 292 | // free malloc'd memory 293 | vDSP_destroy_fftsetup(setupReal); 294 | free(sampleComplex.realp); 295 | free(sampleComplex.imagp); 296 | free(kernelComplex.realp); 297 | free(kernelComplex.imagp); 298 | free(resultComplex.realp); 299 | free(resultComplex.imagp); 300 | free(sampleArray); 301 | free(kernelArray); 302 | free(resultArray); 303 | free(sampleRealColumn.realp); 304 | free(sampleRealColumn.imagp); 305 | free(kernelRealColumn.realp); 306 | free(kernelRealColumn.imagp); 307 | free(resultRealColumn.realp); 308 | free(resultRealColumn.imagp); 309 | free(sampleImagColumn.realp); 310 | free(sampleImagColumn.imagp); 311 | free(kernelImagColumn.realp); 312 | free(kernelImagColumn.imagp); 313 | free(resultImagColumn.realp); 314 | free(resultImagColumn.imagp); 315 | 316 | return points; 317 | } 318 | 319 | - (float*)applySobel:(float*)imageArray forWidth:(int)width andHeight:(int)height 320 | { 321 | // sobel is a simple edge detection filter, good for images with some contrast 322 | float xKernel[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; 323 | float yKernel[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; 324 | 325 | // background estimation by averaging values at midpoints for each edge 326 | Pixel_F bgColor = (imageArray[width*(height/2)]+imageArray[(width*(height/2))-1]+imageArray[width/2]+imageArray[(width*height)-(width/2)])/4; 327 | 328 | // NSLog(@"bgcolor: %f",bgColor); 329 | 330 | vImage_Buffer buf; 331 | buf.data = imageArray; 332 | buf.height = height; 333 | buf.width = width; 334 | buf.rowBytes = width*sizeof(float); 335 | 336 | vImage_Buffer xdest; 337 | xdest.data = malloc(width*height * sizeof(float)); 338 | xdest.height = height; 339 | xdest.width = width; 340 | xdest.rowBytes = width*sizeof(float); 341 | 342 | vImage_Buffer ydest; 343 | ydest.data = malloc(width*height * sizeof(float)); 344 | ydest.height = height; 345 | ydest.width = width; 346 | ydest.rowBytes = width*sizeof(float); 347 | 348 | // convolve with each kernel which estimates the gradient in each direction 349 | vImageConvolve_PlanarF(&buf, &xdest, nil, 0, 0, xKernel, 3, 3, bgColor, kvImageBackgroundColorFill); 350 | vImageConvolve_PlanarF(&buf, &ydest, nil, 0, 0, yKernel, 3, 3, bgColor, kvImageBackgroundColorFill); 351 | 352 | float *xtemp = xdest.data; 353 | float *ytemp = ydest.data; 354 | for (int i = 0; i < height; i++) { 355 | for (int j = 0; j < width; j++) { 356 | // calculatew magnitude of both vertical and horizontal directions 357 | imageArray[(width*i)+j] = sqrtf(powf(xtemp[(width*i)+j],2)+powf(ytemp[(width*i)+j],2)); 358 | } 359 | } 360 | 361 | free(xdest.data); 362 | free(ydest.data); 363 | 364 | return imageArray; 365 | } 366 | 367 | @end 368 | -------------------------------------------------------------------------------- /FeatureDetection.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D0090942157DB656004981B8 /* CGImageToBitmap.m in Sources */ = {isa = PBXBuildFile; fileRef = D0090941157DB656004981B8 /* CGImageToBitmap.m */; }; 11 | D04A3736153B7E14005621CF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04A3735153B7E14005621CF /* Cocoa.framework */; }; 12 | D04A3740153B7E14005621CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04A373E153B7E14005621CF /* InfoPlist.strings */; }; 13 | D04A3742153B7E14005621CF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D04A3741153B7E14005621CF /* main.m */; }; 14 | D04A3749153B7E14005621CF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D04A3748153B7E14005621CF /* AppDelegate.m */; }; 15 | D04A374C153B7E14005621CF /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D04A374A153B7E14005621CF /* MainMenu.xib */; }; 16 | D04A3754153B7E14005621CF /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04A3753153B7E14005621CF /* SenTestingKit.framework */; }; 17 | D04A3755153B7E14005621CF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04A3735153B7E14005621CF /* Cocoa.framework */; }; 18 | D04A375D153B7E14005621CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04A375B153B7E14005621CF /* InfoPlist.strings */; }; 19 | D04A3760153B7E14005621CF /* FeatureDetectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D04A375F153B7E14005621CF /* FeatureDetectionTests.m */; }; 20 | D04A376C153B7FF2005621CF /* LAFeatureDetection.m in Sources */ = {isa = PBXBuildFile; fileRef = D04A376B153B7FF2005621CF /* LAFeatureDetection.m */; }; 21 | D05275FC15570BCB00F464CC /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D05275FB15570BCB00F464CC /* Accelerate.framework */; }; 22 | D09034E91587FB1600F971E0 /* flag-kernel.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF3F1583D44900F99148 /* flag-kernel.png */; }; 23 | D09034EA1587FB1600F971E0 /* shuttle-sample.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF421583D44900F99148 /* shuttle-sample.png */; }; 24 | D0A2107B1587CC11002F41F1 /* LAFeatureDetection.m in Sources */ = {isa = PBXBuildFile; fileRef = D04A376B153B7FF2005621CF /* LAFeatureDetection.m */; }; 25 | D0A2107C1587CCCA002F41F1 /* CGImageToBitmap.m in Sources */ = {isa = PBXBuildFile; fileRef = D0090941157DB656004981B8 /* CGImageToBitmap.m */; }; 26 | D0A2107E1587CCEA002F41F1 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0A2107D1587CCEA002F41F1 /* Accelerate.framework */; }; 27 | D0A210801587CD11002F41F1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0A2107F1587CD11002F41F1 /* CoreGraphics.framework */; }; 28 | D0A210811587CD41002F41F1 /* lax-sample.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF401583D44900F99148 /* lax-sample.png */; }; 29 | D0A210821587CD41002F41F1 /* plane-kernel.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF411583D44900F99148 /* plane-kernel.png */; }; 30 | D0ABE8141579AF1400A84A96 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0ABE8121579AF1400A84A96 /* InfoPlist.strings */; }; 31 | D0ABE8161579AF1400A84A96 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D0ABE8151579AF1400A84A96 /* main.m */; }; 32 | D0ABE81A1579AF1400A84A96 /* iOSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0ABE8191579AF1400A84A96 /* iOSAppDelegate.m */; }; 33 | D0C425DD1586929A00DB4EF2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C425DC1586929A00DB4EF2 /* UIKit.framework */; }; 34 | D0FEEF451583D44900F99148 /* flag-kernel.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF3F1583D44900F99148 /* flag-kernel.png */; }; 35 | D0FEEF461583D44900F99148 /* lax-sample.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF401583D44900F99148 /* lax-sample.png */; }; 36 | D0FEEF471583D44900F99148 /* plane-kernel.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF411583D44900F99148 /* plane-kernel.png */; }; 37 | D0FEEF481583D44900F99148 /* shuttle-sample.png in Resources */ = {isa = PBXBuildFile; fileRef = D0FEEF421583D44900F99148 /* shuttle-sample.png */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXContainerItemProxy section */ 41 | D04A3756153B7E14005621CF /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = D04A3728153B7E14005621CF /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = D04A3730153B7E14005621CF; 46 | remoteInfo = FastImageCorrelation; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | D0090940157DB656004981B8 /* CGImageToBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGImageToBitmap.h; sourceTree = SOURCE_ROOT; }; 52 | D0090941157DB656004981B8 /* CGImageToBitmap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGImageToBitmap.m; sourceTree = SOURCE_ROOT; }; 53 | D04A3731153B7E14005621CF /* FeatureDetection.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FeatureDetection.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | D04A3735153B7E14005621CF /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 55 | D04A3738153B7E14005621CF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 56 | D04A3739153B7E14005621CF /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 57 | D04A373A153B7E14005621CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 58 | D04A373D153B7E14005621CF /* FeatureDetection-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FeatureDetection-Info.plist"; sourceTree = ""; }; 59 | D04A373F153B7E14005621CF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | D04A3741153B7E14005621CF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | D04A3743153B7E14005621CF /* FeatureDetection-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FeatureDetection-Prefix.pch"; sourceTree = ""; }; 62 | D04A3747153B7E14005621CF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 63 | D04A3748153B7E14005621CF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 64 | D04A374B153B7E14005621CF /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 65 | D04A3752153B7E14005621CF /* FeatureDetectionTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FeatureDetectionTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | D04A3753153B7E14005621CF /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 67 | D04A375A153B7E14005621CF /* FeatureDetectionTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FeatureDetectionTests-Info.plist"; sourceTree = ""; }; 68 | D04A375C153B7E14005621CF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 69 | D04A375E153B7E14005621CF /* FeatureDetectionTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FeatureDetectionTests.h; sourceTree = ""; }; 70 | D04A375F153B7E14005621CF /* FeatureDetectionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FeatureDetectionTests.m; sourceTree = ""; }; 71 | D04A376A153B7FF2005621CF /* LAFeatureDetection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAFeatureDetection.h; sourceTree = SOURCE_ROOT; }; 72 | D04A376B153B7FF2005621CF /* LAFeatureDetection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAFeatureDetection.m; sourceTree = SOURCE_ROOT; }; 73 | D05275FB15570BCB00F464CC /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 74 | D0A2107D1587CCEA002F41F1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; 75 | D0A2107F1587CD11002F41F1 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; 76 | D0ABE8071579AF1400A84A96 /* iOSFeatureDetection.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSFeatureDetection.app; sourceTree = BUILT_PRODUCTS_DIR; }; 77 | D0ABE8111579AF1400A84A96 /* iOSFeatureDetection-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iOSFeatureDetection-Info.plist"; sourceTree = ""; }; 78 | D0ABE8131579AF1400A84A96 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 79 | D0ABE8151579AF1400A84A96 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 80 | D0ABE8171579AF1400A84A96 /* iOSFeatureDetection-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iOSFeatureDetection-Prefix.pch"; sourceTree = ""; }; 81 | D0ABE8181579AF1400A84A96 /* iOSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iOSAppDelegate.h; sourceTree = ""; }; 82 | D0ABE8191579AF1400A84A96 /* iOSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSAppDelegate.m; sourceTree = ""; }; 83 | D0C425DC1586929A00DB4EF2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 84 | D0FEEF3F1583D44900F99148 /* flag-kernel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "flag-kernel.png"; path = "FeatureDetection/Example Images/flag-kernel.png"; sourceTree = SOURCE_ROOT; }; 85 | D0FEEF401583D44900F99148 /* lax-sample.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "lax-sample.png"; path = "FeatureDetection/Example Images/lax-sample.png"; sourceTree = SOURCE_ROOT; }; 86 | D0FEEF411583D44900F99148 /* plane-kernel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "plane-kernel.png"; path = "FeatureDetection/Example Images/plane-kernel.png"; sourceTree = SOURCE_ROOT; }; 87 | D0FEEF421583D44900F99148 /* shuttle-sample.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "shuttle-sample.png"; path = "FeatureDetection/Example Images/shuttle-sample.png"; sourceTree = SOURCE_ROOT; }; 88 | /* End PBXFileReference section */ 89 | 90 | /* Begin PBXFrameworksBuildPhase section */ 91 | D04A372E153B7E14005621CF /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | D05275FC15570BCB00F464CC /* Accelerate.framework in Frameworks */, 96 | D04A3736153B7E14005621CF /* Cocoa.framework in Frameworks */, 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | D04A374E153B7E14005621CF /* Frameworks */ = { 101 | isa = PBXFrameworksBuildPhase; 102 | buildActionMask = 2147483647; 103 | files = ( 104 | D04A3754153B7E14005621CF /* SenTestingKit.framework in Frameworks */, 105 | D04A3755153B7E14005621CF /* Cocoa.framework in Frameworks */, 106 | ); 107 | runOnlyForDeploymentPostprocessing = 0; 108 | }; 109 | D0ABE8041579AF1400A84A96 /* Frameworks */ = { 110 | isa = PBXFrameworksBuildPhase; 111 | buildActionMask = 2147483647; 112 | files = ( 113 | D0A210801587CD11002F41F1 /* CoreGraphics.framework in Frameworks */, 114 | D0A2107E1587CCEA002F41F1 /* Accelerate.framework in Frameworks */, 115 | D0C425DD1586929A00DB4EF2 /* UIKit.framework in Frameworks */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXFrameworksBuildPhase section */ 120 | 121 | /* Begin PBXGroup section */ 122 | D00AA3AA1541D7AF006586B3 /* Example Images */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | D0FEEF3F1583D44900F99148 /* flag-kernel.png */, 126 | D0FEEF401583D44900F99148 /* lax-sample.png */, 127 | D0FEEF411583D44900F99148 /* plane-kernel.png */, 128 | D0FEEF421583D44900F99148 /* shuttle-sample.png */, 129 | ); 130 | name = "Example Images"; 131 | path = FastImageCorrelation; 132 | sourceTree = ""; 133 | }; 134 | D04A3726153B7E14005621CF = { 135 | isa = PBXGroup; 136 | children = ( 137 | D04A3769153B7FD7005621CF /* LAFeatureDetection */, 138 | D00AA3AA1541D7AF006586B3 /* Example Images */, 139 | D04A373B153B7E14005621CF /* FeatureDetection */, 140 | D0ABE80F1579AF1400A84A96 /* iOSFeatureDetection */, 141 | D04A3758153B7E14005621CF /* FeatureDetectionTests */, 142 | D04A3734153B7E14005621CF /* Frameworks */, 143 | D04A3732153B7E14005621CF /* Products */, 144 | ); 145 | sourceTree = ""; 146 | }; 147 | D04A3732153B7E14005621CF /* Products */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | D04A3731153B7E14005621CF /* FeatureDetection.app */, 151 | D04A3752153B7E14005621CF /* FeatureDetectionTests.octest */, 152 | D0ABE8071579AF1400A84A96 /* iOSFeatureDetection.app */, 153 | ); 154 | name = Products; 155 | sourceTree = ""; 156 | }; 157 | D04A3734153B7E14005621CF /* Frameworks */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | D0A2107F1587CD11002F41F1 /* CoreGraphics.framework */, 161 | D0A2107D1587CCEA002F41F1 /* Accelerate.framework */, 162 | D05275FB15570BCB00F464CC /* Accelerate.framework */, 163 | D04A3735153B7E14005621CF /* Cocoa.framework */, 164 | D04A3753153B7E14005621CF /* SenTestingKit.framework */, 165 | D04A3737153B7E14005621CF /* Other Frameworks */, 166 | ); 167 | name = Frameworks; 168 | sourceTree = ""; 169 | }; 170 | D04A3737153B7E14005621CF /* Other Frameworks */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | D0C425DC1586929A00DB4EF2 /* UIKit.framework */, 174 | D04A3738153B7E14005621CF /* AppKit.framework */, 175 | D04A3739153B7E14005621CF /* CoreData.framework */, 176 | D04A373A153B7E14005621CF /* Foundation.framework */, 177 | ); 178 | name = "Other Frameworks"; 179 | sourceTree = ""; 180 | }; 181 | D04A373B153B7E14005621CF /* FeatureDetection */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | D04A3747153B7E14005621CF /* AppDelegate.h */, 185 | D04A3748153B7E14005621CF /* AppDelegate.m */, 186 | D04A374A153B7E14005621CF /* MainMenu.xib */, 187 | D04A373C153B7E14005621CF /* Supporting Files */, 188 | ); 189 | path = FeatureDetection; 190 | sourceTree = ""; 191 | }; 192 | D04A373C153B7E14005621CF /* Supporting Files */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | D04A373D153B7E14005621CF /* FeatureDetection-Info.plist */, 196 | D04A373E153B7E14005621CF /* InfoPlist.strings */, 197 | D04A3741153B7E14005621CF /* main.m */, 198 | D04A3743153B7E14005621CF /* FeatureDetection-Prefix.pch */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | D04A3758153B7E14005621CF /* FeatureDetectionTests */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | D04A375E153B7E14005621CF /* FeatureDetectionTests.h */, 207 | D04A375F153B7E14005621CF /* FeatureDetectionTests.m */, 208 | D04A3759153B7E14005621CF /* Supporting Files */, 209 | ); 210 | name = FeatureDetectionTests; 211 | path = FastImageCorrelationTests; 212 | sourceTree = ""; 213 | }; 214 | D04A3759153B7E14005621CF /* Supporting Files */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | D04A375A153B7E14005621CF /* FeatureDetectionTests-Info.plist */, 218 | D04A375B153B7E14005621CF /* InfoPlist.strings */, 219 | ); 220 | name = "Supporting Files"; 221 | sourceTree = ""; 222 | }; 223 | D04A3769153B7FD7005621CF /* LAFeatureDetection */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | D04A376A153B7FF2005621CF /* LAFeatureDetection.h */, 227 | D04A376B153B7FF2005621CF /* LAFeatureDetection.m */, 228 | D0090940157DB656004981B8 /* CGImageToBitmap.h */, 229 | D0090941157DB656004981B8 /* CGImageToBitmap.m */, 230 | ); 231 | name = LAFeatureDetection; 232 | path = FastImageCorrelation; 233 | sourceTree = ""; 234 | }; 235 | D0ABE80F1579AF1400A84A96 /* iOSFeatureDetection */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | D0ABE8181579AF1400A84A96 /* iOSAppDelegate.h */, 239 | D0ABE8191579AF1400A84A96 /* iOSAppDelegate.m */, 240 | D0ABE8101579AF1400A84A96 /* Supporting Files */, 241 | ); 242 | path = iOSFeatureDetection; 243 | sourceTree = ""; 244 | }; 245 | D0ABE8101579AF1400A84A96 /* Supporting Files */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | D0ABE8111579AF1400A84A96 /* iOSFeatureDetection-Info.plist */, 249 | D0ABE8121579AF1400A84A96 /* InfoPlist.strings */, 250 | D0ABE8151579AF1400A84A96 /* main.m */, 251 | D0ABE8171579AF1400A84A96 /* iOSFeatureDetection-Prefix.pch */, 252 | ); 253 | name = "Supporting Files"; 254 | sourceTree = ""; 255 | }; 256 | /* End PBXGroup section */ 257 | 258 | /* Begin PBXNativeTarget section */ 259 | D04A3730153B7E14005621CF /* FeatureDetection */ = { 260 | isa = PBXNativeTarget; 261 | buildConfigurationList = D04A3763153B7E14005621CF /* Build configuration list for PBXNativeTarget "FeatureDetection" */; 262 | buildPhases = ( 263 | D04A372D153B7E14005621CF /* Sources */, 264 | D04A372E153B7E14005621CF /* Frameworks */, 265 | D04A372F153B7E14005621CF /* Resources */, 266 | ); 267 | buildRules = ( 268 | ); 269 | dependencies = ( 270 | ); 271 | name = FeatureDetection; 272 | productName = FastImageCorrelation; 273 | productReference = D04A3731153B7E14005621CF /* FeatureDetection.app */; 274 | productType = "com.apple.product-type.application"; 275 | }; 276 | D04A3751153B7E14005621CF /* FeatureDetectionTests */ = { 277 | isa = PBXNativeTarget; 278 | buildConfigurationList = D04A3766153B7E14005621CF /* Build configuration list for PBXNativeTarget "FeatureDetectionTests" */; 279 | buildPhases = ( 280 | D04A374D153B7E14005621CF /* Sources */, 281 | D04A374E153B7E14005621CF /* Frameworks */, 282 | D04A374F153B7E14005621CF /* Resources */, 283 | D04A3750153B7E14005621CF /* ShellScript */, 284 | ); 285 | buildRules = ( 286 | ); 287 | dependencies = ( 288 | D04A3757153B7E14005621CF /* PBXTargetDependency */, 289 | ); 290 | name = FeatureDetectionTests; 291 | productName = FastImageCorrelationTests; 292 | productReference = D04A3752153B7E14005621CF /* FeatureDetectionTests.octest */; 293 | productType = "com.apple.product-type.bundle"; 294 | }; 295 | D0ABE8061579AF1400A84A96 /* iOSFeatureDetection */ = { 296 | isa = PBXNativeTarget; 297 | buildConfigurationList = D0ABE81B1579AF1400A84A96 /* Build configuration list for PBXNativeTarget "iOSFeatureDetection" */; 298 | buildPhases = ( 299 | D0ABE8031579AF1400A84A96 /* Sources */, 300 | D0ABE8041579AF1400A84A96 /* Frameworks */, 301 | D0ABE8051579AF1400A84A96 /* Resources */, 302 | ); 303 | buildRules = ( 304 | ); 305 | dependencies = ( 306 | ); 307 | name = iOSFeatureDetection; 308 | productName = iOSFastImageCorrelation; 309 | productReference = D0ABE8071579AF1400A84A96 /* iOSFeatureDetection.app */; 310 | productType = "com.apple.product-type.application"; 311 | }; 312 | /* End PBXNativeTarget section */ 313 | 314 | /* Begin PBXProject section */ 315 | D04A3728153B7E14005621CF /* Project object */ = { 316 | isa = PBXProject; 317 | attributes = { 318 | LastUpgradeCheck = 0450; 319 | }; 320 | buildConfigurationList = D04A372B153B7E14005621CF /* Build configuration list for PBXProject "FeatureDetection" */; 321 | compatibilityVersion = "Xcode 3.2"; 322 | developmentRegion = English; 323 | hasScannedForEncodings = 0; 324 | knownRegions = ( 325 | en, 326 | ); 327 | mainGroup = D04A3726153B7E14005621CF; 328 | productRefGroup = D04A3732153B7E14005621CF /* Products */; 329 | projectDirPath = ""; 330 | projectRoot = ""; 331 | targets = ( 332 | D04A3730153B7E14005621CF /* FeatureDetection */, 333 | D04A3751153B7E14005621CF /* FeatureDetectionTests */, 334 | D0ABE8061579AF1400A84A96 /* iOSFeatureDetection */, 335 | ); 336 | }; 337 | /* End PBXProject section */ 338 | 339 | /* Begin PBXResourcesBuildPhase section */ 340 | D04A372F153B7E14005621CF /* Resources */ = { 341 | isa = PBXResourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | D04A3740153B7E14005621CF /* InfoPlist.strings in Resources */, 345 | D04A374C153B7E14005621CF /* MainMenu.xib in Resources */, 346 | D0FEEF451583D44900F99148 /* flag-kernel.png in Resources */, 347 | D0FEEF461583D44900F99148 /* lax-sample.png in Resources */, 348 | D0FEEF471583D44900F99148 /* plane-kernel.png in Resources */, 349 | D0FEEF481583D44900F99148 /* shuttle-sample.png in Resources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | D04A374F153B7E14005621CF /* Resources */ = { 354 | isa = PBXResourcesBuildPhase; 355 | buildActionMask = 2147483647; 356 | files = ( 357 | D04A375D153B7E14005621CF /* InfoPlist.strings in Resources */, 358 | ); 359 | runOnlyForDeploymentPostprocessing = 0; 360 | }; 361 | D0ABE8051579AF1400A84A96 /* Resources */ = { 362 | isa = PBXResourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | D09034E91587FB1600F971E0 /* flag-kernel.png in Resources */, 366 | D09034EA1587FB1600F971E0 /* shuttle-sample.png in Resources */, 367 | D0A210811587CD41002F41F1 /* lax-sample.png in Resources */, 368 | D0A210821587CD41002F41F1 /* plane-kernel.png in Resources */, 369 | D0ABE8141579AF1400A84A96 /* InfoPlist.strings in Resources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | /* End PBXResourcesBuildPhase section */ 374 | 375 | /* Begin PBXShellScriptBuildPhase section */ 376 | D04A3750153B7E14005621CF /* ShellScript */ = { 377 | isa = PBXShellScriptBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | ); 381 | inputPaths = ( 382 | ); 383 | outputPaths = ( 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | shellPath = /bin/sh; 387 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 388 | }; 389 | /* End PBXShellScriptBuildPhase section */ 390 | 391 | /* Begin PBXSourcesBuildPhase section */ 392 | D04A372D153B7E14005621CF /* Sources */ = { 393 | isa = PBXSourcesBuildPhase; 394 | buildActionMask = 2147483647; 395 | files = ( 396 | D04A3742153B7E14005621CF /* main.m in Sources */, 397 | D04A3749153B7E14005621CF /* AppDelegate.m in Sources */, 398 | D04A376C153B7FF2005621CF /* LAFeatureDetection.m in Sources */, 399 | D0090942157DB656004981B8 /* CGImageToBitmap.m in Sources */, 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | }; 403 | D04A374D153B7E14005621CF /* Sources */ = { 404 | isa = PBXSourcesBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | D04A3760153B7E14005621CF /* FeatureDetectionTests.m in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | D0ABE8031579AF1400A84A96 /* Sources */ = { 412 | isa = PBXSourcesBuildPhase; 413 | buildActionMask = 2147483647; 414 | files = ( 415 | D0ABE8161579AF1400A84A96 /* main.m in Sources */, 416 | D0ABE81A1579AF1400A84A96 /* iOSAppDelegate.m in Sources */, 417 | D0A2107B1587CC11002F41F1 /* LAFeatureDetection.m in Sources */, 418 | D0A2107C1587CCCA002F41F1 /* CGImageToBitmap.m in Sources */, 419 | ); 420 | runOnlyForDeploymentPostprocessing = 0; 421 | }; 422 | /* End PBXSourcesBuildPhase section */ 423 | 424 | /* Begin PBXTargetDependency section */ 425 | D04A3757153B7E14005621CF /* PBXTargetDependency */ = { 426 | isa = PBXTargetDependency; 427 | target = D04A3730153B7E14005621CF /* FeatureDetection */; 428 | targetProxy = D04A3756153B7E14005621CF /* PBXContainerItemProxy */; 429 | }; 430 | /* End PBXTargetDependency section */ 431 | 432 | /* Begin PBXVariantGroup section */ 433 | D04A373E153B7E14005621CF /* InfoPlist.strings */ = { 434 | isa = PBXVariantGroup; 435 | children = ( 436 | D04A373F153B7E14005621CF /* en */, 437 | ); 438 | name = InfoPlist.strings; 439 | sourceTree = ""; 440 | }; 441 | D04A374A153B7E14005621CF /* MainMenu.xib */ = { 442 | isa = PBXVariantGroup; 443 | children = ( 444 | D04A374B153B7E14005621CF /* en */, 445 | ); 446 | name = MainMenu.xib; 447 | sourceTree = ""; 448 | }; 449 | D04A375B153B7E14005621CF /* InfoPlist.strings */ = { 450 | isa = PBXVariantGroup; 451 | children = ( 452 | D04A375C153B7E14005621CF /* en */, 453 | ); 454 | name = InfoPlist.strings; 455 | sourceTree = ""; 456 | }; 457 | D0ABE8121579AF1400A84A96 /* InfoPlist.strings */ = { 458 | isa = PBXVariantGroup; 459 | children = ( 460 | D0ABE8131579AF1400A84A96 /* en */, 461 | ); 462 | name = InfoPlist.strings; 463 | sourceTree = ""; 464 | }; 465 | /* End PBXVariantGroup section */ 466 | 467 | /* Begin XCBuildConfiguration section */ 468 | D04A3761153B7E14005621CF /* Debug */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 473 | CLANG_ENABLE_OBJC_ARC = YES; 474 | COMBINE_HIDPI_IMAGES = YES; 475 | COPY_PHASE_STRIP = NO; 476 | GCC_C_LANGUAGE_STANDARD = gnu99; 477 | GCC_DYNAMIC_NO_PIC = NO; 478 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 479 | GCC_OPTIMIZATION_LEVEL = 0; 480 | GCC_PREPROCESSOR_DEFINITIONS = ( 481 | "DEBUG=1", 482 | "$(inherited)", 483 | ); 484 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 485 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 486 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 487 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 489 | GCC_WARN_UNUSED_VARIABLE = YES; 490 | MACOSX_DEPLOYMENT_TARGET = 10.7; 491 | ONLY_ACTIVE_ARCH = YES; 492 | SDKROOT = macosx; 493 | }; 494 | name = Debug; 495 | }; 496 | D04A3762153B7E14005621CF /* Release */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | ALWAYS_SEARCH_USER_PATHS = NO; 500 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 501 | CLANG_ENABLE_OBJC_ARC = YES; 502 | COMBINE_HIDPI_IMAGES = YES; 503 | COPY_PHASE_STRIP = YES; 504 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 505 | GCC_C_LANGUAGE_STANDARD = gnu99; 506 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 507 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 508 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 509 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 510 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 511 | GCC_WARN_UNUSED_VARIABLE = YES; 512 | MACOSX_DEPLOYMENT_TARGET = 10.7; 513 | SDKROOT = macosx; 514 | }; 515 | name = Release; 516 | }; 517 | D04A3764153B7E14005621CF /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 521 | GCC_PREFIX_HEADER = "FeatureDetection/FeatureDetection-Prefix.pch"; 522 | INFOPLIST_FILE = "FeatureDetection/FeatureDetection-Info.plist"; 523 | PRODUCT_NAME = FeatureDetection; 524 | WRAPPER_EXTENSION = app; 525 | }; 526 | name = Debug; 527 | }; 528 | D04A3765153B7E14005621CF /* Release */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 532 | GCC_PREFIX_HEADER = "FeatureDetection/FeatureDetection-Prefix.pch"; 533 | INFOPLIST_FILE = "FeatureDetection/FeatureDetection-Info.plist"; 534 | PRODUCT_NAME = FeatureDetection; 535 | WRAPPER_EXTENSION = app; 536 | }; 537 | name = Release; 538 | }; 539 | D04A3767153B7E14005621CF /* Debug */ = { 540 | isa = XCBuildConfiguration; 541 | buildSettings = { 542 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FeatureDetection.app/Contents/MacOS/FeatureDetection"; 543 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 544 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 545 | GCC_PREFIX_HEADER = "FastImageCorrelation/FastImageCorrelation-Prefix.pch"; 546 | INFOPLIST_FILE = "FastImageCorrelationTests/FeatureDetectionTests-Info.plist"; 547 | PRODUCT_NAME = FeatureDetectionTests; 548 | TEST_HOST = "$(BUNDLE_LOADER)"; 549 | WRAPPER_EXTENSION = octest; 550 | }; 551 | name = Debug; 552 | }; 553 | D04A3768153B7E14005621CF /* Release */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FeatureDetection/Contents/MacOS/FeatureDetection"; 557 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 558 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 559 | GCC_PREFIX_HEADER = "FastImageCorrelation/FastImageCorrelation-Prefix.pch"; 560 | INFOPLIST_FILE = "FastImageCorrelationTests/FeatureDetectionTests-Info.plist"; 561 | PRODUCT_NAME = FeatureDetectionTests; 562 | TEST_HOST = "$(BUNDLE_LOADER)"; 563 | WRAPPER_EXTENSION = octest; 564 | }; 565 | name = Release; 566 | }; 567 | D0ABE81C1579AF1400A84A96 /* Debug */ = { 568 | isa = XCBuildConfiguration; 569 | buildSettings = { 570 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 571 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 572 | FRAMEWORK_SEARCH_PATHS = ( 573 | "$(inherited)", 574 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 575 | ); 576 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 577 | GCC_PREFIX_HEADER = "iOSFeatureDetection/iOSFeatureDetection-Prefix.pch"; 578 | INFOPLIST_FILE = "iOSFeatureDetection/iOSFeatureDetection-Info.plist"; 579 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 580 | PRODUCT_NAME = iOSFeatureDetection; 581 | SDKROOT = iphoneos; 582 | TARGETED_DEVICE_FAMILY = "1,2"; 583 | WRAPPER_EXTENSION = app; 584 | }; 585 | name = Debug; 586 | }; 587 | D0ABE81D1579AF1400A84A96 /* Release */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 591 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 592 | FRAMEWORK_SEARCH_PATHS = ( 593 | "$(inherited)", 594 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 595 | ); 596 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 597 | GCC_PREFIX_HEADER = "iOSFeatureDetection/iOSFeatureDetection-Prefix.pch"; 598 | INFOPLIST_FILE = "iOSFeatureDetection/iOSFeatureDetection-Info.plist"; 599 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 600 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 601 | PRODUCT_NAME = iOSFeatureDetection; 602 | SDKROOT = iphoneos; 603 | TARGETED_DEVICE_FAMILY = "1,2"; 604 | VALIDATE_PRODUCT = YES; 605 | WRAPPER_EXTENSION = app; 606 | }; 607 | name = Release; 608 | }; 609 | /* End XCBuildConfiguration section */ 610 | 611 | /* Begin XCConfigurationList section */ 612 | D04A372B153B7E14005621CF /* Build configuration list for PBXProject "FeatureDetection" */ = { 613 | isa = XCConfigurationList; 614 | buildConfigurations = ( 615 | D04A3761153B7E14005621CF /* Debug */, 616 | D04A3762153B7E14005621CF /* Release */, 617 | ); 618 | defaultConfigurationIsVisible = 0; 619 | defaultConfigurationName = Release; 620 | }; 621 | D04A3763153B7E14005621CF /* Build configuration list for PBXNativeTarget "FeatureDetection" */ = { 622 | isa = XCConfigurationList; 623 | buildConfigurations = ( 624 | D04A3764153B7E14005621CF /* Debug */, 625 | D04A3765153B7E14005621CF /* Release */, 626 | ); 627 | defaultConfigurationIsVisible = 0; 628 | defaultConfigurationName = Release; 629 | }; 630 | D04A3766153B7E14005621CF /* Build configuration list for PBXNativeTarget "FeatureDetectionTests" */ = { 631 | isa = XCConfigurationList; 632 | buildConfigurations = ( 633 | D04A3767153B7E14005621CF /* Debug */, 634 | D04A3768153B7E14005621CF /* Release */, 635 | ); 636 | defaultConfigurationIsVisible = 0; 637 | defaultConfigurationName = Release; 638 | }; 639 | D0ABE81B1579AF1400A84A96 /* Build configuration list for PBXNativeTarget "iOSFeatureDetection" */ = { 640 | isa = XCConfigurationList; 641 | buildConfigurations = ( 642 | D0ABE81C1579AF1400A84A96 /* Debug */, 643 | D0ABE81D1579AF1400A84A96 /* Release */, 644 | ); 645 | defaultConfigurationIsVisible = 0; 646 | defaultConfigurationName = Release; 647 | }; 648 | /* End XCConfigurationList section */ 649 | }; 650 | rootObject = D04A3728153B7E14005621CF /* Project object */; 651 | } 652 | --------------------------------------------------------------------------------