GPUImageMotionDetector.m 3.55 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#import "GPUImageMotionDetector.h"

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageMotionComparisonFragmentShaderString = SHADER_STRING
(
 varying highp vec2 textureCoordinate;
 varying highp vec2 textureCoordinate2;
 
 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;
 
 uniform highp float intensity;
 
 void main()
 {
     lowp vec3 currentImageColor = texture2D(inputImageTexture, textureCoordinate).rgb;
     lowp vec3 lowPassImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb;
     
     mediump float colorDistance = distance(currentImageColor, lowPassImageColor); // * 0.57735
     lowp float movementThreshold = step(0.2, colorDistance);
     
     gl_FragColor = movementThreshold * vec4(textureCoordinate2.x, textureCoordinate2.y, 1.0, 1.0);
 }
);
#else
NSString *const kGPUImageMotionComparisonFragmentShaderString = SHADER_STRING
(
 varying vec2 textureCoordinate;
 varying vec2 textureCoordinate2;
 
 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;
 
 uniform float intensity;
 
 void main()
 {
     vec3 currentImageColor = texture2D(inputImageTexture, textureCoordinate).rgb;
     vec3 lowPassImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb;
     
     float colorDistance = distance(currentImageColor, lowPassImageColor); // * 0.57735
     float movementThreshold = step(0.2, colorDistance);
     
     gl_FragColor = movementThreshold * vec4(textureCoordinate2.x, textureCoordinate2.y, 1.0, 1.0);
 }
);
#endif


@implementation GPUImageMotionDetector

@synthesize lowPassFilterStrength, motionDetectionBlock;

#pragma mark -
#pragma mark Initialization and teardown

- (id)init;
{
    if (!(self = [super init]))
    {
		return nil;
    }
    
    // Start with a low pass filter to define the component to be removed
    lowPassFilter = [[GPUImageLowPassFilter alloc] init];
    [self addFilter:lowPassFilter];
    
    // Take the difference of the current frame from the low pass filtered result to get the high pass
    frameComparisonFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageMotionComparisonFragmentShaderString];
    [self addFilter:frameComparisonFilter];
    
    // Texture location 0 needs to be the original image for the difference blend
    [lowPassFilter addTarget:frameComparisonFilter atTextureLocation:1];
    
    // End with the average color for the scene to determine the centroid
    averageColor = [[GPUImageAverageColor alloc] init];
    
    __unsafe_unretained GPUImageMotionDetector *weakSelf = self;

    [averageColor setColorAverageProcessingFinishedBlock:^(CGFloat redComponent, CGFloat greenComponent, CGFloat blueComponent, CGFloat alphaComponent, CMTime frameTime) {
        if (weakSelf.motionDetectionBlock != NULL)
        {
            weakSelf.motionDetectionBlock(CGPointMake(redComponent / alphaComponent, greenComponent / alphaComponent), alphaComponent, frameTime);
        }
//        NSLog(@"Average X: %f, Y: %f total: %f", redComponent / alphaComponent, greenComponent / alphaComponent, alphaComponent);
    }];
    
    [frameComparisonFilter addTarget:averageColor];
    
    self.initialFilters = [NSArray arrayWithObjects:lowPassFilter, frameComparisonFilter, nil];
    self.terminalFilter = frameComparisonFilter;
    
    self.lowPassFilterStrength = 0.5;
    
    return self;
}

#pragma mark -
#pragma mark Accessors

- (void)setLowPassFilterStrength:(CGFloat)newValue;
{
    lowPassFilter.filterStrength = newValue;
}

- (CGFloat)lowPassFilterStrength;
{
    return lowPassFilter.filterStrength;
}


@end