Page 1 of 1

Extracting certain unformatted data from each frame of a GIF

Posted: 2012-03-14T14:30:29-07:00
by brkl
Hello! I'm trying to make a process for generating some simple ambient algorithmic music from (and for) videos I've shot. For the music I'm using something completely different, of course, but I was hoping to use IM to extract the data I plan to use for generating the music. I've been poring over the manuals, but I'm having great trouble wrapping my head around the intricacies of IM.

I'm using the Windows command line. I suppose if I had to I could fetch a linux distro, but I'd rather not.

Here's what I'm trying to do:
I have the video as tiny .gif animations of 32 x 18 pixels and 1 x 1 pixels. From the single pixel file I'd like to generate a text file whose each line contained the following data of one frame.

Code: Select all

HUE SAT LUM
The values should be clean integers (preferably) without any other text. I think I'm actually (almost) successful in this with the following command:

Code: Select all

convert anim.gif -format "%[fx:hue*360] %[fx:saturation*100] %[fx:luminance*100]" info:huesatlum.txt
The bigger 32x18 file is a bit more complicated.
1. First decrease the amount of colors to 4.
2. Then, for each frame, the following line in a text file:

Code: Select all

COLOR1_AMOUNT COLOR1_HUE COLOR1_LUM COLOR2_AMOUNT COLOR2_HUE COLOR2_LUM COLOR3_AMOUNT COLOR3_HUE COLOR3_LUM COLOR4_AMOUNT COLOR4_HUE COLOR4_LUM
Preferably this would be ordered so that the first color had the largest amount of pixels and the last had least pixels. I probably won't need saturation for this one. For the life of me I can't figure this out, but I know IM should be able to handle it quite easily.

I'd very much appreciate help with this!

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-14T21:55:36-07:00
by anthony
brkl wrote:HI'm actually (almost) successful in this with the following command:

Code: Select all

convert anim.gif -format "%[fx:hue*360] %[fx:saturation*100] %[fx:luminance*100]" info:huesatlum.txt
Note that values in the gif are actually 0 to 255 so if you use 255 for the above multipliers
you should get integers (or very close to integers)

However if you want the scaling factors you used in the above, you can ensure the result are integers by using, round() function around the scaled value. EG:

Code: Select all

-format "%[fx:round(hue*360)]
The bigger 32x18 file is a bit more complicated.
1. First decrease the amount of colors to 4.
In what way? -colors works, to an extent. Or for the 4 quadrents you could use -scale '2x2\!'.
2. Then, for each frame, the following line in a text file:

Code: Select all

COLOR1_AMOUNT COLOR1_HUE COLOR1_LUM COLOR2_AMOUNT COLOR2_HUE COLOR2_LUM COLOR3_AMOUNT COLOR3_HUE COLOR3_LUM COLOR4_AMOUNT COLOR4_HUE COLOR4_LUM
Preferably this would be ordered so that the first color had the largest amount of pixels and the last had least pixels.
Okay the first bit can be used in windows. The second replaces any sequence non-number characters with a space, then sort by numbers.

Code: Select all

convert rose: -colors 4  -colorspace HSL -depth 8 -format %c histogram:info:- | \
       tr -sc '0-9\012' ' ' | sort -r -n 
1250 24 39 68 182744 9 41176 15 2941 26 6667
1177 1 150 132 019684 0 392157 58 8235 51 7647
491 69 33 126 45217 27 0588 12 9412 49 4118
302 180 18 214 412 6 70 5882 7 05882 83 9216
The first number is the pixel count, then Hue (0-255) Saturation (0-255) and Liminance (0-255)
Other numbers can be ignored.
[/quote]

See Quantization and Dithering, Extracting Colors,
http://www.imagemagick.org/Usage/quantize/#extract

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-15T06:10:01-07:00
by brkl
Thank you so much for taking the time to reply, anthony!
anthony wrote: Note that values in the gif are actually 0 to 255 so if you use 255 for the above multipliers
you should get integers (or very close to integers)

However if you want the scaling factors you used in the above, you can ensure the result are integers by using, round() function around the scaled value. EG:

Code: Select all

-format "%[fx:round(hue*360)]
Thanks for this! The round() command is very handy. It's useful to have hue as 0-360 as that's how GIMP has it (an angle on a circle).
anthony wrote: In what way? -colors works, to an extent.
It's sufficient for me. The colors don't really have to be very accurate, only consistent.
anthony wrote: Okay the first bit can be used in windows. The second replaces any sequence non-number characters with a space, then sort by numbers.

Code: Select all

convert rose: -colors 4  -colorspace HSL -depth 8 -format %c histogram:info:- | \
       tr -sc '0-9\012' ' ' | sort -r -n 
1250 24 39 68 182744 9 41176 15 2941 26 6667
1177 1 150 132 019684 0 392157 58 8235 51 7647
491 69 33 126 45217 27 0588 12 9412 49 4118
302 180 18 214 412 6 70 5882 7 05882 83 9216
The first number is the pixel count, then Hue (0-255) Saturation (0-255) and Liminance (0-255)
Other numbers can be ignored.
Okay, I installed Cygwin so I'm able to execute bash script. This method works excellently for single frames, but there's a problem with using it on a GIF animation: it orders every single color in the entire animation. Instead, I need the ordering for each frame separately. However, I suppose I can just do the order when I'm parsing the data.

Thanks for your help!

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-15T19:44:08-07:00
by anthony
brkl wrote:Okay, I installed Cygwin so I'm able to execute bash script. This method works excellently for single frames, but there's a problem with using it on a GIF animation: it orders every single color in the entire animation. Instead, I need the ordering for each frame separately. However, I suppose I can just do the order when I'm parsing the data. !
That would be the sort. To fix that you will need to somehow include the frame numebr into the histogram comment, and then replicate that into each line the first number is frame, then the rest of the color counts. That is not quite so easy, but is posible.

Hmmm a perl solution may be inorder, and perl is available under windows without needing cygwin, though is available unde cgywin too. The sort however is not available under windows (I don't think).

Code: Select all

convert rose: logo:[100x100] -colors 4  -colorspace HSL -depth 8 -format '%s\n%c' histogram:info:- |
  perl -nle ' next if /^$/;    $frame=$_,next if /^\d+$/;  $_=$frame.$_; tr/0-9/ /cs; print;' | sort -k1n -k2rn 
0 1250 24 39 68 182744 9 41176 15 2941 26 6667
0 1177 1 150 132 019684 0 392157 58 8235 51 7647
0 491 69 33 126 45217 27 0588 12 9412 49 4118
0 302 180 18 214 412 6 70 5882 7 05882 83 9216
1 6034 15 44 253 0 2 5 88235 17 2549 99 2157
1 646 167 49 74 7314 65 4902 19 2157 29 0196
1 485 9 55 179 0937 3 3 52941 21 5686 70 1961
1 335 225 35 107 1236 88 2353 13 7255 41 9608
Note perl can become very obtuse, though the above is not to bad. But I'll explain...
-n loop over each line - no final print
-l handle end of lines autoatically
-e comamnd line expression
next if /^$/; skip blank lines
$frame=$_,next if /^\d+$/; number only - note it and skip to next line
$_=$frame.$_; prepend frame number to each line
tr/0-9/ /cs; the tr-command equivelent
print; print line.

For the sort....
sort -k1n -k2rn numerically sort on first key, then numerically sort in reverse (highest first) on second key
NOTE the white really has no hue and it is the most common color in 'logo', the resize however generated an off-white as the 'best fit' color :-)

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-16T08:45:09-07:00
by brkl
Hmm, I get this from that command (after installing perl to cygwin). Could be a problem with cygwin, I suppose.

Code: Select all

0
1
 302 180 18 214 412 6 70 5882 7 05882 83 9216
 335 225 35 107 1236 88 2353 13 7255 41 9608
 485 9 55 179 0937 3 3 52941 21 5686 70 1961
 491 69 33 126 45217 27 0588 12 9412 49 4118
 646 167 49 74 7314 65 4902 19 2157 29 0196
 1177 1 150 132 019684 0 392157 58 8235 51 7647
 1250 24 39 68 182744 9 41176 15 2941 26 6667
 6034 15 44 253 0 2 5 88235 17 2549 99 2157

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-16T17:35:00-07:00
by anthony
The perl looks like it did nothing, so the sort re-arraged things wrongly.

Re: Extracting certain unformatted data from each frame of a

Posted: 2012-03-19T00:16:20-07:00
by brkl
Well, that would explain it. But I suppose it doesn't matter whether I program in the ordering when I parse the data or you program it to happen when I extract it! Thank you for your help, anthony.