[FFmpeg-user] Remove everything but a single color (range)

Ted Park kumowoon1025 at gmail.com
Tue Mar 17 08:15:13 EET 2020


Hello..

>> I think colorkey filter can still do this. Basically you want the converse of what color keying does right? It should work the same (that is the opposite) way, and you just have to invert the alpha value.
> 
> I'm not quite sure what you mean by invert the alpha value.  I think you mean invert the color I'm using... ie, if want to KEEP colors very close to e6e65c (I've refined the color since my first post), then the "invert" of that would be 1919A3 (at least according to an "opposite color tool" I found).
> 
> So... after some experimenting...
> 
> colorkey sort of works if I use the "invert" color and max similarity and blend values:
> 
>  colorkey=color=0x1919A3:similarity=1:blend=1
> 
> But the yellow box is pretty faint and there's still too much of the video still visible.  NOTE: this ONLY works if I use ffplay, not ffmpeg (see below).
> 
Sorry I wasn’t clear, that is not what I meant at all and in fact I am surprised that produced results that you describe as “sort of works.” I’m kind of curious, is the material something you could share?

What I meant was use colorkey to get the exact opposite of what you’re looking for, then you can use any one of a number of methods to get the difference from the original. (To put it conceptually, if you key out the subject, you’d be left with everything else, so if you subtract that from the whole, you should get only what you want.)

>> try using colorkey or colorhold with higher similarity values first.
> 
> colorhold does seem to work, but as Dan Bridges points out...
> 
>> Note, this filter will only make the discriminated stuff gray, not black
>> or transparent.  Perhaps someone else will be able to help.
> 
> Yes... that's what I see.  If I use this:
> 
>  colorhold=color=0xe6e65c:similarity=0.25:blend=0.5
> 
> Then the "yellow box" stays yellow and everything else becomes gray scale... like I'm watching a black and white video.  But I don't want ANY video... I ONLY want the yellow box floating around the screen.
> 
> Now I did find something that works (colorhold + chromakey)
> 
>  colorhold=color=0xe6e65c:similarity=0.25:blend=0.0,chromakey=color=black:similarity=.1
> 
> but this ONLY works if I use ffplay, so perhaps I'm not using it correctly.
> 
> **IF** I use ffplay, then this does (mostly) what I want:
> 
>  ffplay -i test.mkv -vf "colorhold=color=0xe6e65c:similarity=0.25:blend=0.0,chromakey=color=black:similarity=.1"
> 
> I ONLY see the yellow box (although it's a bit spotty), but pretty much all of the rest of the video is completely black.  That's what I want.
> 
Okay, I am not sure if you are just trying a bunch of combinations but I don’t really understand how that works (what is similar to black in terms of chroma???)

> BUT, if I use ffmpeg:
> 
>  ffmpeg -i test.mkv -vf "colorhold=color=0xe6e65c:similarity=0.25:blend=0.0,chromakey=color=black:similarity=.1" test-highlight.mkv
> 
> Then it behaves as if the chromakey filter isn't used at all.  If fact, the above produces the same output (as far as I can tell) as this:
> 
>  ffmpeg -i test.mkv -vf "colorhold=color=0xe6e65c:similarity=0.25:blend=0.0" test-highlight.mkv
> 
> How can I get the same results with ffmpeg that I see with ffplay?
> 
> I have similar results using only colorkey with the inverted color.  ie, using this (sort of) works:
> 
>  ffplay -i test.mkv -vf "colorkey=color=0x1919A3:similarity=1:blend=1"
> 
> but this doesn't seem to do anything (at least visibly):
> 
>  ffmpeg -i test.mkv -vf "colorkey=color=0x1919A3:similarity=1:blend=1" test-highlight.mkv
I am guessing here, but it is probably because every time you switch from working with RGB then Y’CbCr, it erodes all the meaning from your filter configurations.

I’m sorry I wasn’t clear the first time around, I did not think you would invert your target color. 
Try this…
First, choose rgb or yuv, then stick to one. (The video is yuv so I would choose that.) Then, add an alpha channel to serve as the mask. It might be added/converted automatically before the keying filters, but then it might switch from yuv to argb and back, which you probably would not like. If yuv, yuva444p would be sufficient in this case. If you really don’t to work in yuv, I think any of the plain rgb formats with alpha would work (rgba, argb, etc).
ffmpeg -i $INPUT -filter_complex "format=yuva444p”

Chroma key out the box (or color key, if you went that route)
ffmpeg -i $INPUT -filter_complex "format=yuva444p,chromakey=0xC8438A:yuv=1”

At this point the box you’re trying  to isolate should have alpha 0, which is the inverse of what you want. So all you need to do is invert the alpha values.

There’s probably a way to invert the values of just a single plane/channel, but I don't know how. Instead, there’s a filter that inverts (takes 1’s complement, i believe) of all pixel values, called “negate”.
Since it inverts values, obviously if you use it twice in series, the result is more or less identical to the input.
This is useful because it has an option, “negate_alpha” that controls whether the filter works on the alpha channel or not. We want to invert just the alpha values, we can achieve this by inverting everything, then inverting everything except the alpha back.
ffmpeg -i $INPUT -filter_complex "format=yuva444p,chromakey=0xC8438A:yuv=1,negate=negate_alpha=1,negate=negate_alpha=0”

That should give you the yellow box sort of rotoscoped out. You might still have to refine the mask, which you can do by isolating the alpha plane as a separate movie then working on that. 

> Here's the complete output for ffmpeg colorhold,chromakey:
> 
> $ ffmpeg -i test.mkv -vf "colorhold=color=0xe6e65c:similarity=0.25:blend=0.0,chromakey=color=black:similarity=.1" test-highlight.mkv

Really stumped on what chromakey does when you give it black, which is essentially no chroma. Does it just do the smart thing and key out everything with no color?
I think that would be the logical way to do this actually, remove color information other than the one you want, then extract just the areas with color. if you were to do this, you would need much more complex filtering. In yuv, you could check where u and v are both 0, but in rgb, I think it varies. Flip flopping the colors is kinda hacky but easier, probably faster too.

> Can anyone explain to me why this displays only the yellow bar with everything else black:
> 
>  ffplay -f lavfi -i 'smptehdbars=duration=5' -vf "colorhold=color=0xbcc906:similarity=0.25,chromakey=color=black:similarity=.2"
> 
> but this displays all bars in gray scale except the yellow bar which is in color:
> 
>  ffmpeg -f lavfi -i 'smptehdbars=duration=5' -vf "colorhold=color=0xbcc906:similarity=0.25,chromakey=color=black:similarity=.2" TEST-smptehdbars-yellow-only.mkv
> 
> What I want is ONLY the yellow bar and everything else black, as in the ffplay command.  How can I get the same thing with ffmpeg?

A rudimentary explanation, but I think it's like the renderer used by ffplay draws on a black screen, and libx264 uses a white canvas.

Regards,
Ted Park



More information about the ffmpeg-user mailing list