Skip to content

Commit

Permalink
Made the ColorObjectTracking example functional, finally. It's a litt…
Browse files Browse the repository at this point in the history
…le slow because of the CPU-bound color averaging.
  • Loading branch information
BradLarson committed Feb 25, 2012
1 parent 9bf612f commit 407560c
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ - (UIImage *)imageProcessedOnCPU:(UIImage *)imageToProcess;

- (UIImage *)imageProcessedUsingCoreImage:(UIImage *)imageToProcess;
{
/*
NSArray *filterNames = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
NSLog(@"Built in filters");
for (NSString *currentFilterName in filterNames)
{
NSLog(@"%@", currentFilterName);
}
*/

CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent();

CIImage *inputImage = [[CIImage alloc] initWithCGImage:imageToProcess.CGImage];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@
BC245DED14DDC959009FE7EB /* ColorTrackingAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorTrackingAppDelegate.h; sourceTree = "<group>"; };
BC245DEE14DDC959009FE7EB /* ColorTrackingAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ColorTrackingAppDelegate.m; sourceTree = "<group>"; };
BC245E0C14DDCA1F009FE7EB /* GPUImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GPUImage.xcodeproj; path = ../../framework/GPUImage.xcodeproj; sourceTree = "<group>"; };
BCB5DD8214E85CB0000AF3C2 /* PositionColor.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = PositionColor.fsh; sourceTree = "<group>"; };
BCB5DD8214E85CB0000AF3C2 /* PositionColor.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = PositionColor.fsh; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.glsl; };
BCB5E74414DDCF4F00701302 /* ColorTrackingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorTrackingViewController.h; sourceTree = "<group>"; };
BCB5E74514DDCF4F00701302 /* ColorTrackingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ColorTrackingViewController.m; sourceTree = "<group>"; };
BCB5E74714DDD1B300701302 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
BCB5E7A214E346BE00701302 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
BCB5E7A514E346F100701302 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
BCB5E7A714E3471100701302 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
BCB5E7A914E3472100701302 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
BCB5E7B114E460D300701302 /* Threshold.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Threshold.fsh; sourceTree = "<group>"; };
BCB5E7B114E460D300701302 /* Threshold.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Threshold.fsh; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.glsl; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -336,6 +336,7 @@
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ColorObjectTracking/ColorObjectTracking-Prefix.pch";
GCC_THUMB_SUPPORT = "";
INFOPLIST_FILE = "ColorObjectTracking/ColorObjectTracking-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
Expand All @@ -347,6 +348,7 @@
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ColorObjectTracking/ColorObjectTracking-Prefix.pch";
GCC_THUMB_SUPPORT = "";
INFOPLIST_FILE = "ColorObjectTracking/ColorObjectTracking-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

typedef enum { PASSTHROUGH_VIDEO, SIMPLE_THRESHOLDING, POSITION_THRESHOLDING, OBJECT_TRACKING} ColorTrackingDisplayMode;

@interface ColorTrackingViewController : UIViewController
@interface ColorTrackingViewController : UIViewController <GPUImageRawDataProcessor>
{
CALayer *trackingDot;

GPUImageVideoCamera *videoCamera;
GPUImageFilter *rotationFilter, *thresholdFilter, *positionFilter;
GPUImageRawData *positionRawData, *videoRawData;
GPUImageView *filteredVideoView;

ColorTrackingDisplayMode displayMode;
Expand All @@ -23,4 +24,7 @@ typedef enum { PASSTHROUGH_VIDEO, SIMPLE_THRESHOLDING, POSITION_THRESHOLDING, OB
- (void)configureToolbar;
- (void)configureTrackingDot;

// Image processing
- (CGPoint)centroidFromTexture:(GLubyte *)pixels ofSize:(CGSize)textureSize;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,34 @@ - (void)configureVideoFiltering;
videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, mainScreenFrame.size.width, mainScreenFrame.size.height)];
[self.view addSubview:filteredVideoView];

thresholdFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"Threshold"];
[thresholdFilter setFloat:thresholdSensitivity forUniform:@"threshold"];
[thresholdFilter setFloat:thresholdSensitivity forUniform:@"threshold"];
[thresholdFilter setFloatVec3:thresholdColor forUniform:@"inputColor"];
positionFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"PositionColor"];
[positionFilter setFloat:thresholdSensitivity forUniform:@"threshold"];
[positionFilter setFloatVec3:thresholdColor forUniform:@"inputColor"];
rotationFilter = [[GPUImageRotationFilter alloc] initWithRotation:kGPUImageRotateRight];

// videoCamera -> thresholdFilter -> filteredVideoView
// CGSize videoPixelSize = filteredVideoView.bounds.size;
// videoPixelSize.width *= [filteredVideoView contentScaleFactor];
// videoPixelSize.height *= [filteredVideoView contentScaleFactor];

CGSize videoPixelSize = CGSizeMake(480.0, 640.0);

positionRawData = [[GPUImageRawData alloc] initWithImageSize:videoPixelSize];
positionRawData.delegate = self;

videoRawData = [[GPUImageRawData alloc] initWithImageSize:videoPixelSize];
videoRawData.delegate = self;

[videoCamera addTarget:rotationFilter];
[rotationFilter addTarget:filteredVideoView];

[rotationFilter addTarget:videoRawData];
// [rotationFilter addTarget:positionFilter];
// [positionFilter addTarget:filteredVideoView];
// [positionFilter addTarget:videoRawData];

[videoCamera startCameraCapture];
}

Expand Down Expand Up @@ -104,6 +119,8 @@ - (void)configureTrackingDot;
// [glView.layer addSublayer:trackingDot];
trackingDot.position = CGPointMake(100.0f, 100.0f);
trackingDot.opacity = 0.0f;

[self.view.layer addSublayer:trackingDot];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
Expand All @@ -121,12 +138,7 @@ - (void)handleSwitchOfDisplayMode:(id)sender;

if (newDisplayMode != displayMode)
{
switch (displayMode)
{
case SIMPLE_THRESHOLDING: [thresholdFilter removeTarget:filteredVideoView]; break;
case POSITION_THRESHOLDING: [positionFilter removeTarget:filteredVideoView]; break;
default: break;
}
displayMode = newDisplayMode;
if (displayMode == OBJECT_TRACKING)
{
trackingDot.opacity = 1.0f;
Expand All @@ -136,9 +148,10 @@ - (void)handleSwitchOfDisplayMode:(id)sender;
trackingDot.opacity = 0.0f;
}

displayMode = newDisplayMode;
[rotationFilter removeAllTargets];

[positionFilter removeAllTargets];
[thresholdFilter removeAllTargets];
[rotationFilter addTarget:videoRawData];

switch(displayMode)
{
Expand All @@ -160,11 +173,74 @@ - (void)handleSwitchOfDisplayMode:(id)sender;
{
[rotationFilter addTarget:filteredVideoView];
[rotationFilter addTarget:positionFilter];
[positionFilter addTarget:positionRawData];
}; break;
}
}
}

#pragma mark -
#pragma mark Image processing

- (CGPoint)centroidFromTexture:(GLubyte *)pixels ofSize:(CGSize)textureSize;
{
CGFloat currentXTotal = 0.0f, currentYTotal = 0.0f, currentPixelTotal = 0.0f;

for (NSUInteger currentPixel = 0; currentPixel < (textureSize.width * textureSize.height); currentPixel++)
{
currentXTotal += (CGFloat)pixels[currentPixel * 4] / 255.0f;
currentYTotal += (CGFloat)pixels[(currentPixel * 4) + 1] / 255.0f;
currentPixelTotal += (CGFloat)pixels[(currentPixel * 4) + 3] / 255.0f;
}

return CGPointMake(currentXTotal / currentPixelTotal, currentYTotal / currentPixelTotal);
}

#pragma mark -
#pragma mark GPUImageRawDataProcessor protocol

- (void)newImageFrameAvailableFromDataSource:(GPUImageRawData *)rawDataSource;
{
if (rawDataSource == positionRawData)
{
GLubyte *bytesForPositionData = rawDataSource.rawBytesForImage;
CGPoint currentTrackingLocation = [self centroidFromTexture:bytesForPositionData ofSize:[rawDataSource maximumOutputSize]];
CGSize currentViewSize = self.view.bounds.size;
trackingDot.position = CGPointMake(currentTrackingLocation.x * currentViewSize.width, currentTrackingLocation.y * currentViewSize.height);
}
else
{
if (shouldReplaceThresholdColor)
{
CGSize currentViewSize = self.view.bounds.size;
CGSize rawPixelsSize = [rawDataSource maximumOutputSize];


CGPoint scaledTouchPoint;
scaledTouchPoint.x = (currentTouchPoint.x / currentViewSize.width) * rawPixelsSize.width;
scaledTouchPoint.y = (currentTouchPoint.y / currentViewSize.height) * rawPixelsSize.height;

GPUByteColorVector colorAtTouchPoint = [rawDataSource colorAtLocation:scaledTouchPoint];

thresholdColor[0] = (float)colorAtTouchPoint.red / 255.0;
thresholdColor[1] = (float)colorAtTouchPoint.green / 255.0;
thresholdColor[2] = (float)colorAtTouchPoint.blue / 255.0;

// NSLog(@"Color at touch point: %d, %d, %d, %d", colorAtTouchPoint.red, colorAtTouchPoint.green, colorAtTouchPoint.blue, colorAtTouchPoint.alpha);

[[NSUserDefaults standardUserDefaults] setFloat:thresholdColor[0] forKey:@"thresholdColorR"];
[[NSUserDefaults standardUserDefaults] setFloat:thresholdColor[1] forKey:@"thresholdColorG"];
[[NSUserDefaults standardUserDefaults] setFloat:thresholdColor[2] forKey:@"thresholdColorB"];

[thresholdFilter setFloatVec3:thresholdColor forUniform:@"inputColor"];
[positionFilter setFloatVec3:thresholdColor forUniform:@"inputColor"];

shouldReplaceThresholdColor = NO;
}
}

}

#pragma mark -
#pragma mark Touch handling

Expand All @@ -181,6 +257,9 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

thresholdSensitivity = distanceMoved / 160.0f;
[[NSUserDefaults standardUserDefaults] setFloat:thresholdSensitivity forKey:@"thresholdSensitivity"];

[thresholdFilter setFloat:thresholdSensitivity forUniform:@"threshold"];
[positionFilter setFloat:thresholdSensitivity forUniform:@"threshold"];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ vec4 maskPixel(vec3 pixelColor, vec3 maskColor)
vec4 coordinateMask(vec4 maskColor, vec2 coordinate)
{
// Return this vector weighted by the mask value
return maskColor * vec4(coordinate, vec2(1.0));
return maskColor * vec4(coordinate, vec2(0.0, 1.0));
}

void main()
Expand All @@ -40,6 +40,6 @@ void main()
pixelColor = texture2D(inputImageTexture, textureCoordinate);
maskedColor = maskPixel(pixelColor.rgb, inputColor);
coordinateColor = coordinateMask(maskedColor, textureCoordinate);

gl_FragColor = coordinateColor;
}
6 changes: 3 additions & 3 deletions framework/GPUImage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,15 @@
name = Sources;
sourceTree = "<group>";
};
BCB5E78214E232D600701302 /* Display */ = {
BCB5E78214E232D600701302 /* Outputs */ = {
isa = PBXGroup;
children = (
BCB5E75A14E2086300701302 /* GPUImageView.h */,
BCB5E75B14E2086300701302 /* GPUImageView.m */,
BC1B715514F49DAA00ACA2AB /* GPUImageRawData.h */,
BC1B715614F49DAA00ACA2AB /* GPUImageRawData.m */,
);
name = Display;
name = Outputs;
sourceTree = "<group>";
};
BCF1A32914DDB1EC00852800 = {
Expand Down Expand Up @@ -332,7 +332,7 @@
BCB5E76B14E20AD700701302 /* GPUImageOpenGLESContext.m */,
BCB5E78114E232BC00701302 /* Sources */,
BC245DC314DDBE6B009FE7EB /* Filters */,
BCB5E78214E232D600701302 /* Display */,
BCB5E78214E232D600701302 /* Outputs */,
BCF1A33A14DDB1EC00852800 /* Supporting Files */,
);
path = GPUImage;
Expand Down
2 changes: 1 addition & 1 deletion framework/Source/GPUImageOutput.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ - (void)removeAllTargets;
{
[targetToRemove setInputSize:CGSizeZero];
[targetToRemove setInputTexture:0];
[targets removeObject:targetToRemove];
}
[targets removeAllObjects];
}

#pragma mark -
Expand Down
3 changes: 1 addition & 2 deletions framework/Source/GPUImageRawData.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ struct GPUByteColorVector {
GLubyte red;
GLubyte green;
GLubyte blue;
GLubyte alphe;
GLubyte alpha;
};
typedef struct GPUByteColorVector GPUByteColorVector;

Expand All @@ -15,7 +15,6 @@ typedef struct GPUByteColorVector GPUByteColorVector;

@property(readwrite, unsafe_unretained, nonatomic) id<GPUImageRawDataProcessor> delegate;
@property(readonly) GLubyte *rawBytesForImage;
@property(readonly) GLint openGLTexture;

// Initialization and teardown
- (id)initWithImageSize:(CGSize)newImageSize;
Expand Down
Loading

0 comments on commit 407560c

Please sign in to comment.