0

I'm trying to display zebras (colorize totally black pixels one color and totally white pixels a second color) on a selected frame from a video using ffmpeg. Using an rgb lookup table expression I'm getting a workable solution:

lutrgb=r='if(eq(val,0),0,val)':g='if(eq(val,0),153,val)':b='if(eq(val,0),254,val)',lutrgb=r='if(eq(val,255),254,val)':g='if(eq(val,255),102,val)':b='if(eq(val,255),0,val)'

The problem with this expression is that it's testing each pixel for clipping by color, then modding only if that color component = 0 or 255. My video is largely black and white, but a slight pixel level color shift results in a two toned zebra pattern. You can see the two shades of blue in this sample zebra frame:

inconsistent zebras

If I could test for the maxval for clipping into 0 and minval for 255 I would think this problem would be solved, but this code below doesn't work:

lutrgb=r='if(eq(maxval,0),0,val)':g='if(eq(maxval,0),153,val)':b='if(eq(maxval,0),254,val)',lutrgb=r='if(eq(minval,255),254,val)':g='if(eq(minval,255),102,val)':b='if(eq(minval,255),0,val)'

The if/then code for filters is poorly documented on the ffmpeg wiki. Any LUT experts out there?

  • My guess is that minval and maxval are set for the given codec, not the minimum and maximum values of a given RGB triple. I would suggest using 'ge' (greater or equal) and 'le' (lesser or equal) instead of 'eq' (equal) and let the inequalities rule whether you deliver black or white (or interpret black or white to a given color). – Michael Tiemann Jun 14 '18 at 14:21
  • maxval and minval describe the storage ranges for the pixel format and color space. i.e. 0-255 or 16-235/240 for RGB and YUV respectively. – Gyan Jun 14 '18 at 14:27
  • The lut filter only allows one-to-one mapping i.e. r expr can only reference input r values. But a pixel can have 0 component without being black i.e. (0,25,44). You need to use the geq filter, which allows cross-referencing. I'll provide a sample invocation if you wish. – Gyan Jun 14 '18 at 14:29
  • a sample geq would be great, thanks for the input. – user255406 Jun 14 '18 at 14:40
  • FWIW, I think a simple solution to this problem is to just test and modify the blue for black clipping and test/change the red for white clipping: lutrgb=r='if(eq(val,0),0,val)':g='if(eq(val,0),0,val)':b='if(eq(val,0),254,val)',lutrgb=r='if(eq(val,255),254,val)':g='if(eq(val,255),0,val)':b='if(eq(val,255),0,val)' ...but no customizable zebra colors =( – user255406 Jun 14 '18 at 15:04
3

Assuming your input is full range RGB when fed to the filter, then something like

geq=r='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),15,750),p(X,Y),if(lt(ld(1),15),C1R,C2R))':
    g='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),15,750),p(X,Y),if(lt(ld(1),15),C1G,C2G))':
    b='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),15,750),p(X,Y),if(lt(ld(1),15),C1B,C2B))'

Here the two colors are (C1R,C1G,C1B) and (C2R,C2G,C2B). with each component range being 0-255.

The 15 and 750 are the thresholds for selecting black and white pixels. The sum of the values of the three components for each pixel is compared to those values.

The st and ld functions are store and load functions with the first argument being the 'register no.'.

You can also try the colorkey filter.

  • strange, I'm getting a Missing ')' or too many args in 'st(1' error, even though I only see 2 arguments and each parenthesis is appropriately closed. – user255406 Jun 14 '18 at 17:25
  • Color look up functions should be lower-case. Edited. – Gyan Jun 14 '18 at 17:46
  • Thanks, now getting a Either YCbCr or RGB but not both must be specified error. – user255406 Jun 14 '18 at 22:16
  • Share your full command – Gyan Jun 15 '18 at 5:34
  • ffmpeg -i in.mp4 geq=r='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),10,755),p(X,Y),if(lt(ld(1),10),0,254))':g='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),10,755),p(X,Y),if(lt(ld(1),10),153,102))':b='if(between(st(1,r(X,Y)+g(X,Y)+b(X,Y)),10,755),p(X,Y),if(lt(ld(1),10),254,0))' out.jpg – user255406 Jun 16 '18 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.