Sample Point not centered! (Fixed in SVN)

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Sample Point not centered! (Fixed in SVN)

Post by anthony »

The -sample' operation takes one color from each 'rectangular' region of the image.
However the selected 'sample' is from the top-left corner of each region.

Example... Reference (for color values)

Code: Select all

convert -size 1x10 gradient: txt:
# ImageMagick pixel enumeration: 1,10,65535,srgb
0,0: (65535,65535,65535)  #FFFFFFFFFFFF  white
0,1: (58253,58253,58253)  #E38DE38DE38D  srgb(88.8884%,88.8884%,88.8884%)
0,2: (50972,50972,50972)  #C71CC71CC71C  srgb(77.7783%,77.7783%,77.7783%)
0,3: (43690,43690,43690)  #AAAAAAAAAAAA  srgb(170,170,170)
0,4: (36408,36408,36408)  #8E388E388E38  srgb(55.555%,55.555%,55.555%)
0,5: (29127,29127,29127)  #71C771C771C7  srgb(44.445%,44.445%,44.445%)
0,6: (21845,21845,21845)  #555555555555  srgb(85,85,85)
0,7: (14563,14563,14563)  #38E338E338E3  srgb(22.2217%,22.2217%,22.2217%)
0,8: ( 7282, 7282, 7282)  #1C721C721C72  srgb(11.1116%,11.1116%,11.1116%)
0,9: (    0,    0,    0)  #000000000000  black
Sample a 10x10 gradient to 2x2 samples

Code: Select all

convert -size 10x10 gradient: -sample 2x2\! txt:
# ImageMagick pixel enumeration: 2,2,65535,srgb
0,0: (65535,65535,65535)  #FFFFFFFFFFFF  white
1,0: (65535,65535,65535)  #FFFFFFFFFFFF  white
0,1: (29127,29127,29127)  #71C771C771C7  srgb(44.445%,44.445%,44.445%)
1,1: (29127,29127,29127)  #71C771C771C7  srgb(44.445%,44.445%,44.445%)
As you can see it selected the top and left pixel of each 5x5 rectangular region in the gradient image

I would have expected it to have selected the middle pixel, or for rectangles sized an even number of pixels the middle-top-left pixel.

As it stands if I have a grid of images and I sample it so one pixel is taken from each sub-image in the grid, I would only get the top-left pixel of each sub-image, that is more often than not a 'border' pixel (such as from a montage)

The exact pixel to sample important when sampling images that 'pixelated'. For example if sampling a 'spot' image generated by the 'JqMagick' package you would only get a 'black' image, and not the 'pixelated color'.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sample Point not centered!

Post by fmw42 »

With a 2x2 pattern, it seems to pick the top left pixel. This would be what I would have expected.


convert \( -size 1x1 xc:"gray(255)" xc:"gray(168)" +append \) \
\( -size 1x1 xc:"gray(86)" xc:"gray(0)" +append \) \
-append -depth 8 -write mpr:tile +delete \
-size 4x4 tile:mpr:tile 1tmp1.gif

convert 1tmp1.gif txt:

Code: Select all

# ImageMagick pixel enumeration: 4,4,255,srgb
0,0: (255,255,255)  #FFFFFF  white
1,0: (168,168,168)  #A8A8A8  grey66
2,0: (255,255,255)  #FFFFFF  white
3,0: (168,168,168)  #A8A8A8  grey66
0,1: ( 86, 86, 86)  #565656  srgb(86,86,86)
1,1: (  0,  0,  0)  #000000  black
2,1: ( 86, 86, 86)  #565656  srgb(86,86,86)
3,1: (  0,  0,  0)  #000000  black
0,2: (255,255,255)  #FFFFFF  white
1,2: (168,168,168)  #A8A8A8  grey66
2,2: (255,255,255)  #FFFFFF  white
3,2: (168,168,168)  #A8A8A8  grey66
0,3: ( 86, 86, 86)  #565656  srgb(86,86,86)
1,3: (  0,  0,  0)  #000000  black
2,3: ( 86, 86, 86)  #565656  srgb(86,86,86)
3,3: (  0,  0,  0)  #000000  black
convert 1tmp1.gif -sample 2x2 1tmp2.gif

convert 1tmp2.gif txt:

Code: Select all

# ImageMagick pixel enumeration: 2,2,255,srgb
0,0: (255,255,255)  #FFFFFF  white
1,0: (255,255,255)  #FFFFFF  white
0,1: (255,255,255)  #FFFFFF  white
1,1: (255,255,255)  #FFFFFF  white
However, it would be nice to have the ability to pick the initial x,y offset.

This would be useful for example to script a haar wavelet transform that needs to isolate each of the 2x2 pixels in a block into different images. However, I do have a workaround for my issue.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Sample Point not centered!

Post by anthony »

I do not think the algorithm would allow you to specify a pixel offset, as it basically is just a incrementing loop of floating point numbers using nearest neighbour across the image.

Remember for non divisible images the pixels can 'jump' by different amounts, as the floating point numbers jump to the next integer pixel position.

The fix would be a initial offset to the start of sampling point in the loop.

A percentage offset (50% of the sample division for my proposal) may however be possible.
A 0% starting offset would get top-left 100% the bottom-right.

Hmmm.... If I get time I'll take a quick look at the code, may be easy to add that offset, though a little harder to add a 'user define' for that offset, especially with x and y different offsets.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Sample Point not centered!

Post by anthony »

Okay I fixed this myself, both IMv6 and IMv7

I have also updated the command line documentation..

In summary...
The actual sampling point is the middle of the sub-region being sampled. As such a single pixel sampling of an image will take the middle pixel, (or top-left-middle if image has even dimensions). However the -define 'sample:offset' can be set to modify this position some other location within each sub-region being sampled, as a percentage offset.

By default this value is '50' for the midpoint, but could be set to '0' for top-left, '100' for bottom-right, or with separate X and Y offsets such as '0x50' for left-middle edge of sampling sub-region.
okay... example....

the test image...

Code: Select all

convert -size 1x5 gradient:'black-gray(4)'  -depth 8 txt:
# ImageMagick pixel enumeration: 1,5,255,srgb
0,0: (  0,  0,  0)  #000000  black
0,1: (  1,  1,  1)  #010101  srgb(1,1,1)
0,2: (  2,  2,  2)  #020202  srgb(2,2,2)
0,3: (  3,  3,  3)  #030303  grey1
0,4: (  4,  4,  4)  #040404  srgb(4,4,4)
the color gradient was set to make it easy to see what pixel was picked.

Default single sample..

Code: Select all

convert -size 1x5 gradient:'black-gray(4)'  -sample 1x1\!  -depth 8 txt:
# ImageMagick pixel enumeration: 1,1,255,srgb
0,0: (  2,  2,  2)  #020202  srgb(2,2,2)
the mid-point

and four samples of the 5 pixel image

Code: Select all

convert -size 1x5 gradient:'black-gray(4)'  -sample 1x4\!  -depth 8 txt:
# ImageMagick pixel enumeration: 1,4,255,srgb
0,0: (  0,  0,  0)  #000000  black
0,1: (  1,  1,  1)  #010101  srgb(1,1,1)
0,2: (  3,  3,  3)  #030303  grey1
0,3: (  4,  4,  4)  #040404  srgb(4,4,4)
the mid-point was not sampled.. Everything is nicely spaced for other tests.

now say you want single sample at top-left corner, rather than mid-point...

Code: Select all

convert -size 1x5 gradient:'black-gray(4)' -define sample:offset=0 -sample 1x1\!  -depth 8 txt:
# ImageMagick pixel enumeration: 1,1,255,srgb
0,0: (  0,  0,  0)  #000000  black
or bottom right

Code: Select all

convert -size 1x5 gradient:'black-gray(4)' -define sample:offset=100 -sample 1x1\!  -depth 8 txt:
# ImageMagick pixel enumeration: 1,1,255,srgb
0,0: (  4,  4,  4)  #040404  srgb(4,4,4)
If only one number is given that offset is for both X and Y of the sub-region being sampled.
If two numbers you can separate the X and Y offset coords.

Enjoy.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Sample Point not centered!

Post by anthony »

ASIDE:

The maths in -sample was not quite right. It was good enough in that it hit the right sampling regions, but it was a little out in specific situations.

I have thoroughly tested it to ensure I get the correct pixel in each sub-regions being sampled.

I have also updated IM Examples, Sample, with similar information (no actual example though)
http://www.imagemagick.org/Usage/resize/#sample_offset

and the Video Image De-interlacing examples
http://www.imagemagick.org/Usage/video/#deinterlace

Update in a couple of hours.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sample Point not centered! (Fixed in SVN)

Post by fmw42 »

Anthony wrote:However the -define 'sample:offset' can be set to modify this position some other location within each sub-region being sampled, as a percentage offset.

Thanks. That will be useful. But why did you specify it as percent and not absolute pixel offsets?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Sample Point not centered! (Fixed in SVN)

Post by anthony »

Because the 'sample area' or 'sub-region' is not pixel bound.

Essentially you take the image that is M wide (we''l do this in 1 dimension) then subdivide that into N sampling areas. These N areas are floating point, if M is not divisible by N the area will not line up with pixels in the image! As such a 'sampling offset' of 0 may be the top left corner of a pixel, or it may be somewhere in the middle of a pixel!

Because of that, a 'pixel offset' does not make sense in a general case, it isn't even coded in terms of pixels at all, until the absolute final lookup.

Of course if the image size M is directly divisible by N you can figure out where pixels are in terms of percentages.

For example if the sampling sub-regions are 5 pixels wide (M/N => 5) then each pixel can be extracted using values
0-19.9 for the first 20-39.9 for the second, ... 90-100 for the last.
or more simply the 5 possible sampling values are.. 10,30,50,70,90

Remember... the '-set' version of '-define' EG; -set option:sample:offset {value} can use percent escapes to do the calculation for you. hmmm...

Code: Select all

    -set  option:sample:offset  '%fx[100*(4+0.5)*5]'
will calculate the offset of pixel 4 (right-most pixel, as pixel 0 left most) when 5 pixel sampling sub-regions is about to be applied.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply