Permalink
Browse files

Switched from using NSNumbers for each point in each glyph to using l…

…ower-level arrays. Fixed a variety of memory leaks and wrapped core routine in an NSAutoreleasePool to prevent memory buildup
  • Loading branch information...
1 parent 0375ac1 commit e3cecce9ead8ffa78171d5d077095d09853cdb5c @bengotow bengotow committed Jan 27, 2013
View
@@ -12,3 +12,5 @@ build/
*.mode2v3
xcuserdata
+
+/DerivedData/
@@ -0,0 +1,20 @@
+//
+// WTMDetectionResult.h
+// WTMGlyphDemo
+//
+// Created by Ben Gotow on 1/27/13.
+// Copyright (c) 2013 torin.nguyen@2359media.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class WTMGlyph;
+
+@interface WTMDetectionResult : NSObject
+
+@property (nonatomic, retain) WTMGlyph * bestMatch;
+@property (nonatomic, assign) float bestScore;
+@property (nonatomic, retain) NSArray * allScores;
+@property (nonatomic, assign) BOOL success;
+
+@end
@@ -0,0 +1,14 @@
+//
+// WTMDetectionResult.m
+// WTMGlyphDemo
+//
+// Created by Ben Gotow on 1/27/13.
+// Copyright (c) 2013 torin.nguyen@2359media.com. All rights reserved.
+//
+
+#import "WTMDetectionResult.h"
+#import "WTMGlyph.h"
+
+@implementation WTMDetectionResult
+
+@end
View
0 WTMGlyph/WTMGlyph.h 100644 → 100755
No changes.
View
30 WTMGlyph/WTMGlyph.m 100644 → 100755
@@ -20,7 +20,8 @@ @implementation WTMGlyph
#pragma mark - Lifecycle
-- (void)dealloc {
+- (void)dealloc
+{
[name release];
[strokes release];
[strokeOrders release];
@@ -34,10 +35,11 @@ - (void)dealloc {
- (id)init {
if ((self = [super init])) {
self.strokes = [NSMutableArray array];
- strokeOrders = [NSMutableArray array];
- permutedStrokeOrders = [NSMutableArray array];
- unistrokes = [NSMutableArray array];
self.templates = [NSMutableArray array];
+
+ strokeOrders = [[NSMutableArray alloc] init];
+ permutedStrokeOrders = [[NSMutableArray alloc] init];
+ unistrokes = [[NSMutableArray alloc] init];
}
return self;
}
@@ -71,8 +73,8 @@ - (void)createTemplates {
// actually create the templates from unistrokes
for (int i = 0; i < [unistrokes count]; i++) {
- WTMGlyphTemplate *newTemplate = [[WTMGlyphTemplate alloc] initWithName:self.name
- points:[unistrokes objectAtIndex:i]];
+ WTMGlyphTemplate *newTemplate = [[[WTMGlyphTemplate alloc] initWithName:self.name
+ points:[unistrokes objectAtIndex:i]] autorelease];
[self.templates addObject:newTemplate];
}
DebugLog(@"Templates %@", self.templates);
@@ -81,30 +83,28 @@ - (void)createTemplates {
- (void)createTemplatesFromJSONData:(NSData *)jsonData {
NSError *error = nil;
- NSArray *arr = [[CJSONDeserializer deserializer] deserializeAsArray:jsonData
- error:&error];
+ NSArray *arr = [[CJSONDeserializer deserializer] deserializeAsArray:jsonData error:&error];
DebugLog(@"json data %@", arr);
int i = 0;
for (NSArray *strokePoints in arr) {
- WTMGlyphStroke *stroke = [[WTMGlyphStroke alloc] init];
- for (NSArray *pointArray in strokePoints) {
+ WTMGlyphStroke *stroke = [[[WTMGlyphStroke alloc] init] autorelease];
+ for (NSArray *pointArray in strokePoints)
[stroke addPoint:CGPointMake([[pointArray objectAtIndex:0] floatValue], [[pointArray objectAtIndex:1] floatValue])];
- }
- DebugLog(@"Adding stroke to initial strokes %@", [stroke points]);
+
[self.strokes addObject:stroke];
[strokeOrders addObject:[NSNumber numberWithInt:i]];
i++;
}
- DebugLog(@"Strokes %@", self.strokes);
+ DebugLog(@"Strokes %@", self.strokes);
DebugLog(@"Initial stroke orders %@", strokeOrders);
[self createTemplates];
}
- (void)permuteStrokeOrders:(int)count {
if (count == 1) {
- [permutedStrokeOrders addObject:[strokeOrders copy]];
+ [permutedStrokeOrders addObject: [[strokeOrders copy] autorelease]];
} else {
for (int i = 0; i < count; i++) {
[self permuteStrokeOrders:(count-1)];
@@ -143,7 +143,7 @@ - (void)createUnistrokes {
int strokeIndex = [[strokeOrder objectAtIndex:i] intValue];
stroke = [self.strokes objectAtIndex:strokeIndex];
- copyOfStrokePoints = [NSMutableArray arrayWithArray:[[stroke points] copy]];
+ copyOfStrokePoints = [NSMutableArray arrayWithArray: [[[stroke points] copy] autorelease]];
if (((b >> i) & 1) == 1) {
points = [[copyOfStrokePoints reverseObjectEnumerator] allObjects];
View
0 WTMGlyph/WTMGlyphDefaults.h 100644 → 100755
No changes.
View
0 WTMGlyph/WTMGlyphDefaults.m 100644 → 100755
No changes.
View
0 WTMGlyph/WTMGlyphDelegate.h 100644 → 100755
No changes.
View
6 WTMGlyph/WTMGlyphDetector.h 100644 → 100755
@@ -9,7 +9,7 @@
#import <Foundation/Foundation.h>
#import "WTMGlyph.h"
#import "WTMGlyphDelegate.h"
-
+#import "WTMDetectionResult.h"
@interface WTMGlyphDetector : NSObject {
@@ -41,7 +41,9 @@
- (void)addPoint:(CGPoint)point;
- (void)removeAllPoints;
- (void)removeAllGlyphs;
-- (void)detectGlyph;
+
+- (WTMDetectionResult*)detectGlyph;
+
- (NSArray *)resample:(NSArray *)_points;
- (NSArray *)translate:(NSArray *)_points;
- (NSArray *)vectorize:(NSArray *)_points;
View
76 WTMGlyph/WTMGlyphDetector.m 100644 → 100755
@@ -20,21 +20,24 @@ @implementation WTMGlyphDetector
#pragma mark - Lifecycle
-+ (id)detector {
- WTMGlyphDetector *detector = [[WTMGlyphDetector alloc] init];
++ (id)detector
+{
+ WTMGlyphDetector *detector = [[[WTMGlyphDetector alloc] init] autorelease];
return detector;
}
-+ (id)defaultDetector {
- WTMGlyphDetector *detector = [[WTMGlyphDetector alloc] initWithDefaultGlyphs];
++ (id)defaultDetector
+{
+ WTMGlyphDetector *detector = [[[WTMGlyphDetector alloc] initWithDefaultGlyphs] autorelease];
return detector;
}
-- (id)init {
+- (id)init
+{
if ((self = [super init])) {
- self.points = [[NSMutableArray alloc] init];
- self.glyphs = [[NSMutableArray alloc] init];
- self.timeoutSeconds = WTMGlyphDefaultTimeoutSeconds;
+ points = [[NSMutableArray alloc] init];
+ glyphs = [[NSMutableArray alloc] init];
+ timeoutSeconds = WTMGlyphDefaultTimeoutSeconds;
lastPointTime = [[NSDate date] timeIntervalSince1970];
}
return self;
@@ -46,24 +49,28 @@ - (id)initWithGlyphs:(NSArray *)_glyphs {
return self;
}
-- (id)initWithDefaultGlyphs {
+- (id)initWithDefaultGlyphs
+{
[self init];
NSData *jsonData;
NSArray *fileNames = [NSArray arrayWithObjects: @"D", @"T", @"N", @"P", nil];
for (int i = 0; i < fileNames.count; i++) {
NSString *name = [fileNames objectAtIndex:i];
+ NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init];
jsonData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:@"json"]];
if (jsonData) {
[self addGlyphFromJSON:jsonData name:name];
}
+ [p release];
}
return self;
}
-- (void)dealloc {
+- (void)dealloc
+{
[points release];
[glyphs release];
@@ -72,20 +79,24 @@ - (void)dealloc {
#pragma mark - Glyph Templates
-- (void)addGlyph:(WTMGlyph *)glyph {
+- (void)addGlyph:(WTMGlyph *)glyph
+{
if (!self.glyphs)
self.glyphs = [NSMutableArray arrayWithCapacity:1];
[self.glyphs addObject:glyph];
}
-- (void)addGlyphFromJSON:(NSData *)jsonData name:(NSString *)name {
+- (void)addGlyphFromJSON:(NSData *)jsonData name:(NSString *)name
+{
WTMGlyph *t = [[WTMGlyph alloc] initWithName:name JSONData:jsonData];
[self addGlyph:t];
+ [t release];
}
-- (void)removeGlyphByName:(NSString *)name {
+- (void)removeGlyphByName:(NSString *)name
+{
NSEnumerator *eachGlyph = [self.glyphs objectEnumerator];
WTMGlyph *glyph;
@@ -96,15 +107,16 @@ - (void)removeGlyphByName:(NSString *)name {
}
}
-- (void)removeAllGlyphs {
+- (void)removeAllGlyphs
+{
[self.glyphs removeAllObjects];
}
#pragma mark - Detection
- (void)addPoint:(CGPoint)point {
- //DebugLog(@"Adding point to detector: %@", [NSValue valueWithCGPoint:point]);
+ DebugLog(@"Adding point to detector: %@", [NSValue valueWithCGPoint:point]);
lastPointTime = [[NSDate date] timeIntervalSince1970];
@@ -115,22 +127,27 @@ - (void)removeAllPoints {
[self.points removeAllObjects];
}
-- (void)detectGlyph {
+- (WTMDetectionResult*)detectGlyph {
// Take the captured points and make a Template
// Compare the template against existing templates and find the best match.
// If the best match is within a threshold, consider it a true match.
-
+ WTMDetectionResult * d = [[WTMDetectionResult alloc] init];
+ d.allScores = nil;
+ d.bestMatch = nil;
+
if (![self hasEnoughPoints]) {
- return;
+ d.success = NO;
+ return d;
}
if (self.glyphs.count < 1) {
- return;
+ d.success = NO;
+ return d;
}
- WTMGlyphTemplate *inputTemplate = [[WTMGlyphTemplate alloc] initWithName:@"Input" points:self.points];
- WTMGlyph *glyph;
+ WTMGlyphTemplate *inputTemplate = [[[WTMGlyphTemplate alloc] initWithName:@"Input" points:self.points] autorelease];
+ WTMGlyph *glyph = nil;
NSEnumerator *eachGlyph = [self.glyphs objectEnumerator];
WTMGlyph *bestMatch;
float highestScore = 0;
@@ -140,7 +157,7 @@ - (void)detectGlyph {
while ((glyph = (WTMGlyph *)[eachGlyph nextObject])) {
float score = 1 / [glyph recognize:inputTemplate];
- DebugLog(@"Glyph: %@ Score: %f", glyph.name, score);
+ NSLog(@"Glyph: %@ Score: %f", glyph.name, score);
result = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:glyph.name, [NSNumber numberWithFloat:score], nil]
forKeys:[NSArray arrayWithObjects:@"name", @"score", nil]];
[results addObject:result];
@@ -150,13 +167,16 @@ - (void)detectGlyph {
bestMatch = glyph;
}
}
- DebugLog(@"Best Glyph: %@ with a Score of: %f", bestMatch.name, highestScore);
+ NSLog(@"Best Glyph: %@ with a Score of: %f", bestMatch.name, highestScore);
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"score" ascending:NO] autorelease];
NSArray *sortedResults = [results sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
- [delegate glyphDetected:bestMatch withScore:highestScore];
- [delegate glyphResults:sortedResults];
+ d.success = YES;
+ d.allScores = sortedResults;
+ d.bestMatch = bestMatch;
+ d.bestScore = highestScore;
+ return d;
}
- (NSArray *)resample:(NSArray *)_points {
@@ -178,7 +198,7 @@ - (NSArray *)vectorize:(NSArray *)_points {
- (void)detectIfTimedOut {
if ([self hasTimedOut]) {
- DebugLog(@"Running detection");
+ NSLog(@"Running detection");
[self detectGlyph];
}
}
@@ -196,9 +216,9 @@ - (BOOL)hasTimedOut {
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
NSInteger elapsed = now - lastPointTime;
- //DebugLog(@"Elapsed time since last point is: %i", elapsed);
+ DebugLog(@"Elapsed time since last point is: %i", elapsed);
if (elapsed >= self.timeoutSeconds) {
- DebugLog(@"Timeout detected");
+ NSLog(@"Timeout detected");
return YES;
}
View
0 WTMGlyph/WTMGlyphStroke.h 100644 → 100755
No changes.
View
0 WTMGlyph/WTMGlyphStroke.m 100644 → 100755
No changes.
View
6 WTMGlyph/WTMGlyphTemplate.h 100644 → 100755
@@ -7,20 +7,20 @@
//
#import <Foundation/Foundation.h>
-
+#import "WTMGlyphUtilities.h"
@interface WTMGlyphTemplate : NSObject {
NSString *name;
NSMutableArray *points;
NSMutableArray *normalizedPoints;
CGPoint startUnitVector;
- NSMutableArray *vector;
+ FloatArrayContainer vector;
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSMutableArray *points;
@property (nonatomic, retain) NSMutableArray *normalizedPoints;
-@property (nonatomic, retain) NSMutableArray *vector;
+@property (nonatomic, assign) FloatArrayContainer vector;
- (id)initWithName:(NSString *)_name points:(NSArray *)_points;
- (void)normalize;
Oops, something went wrong. Retry.

0 comments on commit e3cecce

Please sign in to comment.