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.25k stars 4.61k forks source link

why GPUImageChromaKeyBlendFilter can't replace black color? #2256

Closed Shun87 closed 8 years ago

Shun87 commented 8 years ago

I want add a overlay to my video, my overlay has only black color and green color, I want use chromaKeyBlendFilter to replace black piexl to my video . So I use it like this

GPUImageChromaKeyBlendFilter * filter = [[GPUImageChromaKeyBlendFilter alloc] init]; [filter setColorToReplaceRed:0.0 green:0.0 blue:0.0]; [self.overlay addTarget:self.preview]; [self.overlay processImage]; [self.mov addTarget:self.preview];

But it replace both black and green color , then my overlay is not visible at all, I just want to key off black color, not both。

If I change the code like this, it can key off green color as expected.

[filter setColorToReplaceRed:0.0 green:1.0 blue:0.0];

What's wrong?

BradLarson commented 8 years ago

This has to do with the color-matching calculation within the chroma keying filter. It attempts to remove the luminance component and only match on chrominance, so for white or black colors it has a hard time matching the target color due to the lack of chrominance. You could try digging into the chroma keying shader and seeing you you could improve the color matching algorithm in there.

Shun87 commented 8 years ago

Sorry, I am a new ios developer, What should I do? Can you help me with this algorithm, thanks

jandolina commented 7 years ago

I was running into an issue when Black and White were both getting keyed out of my image. I added a luminance consideration to the filter. This might not be ideal but it works for me.

Replace the gl_FragColor line in your ChromaKeyBlend shader:

float L = dot(textureColor.rgb, W);
float maskL = dot(colorToReplace.rgb, W);
float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec3(Cr, Cb, L), vec3(maskCr, maskCb, maskL)));
gl_FragColor = mix(textureColor, textureColor2, blendValue);

Replace the gl_FragColor line in your ChromaKey shader:

float L = dot(textureColor.rgb, W);
float maskL = dot(colorToReplace.rgb, W);
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec3(Cr, Cb, L), vec3(maskCr, maskCb, maskL)));
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
Pranoy1c commented 6 years ago

@jandolina What's W in the first line?

jandolina commented 6 years ago

@Pranoy1c, Apologies for the lack of W: const vec3 W = vec3(0.2125, 0.7154, 0.0721);

Pranoy1c commented 6 years ago

@jandolina unfortunately it doesn't seem to work :( It's still replacing both the black/grays and whites. Mind looking at it? https://stackoverflow.com/questions/51437007/ios-gpuimage-chroma-keying-gpuimagechromakeyblendfilter-doesnt-work-with-repl