BradLarson / GPUImage

An open source iOS framework for GPU-based image and video processing
http://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework
BSD 3-Clause "New" or "Revised" License
20.21k stars 4.61k forks source link

Masked Gaussian Blur #318

Open ironmanromeo opened 11 years ago

ironmanromeo commented 11 years ago

Hi Brad,

I'm looking for a Gaussian Blur effect applied to a BLUR-EDGE-MASK only.

I did try:

1) initialize a GPUImageMask to have a masked image 2) pass both the result image + the original image to a GPUImageTwoInputFilter 3) adding them using MIX glsl command using

gl_FragColor = mix(originalColor, maskedBlurColor, maskedBlurColor.a);

where alpha channel 100% means "maskedBlurColor" and 0% means "originalColor".

Problem is that pixel resulted from the SUM of both colors is lighter than reality and suddenly go to 120% light (white).

Blurred edges lighter than 50% will go to 100%/120% and will become white and visible.

I need to mix 3 channels, now I have only two.

I tryed to build a maskAndBlur filter (using GPUImageTwoInputFilter) where the Fragment shader calculate a simple blur effect, but its not so clear and visible like Gaussian blur.

Where I wrong?

Thenk you in advance.

Romeo

BradLarson commented 11 years ago

As a note, the GPUImageAlphaBlendFilter with a mix set to 1.0 does the blending operation you describe above, so there shouldn't be a need for a custom filter here. Try using this blend instead of your custom one, maybe there's a precision issue in your shader.

If this doesn't go away, could you post the code you're using and the images that you're getting?

ironmanromeo commented 11 years ago

Hi Brad, I followed your suggestion with no success:

Image and video hosting by TinyPic

I don't want to see the blurred border. I tried assigning a background color to maskLayer with "setBackgroundColorRed" without success.

GPUImageView *imageView = (GPUImageView *)self.view;

GPUImagePicture *sourceMask = [[GPUImagePicture alloc] initWithImage:
                               [UIImage imageNamed:@"mask.png"]
                                                 smoothlyScaleOutput:YES];

sourcePicture = [[GPUImagePicture alloc] initWithImage:[UIImage imageNamed:@"demo.jpg"] smoothlyScaleOutput:YES];

GPUImageMaskFilter *maskFilter = [[GPUImageMaskFilter alloc] init];

//[maskFilter setBackgroundColorRed:.5 green:.5 blue:.5 alpha:0];

[sourcePicture addTarget:maskFilter];
[sourceMask processImage];
[sourceMask addTarget:maskFilter];

GPUImageGaussianBlurFilter *gaussianBlur = [[GPUImageGaussianBlurFilter alloc] init];

[maskFilter addTarget:gaussianBlur];
gaussianBlur.blurSize = 3.0;

GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
blendFilter.mix = 1;
[sourcePicture addTarget:blendFilter];
[gaussianBlur addTarget:blendFilter];

[blendFilter addTarget:imageView];

[sourcePicture processImage];

Where I'm wrong?

Thank you Brad.

Romeo

recher commented 11 years ago

I have the same problem- the GPUImageMaskFilter insert a contour around the masked area and blurring that image enhance the contour line size (but blurred). I am trying to rewrite a mask filter that works without creating a contour around the mask

hirokimu commented 11 years ago

I had the same problem, and I tested some modification in shader of GPUImageAlphaBlendFilter. It seems to work fine.

gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), 
    textureColor.a);

change to

lowp float a = textureColor2.a * mixturePercent;
gl_FragColor = vec4(textureColor2.rgb + (1.0 - a) * textureColor.rgb + 
    (1.0 - textureColor.a) * (1.0 - a) * textureColor.rgb, textureColor.a);

Reference http://stackoverflow.com/questions/4771224/iphone-opengl-es-alpha-blending-i-have-black-color-in-edge http://home.comcast.net/~tom_forsyth/blog.wiki.html#%5B%5BPremultiplied%20alpha%5D%5D

recher commented 11 years ago

Your solution makes the entire image glow... I thought the problem was with the Blur filter- but you gave me an idea and I checked the GPUImageAlphaBlendFilter and found how to fix it. you should replace this:

gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a);

with this:

lowp float a = floor(textureColor2.a); gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, a * mixturePercent), textureColor.a);

and now it works. Thanks!

hirokimu commented 11 years ago

I mistook...

gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), 
textureColor.a);

should be

gl_FragColor = vec4(textureColor2.rgb + (1.0 - textureColor2.a * mixturePercent) * textureColor.rgb, 1.0);

GPUImage creates textures with kCGImageAlphaPremultipliedFirst, so textureColor2.rgb is premultiplied with alpha.