📜 ⬆️ ⬇️

Simple chroma RGB color component

More and more often we see the use of chromakey in the most unexpected places. It was a long thought to try to realize something of my own.

What is a chromakey, for those who are not familiar? Chroma Key is an image matching technology widely used in film-video-television production. As the "key" colors are most often used poisonous green and bright-blue, just by the fact that such shades are not found in the spectrum of the complexion and the human hair. For very dark scenes, such as underground caves, use bright orange as the key color.

After thinking for a while and, having come from the far and not the simplest option using the HSL model, something universal did not work out right away. I must say, this "some" time was very decently drawn out. And here, quite unexpectedly, the idea occurred to try with a simple version, simply by discarding one of the components and making an alpha channel according to its meaning. The green channel was taken as a basis, as one of the most frequently used in similar tasks.
The line of thought was:
- we have a total of 256 gradations of each channel
- all that is approximately below the 30th value can be attributed to the “black” green
- the variant where the green component is dominant is almost certainly green (there are still gradations of gray, close to gray, etc.)
')
Having a random image from the internet


(taken at vid8o.files.wordpress.com/2011/01/chromakey.jpg?w=620 )

and similarly taken background


(I do not know who belongs)

let's go to implement the algorithm for a 24-bit image and an 8-bit mask (alpha channel):

byte const black_threshold = 30; byte* chroma_p = chroma_data; byte* alpha_p = alpha_data; for (int counter = 0; counter < size; ++counter) { byte b = *chroma_p++; byte g = *chroma_p++; byte r = *chroma_p++; // ,      if (g > r && g > b) { //     ,       if (g < black_threshold) *alpha_p++ = 255; else { //         byte m = g - max(r, b); *alpha_p++ = 255 - m; } } } 


Run, we get:

mask


and mask overlay image on our background


As a result, our implementation shows a pretty good, but very rough result. In particular, we see green fog on the resulting image. Let's look at the mask histogram:



We see that the main part of the mask in the field of transparency lies in the range of 17-100. Therefore, we stretch the interval of values ​​100-255 to the interval 0-255, “killing” the veil, and we get just such a histogram



and such a mask, more similar to the one we need

.

As a result, we got rid of the shroud we did not need.

,

but we see the remaining halo around the mask and the green “flare” of the tone, which we naturally looked at against the original green background and looks completely alien to our new background. In general, the result was cheap, but a number of questions remained. How to deal with the halo? You can try to narrow the mask with convolution, or try to somehow stretch the mask histogram.

But I still do not know how to deal with light, therefore, there is enough food for further work. Criticism, tips and advice are welcome.

I would also appreciate links to such works, including their implementation using GPU, OpenCV, etc.

UPD 1: doubled the size of the processed image and masks

Source: https://habr.com/ru/post/158479/


All Articles