Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
fattjake committed May 17, 2012
2 parents b10f83f + d25b072 commit 48a7c42
Show file tree
Hide file tree
Showing 27 changed files with 410 additions and 214 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,18 @@ Documentation is generated from header comments using appledoc. To build the doc
- **GPUImageEmbossFilter**: Applies an embossing effect on the image
- *intensity*: The strength of the embossing, from 0.0 to 4.0, with 1.0 as the normal level

- **GPUImageHarrisCornerDetectionFilter**: Runs the Harris corner detection algorithm on an input image, and produces an image with those corner points as white pixels and everything else black. The cornersDetectedBlock can be set, and you will be provided with a list of corners (in normalized 0..1 X, Y coordinates) within that callback for whatever additional operations you want to perform.
- *blurSize*: The relative size of the blur applied as part of the corner detection implementation. The default is 1.0.
- *sensitivity*: An internal scaling factor applied to adjust the dynamic range of the cornerness maps generated in the filter. The default is 10.0.
- *threshold*: The threshold at which a point is detected as a corner. This can vary significantly based on the size, lighting conditions, and iOS device camera type, so it might take a little experimentation to get right for your cases. Default is 0.05.

- *GPUImageNonMaximumSuppressionFilter*: Currently used only as part of the Harris corner detection filter, this will sample a 1-pixel box around each pixel and determine if the center pixel's red channel is the maximum in that area. If it is, it stays. If not, it is set to 0 for all color components.

- *GPUImageXYDerivativeFilter*: An internal component within the Harris corner detection filter, this calculates the squared difference between the pixels to the left and right of this one, the squared difference of the pixels above and below this one, and the product of those two differences.

- *GPUImageCrosshairGenerator*: This draws a series of crosshairs on an image, most often used for identifying machine vision features. It does not take in a standard image like other filters, but a series of points in its -renderCrosshairsFromArray:count: method, which does the actual drawing. You will need to force this filter to render at the particular output size you need.
- *crosshairWidth*: The width, in pixels, of the crosshairs to be drawn onscreen.

### Blending modes ###

- **GPUImageChromaKeyBlendFilter**: Selectively replaces a color in the first image with the second image
Expand Down Expand Up @@ -385,7 +397,7 @@ One thing to note when adding fragment shaders to your Xcode project is that Xco

### Filtering and re-encoding a movie ###

Movies can be loaded into the framework via the GPUImageMovie class, filtered, and then written out using a GPUImageMovieWriter. GPUImageMovieWriter is also fast enough to record video in realtime from an iPhone 4's camera at 640x480, so a direct filtered video source can be fed into it.
Movies can be loaded into the framework via the GPUImageMovie class, filtered, and then written out using a GPUImageMovieWriter. GPUImageMovieWriter is also fast enough to record video in realtime from an iPhone 4's camera at 640x480, so a direct filtered video source can be fed into it. Currently, GPUImageMovieWriter is fast enough to record live 720p video at up to 20 FPS on the iPhone 4, and both 720p and 1080p video at 30 FPS on the iPhone 4S (as well as on the new iPad).

The following is an example of how you would load a sample movie, pass it through a pixellation filter, then record the result to disk as a 480 x 640 h.264 movie:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,14 @@ - (void)setupFilter;
case GPUIMAGE_HARRISCORNERDETECTION:
{
self.title = @"Harris Corner Detection";
self.filterSettingsSlider.hidden = YES;
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setMinimumValue:0.01];
[self.filterSettingsSlider setMaximumValue:0.20];
[self.filterSettingsSlider setValue:0.05];

filter = [[GPUImageHarrisCornerDetectionFilter alloc] init];
[(GPUImageHarrisCornerDetectionFilter *)filter setThreshold:0.05];
}; break;
case GPUIMAGE_PREWITTEDGEDETECTION:
{
Expand Down Expand Up @@ -623,9 +628,9 @@ - (void)setupFilter;
self.title = @"Vignette";
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setMinimumValue:-1.0];
[self.filterSettingsSlider setMaximumValue:0.74];
[self.filterSettingsSlider setValue:0.5];
[self.filterSettingsSlider setMinimumValue:0.5];
[self.filterSettingsSlider setMaximumValue:0.9];
[self.filterSettingsSlider setValue:0.75];

filter = [[GPUImageVignetteFilter alloc] init];
}; break;
Expand Down Expand Up @@ -771,12 +776,22 @@ - (void)setupFilter;
}
else if (filterType == GPUIMAGE_HARRISCORNERDETECTION)
{
GPUImageCrosshairGenerator *crosshairGenerator = [[GPUImageCrosshairGenerator alloc] init];
crosshairGenerator.crosshairWidth = 15.0;
[crosshairGenerator forceProcessingAtSize:CGSizeMake(480.0, 640.0)];

[(GPUImageHarrisCornerDetectionFilter *)filter setCornersDetectedBlock:^(GLfloat* cornerArray, NSUInteger cornersDetected) {
[crosshairGenerator renderCrosshairsFromArray:cornerArray count:cornersDetected];
}];

GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
GPUImageGammaFilter *gammaFilter = [[GPUImageGammaFilter alloc] init];
[videoCamera addTarget:gammaFilter];
[gammaFilter addTarget:blendFilter];
gammaFilter.targetToIgnoreForUpdates = blendFilter;

[crosshairGenerator addTarget:blendFilter];

[videoCamera addTarget:blendFilter];
[filter addTarget:blendFilter];
videoCamera.targetToIgnoreForUpdates = blendFilter; // Avoid double-updating the blend

[blendFilter addTarget:filterView];
}
else
Expand Down Expand Up @@ -819,11 +834,13 @@ - (IBAction)updateFilterFromSlider:(id)sender;
case GPUIMAGE_EMBOSS: [(GPUImageEmbossFilter *)filter setIntensity:[(UISlider *)sender value]]; break;
case GPUIMAGE_CANNYEDGEDETECTION: [(GPUImageCannyEdgeDetectionFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
// case GPUIMAGE_CANNYEDGEDETECTION: [(GPUImageCannyEdgeDetectionFilter *)filter setThreshold:[(UISlider*)sender value]]; break;
case GPUIMAGE_HARRISCORNERDETECTION: [(GPUImageHarrisCornerDetectionFilter *)filter setThreshold:[(UISlider*)sender value]]; break;
// case GPUIMAGE_HARRISCORNERDETECTION: [(GPUImageHarrisCornerDetectionFilter *)filter setSensitivity:[(UISlider*)sender value]]; break;
case GPUIMAGE_SMOOTHTOON: [(GPUImageSmoothToonFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
// case GPUIMAGE_BULGE: [(GPUImageBulgeDistortionFilter *)filter setRadius:[(UISlider *)sender value]]; break;
case GPUIMAGE_BULGE: [(GPUImageBulgeDistortionFilter *)filter setScale:[(UISlider *)sender value]]; break;
case GPUIMAGE_PINCH: [(GPUImagePinchDistortionFilter *)filter setScale:[(UISlider *)sender value]]; break;
case GPUIMAGE_VIGNETTE: [(GPUImageVignetteFilter *)filter setY:[(UISlider *)sender value]]; break;
case GPUIMAGE_VIGNETTE: [(GPUImageVignetteFilter *)filter setVignetteEnd:[(UISlider *)sender value]]; break;
case GPUIMAGE_GAUSSIAN: [(GPUImageGaussianBlurFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
case GPUIMAGE_BILATERAL: [(GPUImageBilateralFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
case GPUIMAGE_FASTBLUR: [(GPUImageFastBlurFilter *)filter setBlurPasses:round([(UISlider*)sender value])]; break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ - (void)setupImageFilteringToDisk;
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage];
GPUImageSepiaFilter *stillImageFilter = [[GPUImageSepiaFilter alloc] init];
GPUImageVignetteFilter *vignetteImageFilter = [[GPUImageVignetteFilter alloc] init];
vignetteImageFilter.x = 0.6;
vignetteImageFilter.y = 0.4;
vignetteImageFilter.vignetteEnd = 0.6;
vignetteImageFilter.vignetteStart = 0.4;

// There's a problem with the Kuwahara filter where it doesn't finish rendering before the image is extracted from it.
// It looks like it only gets through certain tiles before glReadPixels() is called. Odd.
Expand All @@ -75,7 +75,6 @@ - (void)setupImageFilteringToDisk;
[stillImageSource addTarget:stillImageFilter];
[stillImageFilter addTarget:vignetteImageFilter];
[vignetteImageFilter prepareForImageCapture];

[stillImageSource processImage];

UIImage *currentFilteredImage = [vignetteImageFilter imageFromCurrentlyProcessedOutput];
Expand Down
16 changes: 12 additions & 4 deletions framework/GPUImage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
BC6ED9C31549CA0600966798 /* GPUImageHistogramFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6ED9C11549CA0600966798 /* GPUImageHistogramFilter.m */; };
BC7CC63515605A3500468085 /* GPUImageBilateralFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7CC63315605A3500468085 /* GPUImageBilateralFilter.h */; };
BC7CC63615605A3500468085 /* GPUImageBilateralFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7CC63415605A3500468085 /* GPUImageBilateralFilter.m */; };
BC7CC69C1562C4BB00468085 /* GPUImageCrosshairGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7CC69A1562C4BA00468085 /* GPUImageCrosshairGenerator.h */; };
BC7CC69D1562C4BB00468085 /* GPUImageCrosshairGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7CC69B1562C4BA00468085 /* GPUImageCrosshairGenerator.m */; };
BC7D95D51523EE67000DF037 /* GPUImageStillCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7D95D31523EE67000DF037 /* GPUImageStillCamera.h */; };
BC7D95D61523EE67000DF037 /* GPUImageStillCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7D95D41523EE67000DF037 /* GPUImageStillCamera.m */; };
BC982B5314F07F790001FF6F /* GPUImageColorInvertFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC982B4F14F07F790001FF6F /* GPUImageColorInvertFilter.h */; };
Expand Down Expand Up @@ -254,6 +256,8 @@
BC6ED9C11549CA0600966798 /* GPUImageHistogramFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageHistogramFilter.m; path = Source/GPUImageHistogramFilter.m; sourceTree = SOURCE_ROOT; };
BC7CC63315605A3500468085 /* GPUImageBilateralFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageBilateralFilter.h; path = Source/GPUImageBilateralFilter.h; sourceTree = SOURCE_ROOT; };
BC7CC63415605A3500468085 /* GPUImageBilateralFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageBilateralFilter.m; path = Source/GPUImageBilateralFilter.m; sourceTree = SOURCE_ROOT; };
BC7CC69A1562C4BA00468085 /* GPUImageCrosshairGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageCrosshairGenerator.h; path = Source/GPUImageCrosshairGenerator.h; sourceTree = SOURCE_ROOT; };
BC7CC69B1562C4BA00468085 /* GPUImageCrosshairGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageCrosshairGenerator.m; path = Source/GPUImageCrosshairGenerator.m; sourceTree = SOURCE_ROOT; };
BC7D95D31523EE67000DF037 /* GPUImageStillCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageStillCamera.h; path = Source/GPUImageStillCamera.h; sourceTree = SOURCE_ROOT; };
BC7D95D41523EE67000DF037 /* GPUImageStillCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageStillCamera.m; path = Source/GPUImageStillCamera.m; sourceTree = SOURCE_ROOT; };
BC982B4F14F07F790001FF6F /* GPUImageColorInvertFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageColorInvertFilter.h; path = Source/GPUImageColorInvertFilter.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -523,10 +527,6 @@
BCF3D71C153E06C3009A1FE5 /* GPUImageCannyEdgeDetectionFilter.m */,
BCAD0976154F39C900278521 /* GPUImagePrewittEdgeDetectionFilter.h */,
BCAD0977154F39CA00278521 /* GPUImagePrewittEdgeDetectionFilter.m */,
BCAD097B154F3CAF00278521 /* GPUImageXYDerivativeFilter.h */,
BCAD097C154F3CB000278521 /* GPUImageXYDerivativeFilter.m */,
BCAD097F154F7B2700278521 /* GPUImageHarrisCornerDetectionFilter.h */,
BCAD0980154F7B2800278521 /* GPUImageHarrisCornerDetectionFilter.m */,
BC1B717A14F566E200ACA2AB /* GPUImageSketchFilter.h */,
BC1B717B14F566E200ACA2AB /* GPUImageSketchFilter.m */,
BCF3D720153E0E0B009A1FE5 /* GPUImageThresholdEdgeDetection.h */,
Expand Down Expand Up @@ -639,8 +639,14 @@
BCF3D70E153DF9E6009A1FE5 /* GPUImageEmbossFilter.m */,
83AE9FCB1540E92800F7FC13 /* GPUImageMaskFilter.h */,
83AE9FCC1540E92800F7FC13 /* GPUImageMaskFilter.m */,
BCAD097B154F3CAF00278521 /* GPUImageXYDerivativeFilter.h */,
BCAD097C154F3CB000278521 /* GPUImageXYDerivativeFilter.m */,
BCAD097F154F7B2700278521 /* GPUImageHarrisCornerDetectionFilter.h */,
BCAD0980154F7B2800278521 /* GPUImageHarrisCornerDetectionFilter.m */,
BCAD099D15506F6E00278521 /* GPUImageNonMaximumSuppressionFilter.h */,
BCAD099E15506F6E00278521 /* GPUImageNonMaximumSuppressionFilter.m */,
BC7CC69A1562C4BA00468085 /* GPUImageCrosshairGenerator.h */,
BC7CC69B1562C4BA00468085 /* GPUImageCrosshairGenerator.m */,
);
name = "Image processing";
sourceTree = "<group>";
Expand Down Expand Up @@ -816,6 +822,7 @@
BC01E82D155CA3F1004C75C3 /* GPUImageMedianFilter.h in Headers */,
BC01E832155CA5E2004C75C3 /* GPUImage3x3TextureSamplingFilter.h in Headers */,
BC7CC63515605A3500468085 /* GPUImageBilateralFilter.h in Headers */,
BC7CC69C1562C4BB00468085 /* GPUImageCrosshairGenerator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1014,6 +1021,7 @@
BC01E82E155CA3F1004C75C3 /* GPUImageMedianFilter.m in Sources */,
BC01E833155CA5E2004C75C3 /* GPUImage3x3TextureSamplingFilter.m in Sources */,
BC7CC63615605A3500468085 /* GPUImageBilateralFilter.m in Sources */,
BC7CC69D1562C4BB00468085 /* GPUImageCrosshairGenerator.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
1 change: 1 addition & 0 deletions framework/Source/GPUImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,4 @@
#import "GPUImageRGBFilter.h"
#import "GPUImageMedianFilter.h"
#import "GPUImageBilateralFilter.h"
#import "GPUImageCrosshairGenerator.h"
8 changes: 4 additions & 4 deletions framework/Source/GPUImage3x3ConvolutionFilter.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING
(
precision highp float;

uniform sampler2D inputImageTexture;

uniform mediump mat3 convolutionMatrix;

varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
Expand All @@ -16,10 +20,6 @@
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;

uniform sampler2D inputImageTexture;

uniform mediump mat3 convolutionMatrix;

void main()
{
mediump vec4 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate);
Expand Down
24 changes: 16 additions & 8 deletions framework/Source/GPUImageBilateralFilter.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,57 @@ void main() {
lowp vec4 sum = centralColor * 0.18;

lowp vec4 sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
mediump float distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// lowp float distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
lowp float distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
lowp float gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;

sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
// distanceFromCentralColor = distance(centralColor, sampleColor) * distanceNormalizationFactor;
distanceFromCentralColor = abs(centralColor.g - sampleColor.g);
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
Expand Down
Loading

0 comments on commit 48a7c42

Please sign in to comment.