Shift Individual Color Plane By Subpixel

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
dscully
Posts: 2
Joined: 2017-07-13T09:12:01-07:00
Authentication code: 1151

Shift Individual Color Plane By Subpixel

Post by dscully »

Hello,

I'm attempting to use IM to perform a correction on an image where the green channel of a 1920x1080 RGB image is offset half a pixel in both the positive X and Y directions. My intention is to move the green channel back into alignment with the blue and red channels.

My current approach is to double the size of the image so that the correction becomes a integer number of pixels, separate each channel into a file, use page to shift the green channel with a transparent background, combine the images, and then use a point filter to scale back to the original size.

Code: Select all

convert checker.bmp -resize 200% checker2.bmp
convert -page -1-1 checker2.bmp -channel G -separate -background none -flatten checker_shifted_green.bmp
convert checker2.bmp -channel R -separate checker_red.bmp
convert checker2.bmp -channel B -separate checker_blue.bmp
convert checker_red.bmp checker_shifted_green.bmp checker_blue.bmp -set colorspace RGB -combine -set colorspace sRGB checker_combined.bmp
convert checker_combined.bmp -filter Point -resize %50 checker_combined_smaller.bmp
However, this is fairly inefficient because I do not really need the intermediate files. I was having trouble coming up with a command that does this without the need to write out the files. Also I'm interested if there is a method to avoid the resize and work directly with a floating point translation of the green channel.

Edit: I'm using version ImageMagick 7.0.2-10
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Shift Individual Color Plane By Subpixel

Post by snibgo »

"-distort SRT" can do sub-pixels translations. (With scale=1 and rotation=0, obviously.) So there is no need to double the size, etc.

Does that solve the problem? I don't understand your query about the "floating point translation" of the green channel.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Shift Individual Color Plane By Subpixel

Post by fmw42 »

You can use -distort SRT to do a fractional pixel shift (translate). See http://www.imagemagick.org/Usage/distorts/#srt

Examples:

# create tricolor image

Code: Select all

convert -size 100x100 xc:red xc:green1 xc:blue +append tricolor.png
Image

# shift by 10

Code: Select all

convert tricolor.png \
-separate +channel \
\( -clone 1 -distort SRT "10,10 1 0 0,0" \) \
-swap 1,3 +delete -combine result1.png
Image

# shift by 0.5

Code: Select all

convert tricolor.png \
-separate +channel \
\( -clone 1 -filter lanczos -distort SRT "1,1 1 0 0.5,0.5" \) \
-swap 1,3 +delete -combine result2.png
Image

# compare differences to see that it worked, since it is not visually obvious

Code: Select all

compare -metric rmse tricolor.png result2.png null:
1549.34 (0.0236413)

You may want to change the -filter to triangle for bi-linear interpolation.
User avatar
GeeMack
Posts: 718
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Shift Individual Color Plane By Subpixel

Post by GeeMack »

dscully wrote: 2017-07-13T10:36:04-07:00I'm attempting to use IM to perform a correction on an image where the green channel of a 1920x1080 RGB image is offset half a pixel in both the positive X and Y directions. My intention is to move the green channel back into alignment with the blue and red channels.
As snibgo and fmw42 have already mentioned, IM's "-distort" operator will work with fractions of pixels. The following command would separate your image into its R, G, and B channels, shift the position of the green channel 1/2 pixel to the left and 1/2 pixel up, then reassemble the three images to complete the operation.

Code: Select all

magick input.png -separate -distort affine "0,0 %[fx:t==1?-0.5:0],%[fx:t==1?-0.5:0]" -combine output.png
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Shift Individual Color Plane By Subpixel

Post by fmw42 »

GeeMack: Nice way to do that in IM 7.

It is too bad that -distort does not allow channel modification without separating channels. This does not work.

Code: Select all

convert tricolor.png -channel green -distort SRT "10,10 1 0 0,0" +channel result.png
the result is no change.
User avatar
GeeMack
Posts: 718
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Shift Individual Color Plane By Subpixel

Post by GeeMack »

fmw42 wrote: 2017-07-13T13:01:42-07:00GeeMack: Nice way to do that in IM 7.
Since IM 6 allows the use of FX expressions in "-distort ..." operations, that method also works for me with v6.9.7 in Windows and v6.7.7 in Windows 10's bash.
dscully
Posts: 2
Joined: 2017-07-13T09:12:01-07:00
Authentication code: 1151

Re: Shift Individual Color Plane By Subpixel

Post by dscully »

Thank you everyone, fmw42's method is fast and gets good results!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Shift Individual Color Plane By Subpixel

Post by fmw42 »

GeeMack's method might be slightly faster and less memory intensive since he does not need to clone the green channel, swap and delete.
Post Reply