Page 1 of 1

Using "convert -evaluate-sequence operator" on color images

Posted: 2016-05-16T06:04:35-07:00
by adrda
Dear ImageMagick users,

When applying the operator Max to a sequence of color images, such as in

Code: Select all

convert -size 100x100 radial-gradient:'#FF0000'-black \
        -size 100x100 gradient:black-'#0000FF' \
        -size 100x100 gradient:'#00FF00'-black \
        -evaluate-sequence max \
        show:
it appears that the operator is applied to each RGB channel
separately. This contrasts with the Median operator, which seems to
operate on a single scalar per location to decide which pixel to
retain (some brightness-like value?). Indeed if I replace the Max
operator with Median in the example above, I obtain an image wherein
every pixel is from one of the three source images. If the Median
operator were applied to every channel separately, the result would
be black everywhere (every RGB component is zero in two of the three
images).

The answer to any of the two following questions would help me:
  1. is it possible to specify the scalar that Median should operate on ?
    Example: retain the pixels of median saturation.
  2. conversely, can one apply the Max operator only to a single channel,
    while still copying the entire pixel over to the destination?
    Example: retain the pixels of minimum saturation. Other example:
    retain the pixels of maximum red level (with their respective
    blue and green component): in the example above that would
    yield the first radial-gradient image.
I tried to put '-channel R' in front of -evaluate-sequence for both
Max and Median operators, but that did not have any effect. This is of
course consistent with the documentation, which does not list
-evaluate-sequence among the options affected by -channel, although it
seemed to be the intuitive answer.

TIA
Adrian


In case it matters, I use imagemagick 6.8.9 on a Debian testing Linux box:

Code: Select all

$> uname -a
Linux rouge 4.5.0-1-amd64 #1 SMP Debian 4.5.1-1 (2016-04-14) x86_64 GNU/Linux
$> convert -version
Version: ImageMagick 6.8.9-9 Q16 x86_64 2016-04-08 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules OpenMP
Delegates: bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr
           ltdl lzma openexr pangocairo png tiff wmf x xml zlib

Re: Using "convert -evaluate-sequence operator" on color images

Posted: 2016-05-16T07:30:14-07:00
by snibgo
"-evaluate-sequence" processes each channel independently, but I think median is incorrect. It is not sensitive to channel settings.

Code: Select all

f:\web\im>%IM%convert xc:#00f xc:#0f0 xc:#f00 -evaluate-sequence median txt:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (65535,0,0)  #FFFF00000000  red

f:\web\im>%IM%convert xc:#00f xc:#0f0 xc:#f00 -evaluate-sequence max txt:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (65535,65535,65535)  #FFFFFFFFFFFF  white

f:\web\im>%IM%convert xc:#00f xc:#0f0 xc:#f00 -evaluate-sequence min txt:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (0,0,0)  #000000000000  black

f:\web\im>%IM%convert xc:#00f xc:#0f0 xc:#f00 -evaluate-sequence mean txt:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (21845,21845,21845)  #555555555555  srgb(85,85,85)
A general way of picking the appropriate pixel from one image according to some criteria is to create a mask from that criteria, then do a masked composite. This only works with two input images, so you need to repeat the process.

For example, given images A and B, suppose you want the pixel with the maximum saturation. Convert the images to HSL, separate the saturation channel, find the maximum. Where this value is equal to A, we want A's pixel.

We can do that last bit by finding the difference from A, then turning all non-black pixels into white.

The result is a mask that is black where we want A's pixels, and white where we want B's pixels. A masked composite gives us the result.

Re: Using "convert -evaluate-sequence operator" on color images

Posted: 2016-05-16T09:37:18-07:00
by adrda
Thanks a lot for the reply. I was hoping I had missed something when browsing the documentation, that would have made things easier, but your solution is perfectly acceptable, so I'll go the way you suggest. It may be slightly more efficient to generate only a single map of maximal values, then iterate through all images and copy pixels matching that maximum to the target. If several images match at the same location, the last one wins.
A

Re: Using "convert -evaluate-sequence operator" on color images

Posted: 2016-05-16T10:05:43-07:00
by snibgo
The general problem of selecting each pixel from one of many images is a pain, and I don't know a better method than the messy one of creating multiple masks.

Yes, optimisation can help -- finding the maximum of all the inputs at once. However, this depends on how much memory they need. Sometimes the work can only be done in pairs of images.

My page Detail by pyramids encountered this.