Skip to content

Commit

Permalink
Added a threshold filter that takes the average luminance of a scene …
Browse files Browse the repository at this point in the history
…into account. Updated the documentation for the new filters.
  • Loading branch information
BradLarson committed Aug 27, 2012
1 parent 6c433ae commit ff718ab
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 1 deletion.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,26 @@ Documentation is generated from header comments using appledoc. To build the doc
- **GPUImageOpacityFilter**: Adjusts the alpha channel of the incoming image
- *opacity*: The value to multiply the incoming alpha channel for each pixel by (0.0 - 1.0, with 1.0 as the default)

- **GPUImageSolidColorGenerator**: This outputs a generated image with a solid color. You need to define the image size using -forceProcessingAtSize:
- *color*: The color, in a four component format, that is used to fill the image.

- **GPUImageLuminanceThresholdFilter**: Pixels with a luminance above the threshold will appear white, and those below will be black
- *threshold*: The luminance threshold, from 0.0 to 1.0, with a default of 0.5

- **GPUImageAdaptiveThresholdFilter**: Determines the local luminance around a pixel, then turns the pixel black if it is below that local luminance and white if above. This can be useful for picking out text under varying lighting conditions.

- **GPUImageAverageLuminanceThresholdFilter**: This applies a thresholding operation where the threshold is continually adjusted based on the average luminance of the scene.
- *thresholdMultiplier*: This is a factor that the average luminance will be multiplied by in order to arrive at the final threshold to use. By default, this is 1.0.

- **GPUImageHistogramFilter**: This analyzes the incoming image and creates an output histogram with the frequency at which each color value occurs. The output of this filter is a 3-pixel-high, 256-pixel-wide image with the center (vertical) pixels containing pixels that correspond to the frequency at which various color values occurred. Each color value occupies one of the 256 width positions, from 0 on the left to 255 on the right. This histogram can be generated for individual color channels (kGPUImageHistogramRed, kGPUImageHistogramGreen, kGPUImageHistogramBlue), the luminance of the image (kGPUImageHistogramLuminance), or for all three color channels at once (kGPUImageHistogramRGB).
- *downsamplingFactor*: Rather than sampling every pixel, this dictates what fraction of the image is sampled. By default, this is 16 with a minimum of 1. This is needed to keep from saturating the histogram, which can only record 256 pixels for each color value before it becomes overloaded.

- **GPUImageHistogramGenerator**: This is a special filter, in that it's primarily intended to work with the GPUImageHistogramFilter. It generates an output representation of the color histograms generated by GPUImageHistogramFilter, but it could be repurposed to display other kinds of values. It takes in an image and looks at the center (vertical) pixels. It then plots the numerical values of the RGB components in separate colored graphs in an output texture. You may need to force a size for this filter in order to make its output visible.

- **GPUImageAverageColor**: This processes an input image and determines the average color of the scene, by averaging the RGBA components for each pixel in the image. A reduction process is used to progressively downsample the source image on the GPU, followed by a short averaging calculation on the CPU. The output from this filter is meaningless, but you need to set the colorAverageProcessingFinishedBlock property to a block that takes in four color components and a frame time and does something with them.

- **GPUImageLuminosity**: Like the GPUImageAverageColor, this reduces an image to its average luminosity. You need to set the luminosityProcessingFinishedBlock to handle the output of this filter, which just returns a luminosity value and a frame time.

### Image processing ###

- **GPUImageTransformFilter**: This applies an arbitrary 2-D or 3-D transformation to an image
Expand All @@ -128,6 +138,8 @@ Documentation is generated from header comments using appledoc. To build the doc
- **GPUImageCropFilter**: This crops an image to a specific region, then passes only that region on to the next stage in the filter
- *cropRegion*: A rectangular area to crop out of the image, normalized to coordinates from 0.0 - 1.0. The (0.0, 0.0) position is in the upper left of the image.

- **GPUImageLanczosResamplingFilter**: This lets you up- or downsample an image using Lanczos resampling, which results in noticeably better quality than the standard linear or trilinear interpolation. Simply use -forceProcessingAtSize: to set the target output resolution for the filter, and the image will be resampled for that new size.

- **GPUImageSharpenFilter**: Sharpens the image
- *sharpness*: The sharpness adjustment to apply (-4.0 - 4.0, with 0.0 as the default)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
case GPUIMAGE_LUMINOSITY: cell.textLabel.text = @"Luminosity"; break;
case GPUIMAGE_THRESHOLD: cell.textLabel.text = @"Threshold"; break;
case GPUIMAGE_ADAPTIVETHRESHOLD: cell.textLabel.text = @"Adaptive threshold"; break;
case GPUIMAGE_AVERAGELUMINANCETHRESHOLD: cell.textLabel.text = @"Average luminance threshold"; break;
case GPUIMAGE_CROP: cell.textLabel.text = @"Crop"; break;
case GPUIMAGE_TRANSFORM: cell.textLabel.text = @"Transform (2-D)"; break;
case GPUIMAGE_TRANSFORM3D: cell.textLabel.text = @"Transform (3-D)"; break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef enum {
GPUIMAGE_LUMINOSITY,
GPUIMAGE_THRESHOLD,
GPUIMAGE_ADAPTIVETHRESHOLD,
GPUIMAGE_AVERAGELUMINANCETHRESHOLD,
GPUIMAGE_PIXELLATE,
GPUIMAGE_POLARPIXELLATE,
GPUIMAGE_POLKADOT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,17 @@ - (void)setupFilter;
[self.filterSettingsSlider setValue:1.0];

filter = [[GPUImageAdaptiveThresholdFilter alloc] init];
}; break;
case GPUIMAGE_AVERAGELUMINANCETHRESHOLD:
{
self.title = @"Avg. Lum. Threshold";
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setMinimumValue:0.0];
[self.filterSettingsSlider setMaximumValue:2.0];
[self.filterSettingsSlider setValue:1.0];

filter = [[GPUImageAverageLuminanceThresholdFilter alloc] init];
}; break;
case GPUIMAGE_CROP:
{
Expand Down Expand Up @@ -1243,6 +1254,7 @@ - (IBAction)updateFilterFromSlider:(id)sender;
case GPUIMAGE_HAZE: [(GPUImageHazeFilter *)filter setDistance:[(UISlider *)sender value]]; break;
case GPUIMAGE_THRESHOLD: [(GPUImageLuminanceThresholdFilter *)filter setThreshold:[(UISlider *)sender value]]; break;
case GPUIMAGE_ADAPTIVETHRESHOLD: [(GPUImageAdaptiveThresholdFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
case GPUIMAGE_AVERAGELUMINANCETHRESHOLD: [(GPUImageAverageLuminanceThresholdFilter *)filter setThresholdMultiplier:[(UISlider *)sender value]]; break;
case GPUIMAGE_DISSOLVE: [(GPUImageDissolveBlendFilter *)filter setMix:[(UISlider *)sender value]]; break;
case GPUIMAGE_CHROMAKEY: [(GPUImageChromaKeyBlendFilter *)filter setThresholdSensitivity:[(UISlider *)sender value]]; break;
case GPUIMAGE_KUWAHARA: [(GPUImageKuwaharaFilter *)filter setRadius:round([(UISlider *)sender value])]; break;
Expand Down
8 changes: 8 additions & 0 deletions framework/GPUImage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
BCB79E1115EBE1A700965D92 /* GPUImageSolidColorGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB79E0F15EBE1A600965D92 /* GPUImageSolidColorGenerator.m */; };
BCB79E5F15EC131A00965D92 /* GPUImageLuminosity.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB79E5D15EC131A00965D92 /* GPUImageLuminosity.h */; };
BCB79E6015EC131A00965D92 /* GPUImageLuminosity.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB79E5E15EC131A00965D92 /* GPUImageLuminosity.m */; };
BCB79E7A15EC2A8400965D92 /* GPUImageAverageLuminanceThresholdFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB79E7815EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.h */; };
BCB79E7B15EC2A8400965D92 /* GPUImageAverageLuminanceThresholdFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB79E7915EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.m */; };
BCBCE9991595021B00E0ED33 /* GPUImageMonochromeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBCE9971595021B00E0ED33 /* GPUImageMonochromeFilter.h */; };
BCBCE99A1595021B00E0ED33 /* GPUImageMonochromeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBCE9981595021B00E0ED33 /* GPUImageMonochromeFilter.m */; };
BCBCE9D5159944AC00E0ED33 /* GPUImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBCE9D3159944AB00E0ED33 /* GPUImageBuffer.h */; };
Expand Down Expand Up @@ -494,6 +496,8 @@
BCB79E0F15EBE1A600965D92 /* GPUImageSolidColorGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageSolidColorGenerator.m; path = Source/GPUImageSolidColorGenerator.m; sourceTree = SOURCE_ROOT; };
BCB79E5D15EC131A00965D92 /* GPUImageLuminosity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageLuminosity.h; path = Source/GPUImageLuminosity.h; sourceTree = SOURCE_ROOT; };
BCB79E5E15EC131A00965D92 /* GPUImageLuminosity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageLuminosity.m; path = Source/GPUImageLuminosity.m; sourceTree = SOURCE_ROOT; };
BCB79E7815EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageAverageLuminanceThresholdFilter.h; path = Source/GPUImageAverageLuminanceThresholdFilter.h; sourceTree = SOURCE_ROOT; };
BCB79E7915EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageAverageLuminanceThresholdFilter.m; path = Source/GPUImageAverageLuminanceThresholdFilter.m; sourceTree = SOURCE_ROOT; };
BCBCE9971595021B00E0ED33 /* GPUImageMonochromeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageMonochromeFilter.h; path = Source/GPUImageMonochromeFilter.h; sourceTree = SOURCE_ROOT; };
BCBCE9981595021B00E0ED33 /* GPUImageMonochromeFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageMonochromeFilter.m; path = Source/GPUImageMonochromeFilter.m; sourceTree = SOURCE_ROOT; };
BCBCE9D3159944AB00E0ED33 /* GPUImageBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageBuffer.h; path = Source/GPUImageBuffer.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -653,6 +657,8 @@
BCC94ABA151E4FD6008554B4 /* GPUImageLuminanceThresholdFilter.m */,
BCC1E5CA151EA6610006EFA5 /* GPUImageAdaptiveThresholdFilter.h */,
BCC1E5CB151EA6610006EFA5 /* GPUImageAdaptiveThresholdFilter.m */,
BCB79E7815EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.h */,
BCB79E7915EC2A8300965D92 /* GPUImageAverageLuminanceThresholdFilter.m */,
BC6ED9C01549CA0600966798 /* GPUImageHistogramFilter.h */,
BC6ED9C11549CA0600966798 /* GPUImageHistogramFilter.m */,
BCC11D70154B44DC0044F5A0 /* GPUImageHistogramGenerator.h */,
Expand Down Expand Up @@ -1138,6 +1144,7 @@
BC3AC8B015E6F6170065144E /* GPUImageAverageColor.h in Headers */,
BCB79E1015EBE1A700965D92 /* GPUImageSolidColorGenerator.h in Headers */,
BCB79E5F15EC131A00965D92 /* GPUImageLuminosity.h in Headers */,
BCB79E7A15EC2A8400965D92 /* GPUImageAverageLuminanceThresholdFilter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1382,6 +1389,7 @@
BC3AC8B115E6F6170065144E /* GPUImageAverageColor.m in Sources */,
BCB79E1115EBE1A700965D92 /* GPUImageSolidColorGenerator.m in Sources */,
BCB79E6015EC131A00965D92 /* GPUImageLuminosity.m in Sources */,
BCB79E7B15EC2A8400965D92 /* GPUImageAverageLuminanceThresholdFilter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
3 changes: 2 additions & 1 deletion framework/Source/GPUImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,5 @@
#import "GPUImageLanczosResamplingFilter.h"
#import "GPUImageAverageColor.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageLuminosity.h"
#import "GPUImageLuminosity.h"
#import "GPUImageAverageLuminanceThresholdFilter.h"
8 changes: 8 additions & 0 deletions framework/Source/GPUImageAverageLuminanceThresholdFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import "GPUImageFilterGroup.h"

@interface GPUImageAverageLuminanceThresholdFilter : GPUImageFilterGroup

// This is multiplied by the continually calculated average image luminosity to arrive at the final threshold. Default is 1.0.
@property(readwrite, nonatomic) CGFloat thresholdMultiplier;

@end
47 changes: 47 additions & 0 deletions framework/Source/GPUImageAverageLuminanceThresholdFilter.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#import "GPUImageAverageLuminanceThresholdFilter.h"
#import "GPUImageLuminosity.h"
#import "GPUImageLuminanceThresholdFilter.h"

@interface GPUImageAverageLuminanceThresholdFilter()
{
GPUImageLuminosity *luminosityFilter;
GPUImageLuminanceThresholdFilter *luminanceThresholdFilter;
}
@end

@implementation GPUImageAverageLuminanceThresholdFilter

@synthesize thresholdMultiplier = _thresholdMultiplier;

#pragma mark -
#pragma mark Initialization and teardown

- (id)init;
{
if (!(self = [super init]))
{
return nil;
}

self.thresholdMultiplier = 1.0;

luminosityFilter = [[GPUImageLuminosity alloc] init];
[self addFilter:luminosityFilter];

luminanceThresholdFilter = [[GPUImageLuminanceThresholdFilter alloc] init];
[self addFilter:luminanceThresholdFilter];

__unsafe_unretained GPUImageAverageLuminanceThresholdFilter *weakSelf = self;
__unsafe_unretained GPUImageLuminanceThresholdFilter *weakThreshold = luminanceThresholdFilter;

[luminosityFilter setLuminosityProcessingFinishedBlock:^(CGFloat luminosity, CMTime frameTime) {
weakThreshold.threshold = luminosity * weakSelf.thresholdMultiplier;
}];

self.initialFilters = [NSArray arrayWithObjects:luminosityFilter, luminanceThresholdFilter, nil];
self.terminalFilter = luminanceThresholdFilter;

return self;
}

@end

0 comments on commit ff718ab

Please sign in to comment.