Compositing an image with multiple affine transformation

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
wallclimber21

Compositing an image with multiple affine transformation

Post by wallclimber21 »

Hello all,
I've been reading the manual and trying combinations for hours, but I still must be missing something fundamental.

I have a bunch of images that I want combined onto a 512x512 new image. All images have their own affine transformation.

As a first step, I just want to create this 512x512 canvas and then place one of the original images somewhere on the canvas. The image rotates fine, but it always clipped back to its bounding box.

Here's one of the many try outs:

convert -size 512x512 xc:khaki canvas_khaki.gif
convert orig.jpg -affine 0.5,0.5,-0.5,0.5,20,20 -transform -compose src-over canvas_khaki.gif -flatten final.jpg

Suggestions are highly appreciated.

Thanks!
Tom
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

Here's another trial:

convert -size 512x512 xc:khaki \( orig.jpg -affine 0.589742,-0.030180616,0.0193408,0.9215189,392.383,474.762 -transform \) -composite final.jpg

This is almost what I want, but the problem is always that the second image looses the translation and ends up at the top left of the canvas. This is not the case when I do translations with geometry.

Tom
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

This almost solves my problem:

Code: Select all

convert \( \( -size 512x512 xc:transparent \) \( orig.jpg \) -composite -virtual-pixel transparent -distort SRT 0,0,1,5,100,100 \) \
 \( \( -size 512x512 xc:transparent \) \( orig.jpg \) -composite -virtual-pixel transparent -distort SRT 0,0,1,5,200,200 \) -composite \
 \( \( -size 512x512 xc:transparent \) \( orig.jpg \) -composite -virtual-pixel transparent -distort SRT 0,0,1,5,400,400 \) -composite \
 -crop 512x512+0+ +repage -identify final.jpg
However, if I replace the '-distort SRT etc' by '-affine ... -transform', I still have the same problem.

What's doing me in this: (from the manual:
The size of the resulting image is that of the smallest rectangle that contains the transformed source image. The parameters tx and ty subsequently shift the image pixels so that those that are moved out of the image area are cut off.

When I check with -identify, it's clear that the tool knows that there's a translate offset, but I haven't had success in finding force it into using absolute coordinates insteda of retaining the smallest rectangle.

My SW creates the affine matrix, but I guess I'll have to work around it by transforming it into something that's understood by -distor. (Not very hard, of course.)

Tom
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Compositing an image with multiple affine transformation

Post by el_supremo »

See if +distort does what you want.
It is described near the bottom of http://imagemagick.org/script/command-l ... hp#distort

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Compositing an image with multiple affine transformation

Post by fmw42 »

You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html

It uses -distort SRT
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

el_supremo wrote:See if +distort does what you want.
It is described near the bottom of http://imagemagick.org/script/command-l ... hp#distort
I tried it like this:

Code: Select all

convert \( -size 512x512 xc:transparent \) \( orig.jpg -virtual-pixel transparent +distort SRT 0,0,1,5,100,100 \) -composite \
 -crop 512x512+0+0 +repage -identify final.jpg
but the orig.jpg is still abutted against the left and top sides of the 512x512 canvas instead of being in the middle of it.
You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html

It uses -distort SRT
Google already directed me to your recursion page before I posted here. :-)

I tried the following:

Code: Select all

convert orig.jpg -channel RGBA -matte -virtual-pixel transparent -distort SRT "0,0 0.5 10 100,100" final.jpg
It almost does what it needs to do except that it doesn't expand beyond the size of the original image.

That's why, in my currently working solution, I first do an initial compose over a 512x512 canvas to expand the picture to full size. One problem with that, however, is that the affine transformation how has to work on a 512x512 picture instead of 200x200. I'm transforming tens of pictures in one go. Right now, I'm at 14 seconds to create 1 composite image. I need to do thousands... It would be nice to find a more efficient way (I'm looking into dialing down the filter quality?), but at least I have something that gives me a result and if really necessary, I can throw more EC2 servers at it...

Thanks for your suggestions!

Tom
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Compositing an image with multiple affine transformation

Post by fmw42 »

wallclimber21 wrote:
el_supremo wrote:See if +distort does what you want.
It is described near the bottom of http://imagemagick.org/script/command-l ... hp#distort
I tried it like this:

Code: Select all

convert \( -size 512x512 xc:transparent \) \( orig.jpg -virtual-pixel transparent +distort SRT 0,0,1,5,100,100 \) -composite \
 -crop 512x512+0+0 +repage -identify final.jpg
but the orig.jpg is still abutted against the left and top sides of the 512x512 canvas instead of being in the middle of it.
You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html

It uses -distort SRT
Google already directed me to your recursion page before I posted here. :-)

I tried the following:

Code: Select all

convert orig.jpg -channel RGBA -matte -virtual-pixel transparent -distort SRT "0,0 0.5 10 100,100" final.jpg
It almost does what it needs to do except that it doesn't expand beyond the size of the original image.

That's why, in my currently working solution, I first do an initial compose over a 512x512 canvas to expand the picture to full size. One problem with that, however, is that the affine transformation how has to work on a 512x512 picture instead of 200x200. I'm transforming tens of pictures in one go. Right now, I'm at 14 seconds to create 1 composite image. I need to do thousands... It would be nice to find a more efficient way (I'm looking into dialing down the filter quality?), but at least I have something that gives me a result and if really necessary, I can throw more EC2 servers at it...

Thanks for your suggestions!

Tom

See +distort and -layers merge. Example at http://www.imagemagick.org/Usage/distorts/#box3d
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

That did the trick!

For posterity, my solution looks like this:

Code: Select all

cmd_line = "convert -virtual-pixel transparent "
for each image:
    ... calc parameters...
    cmd_line += " \\( #{fileName} -matte +distort AffineProjection #{sx},#{rx},#{ry},#{sy},#{tx},#{ty} \\)"
end
cmd_line += " -crop 512x512+0+0 +repage ./tmp/final.jpg"
`#{cmd_line}`
The total run time for my particular test case is 2.5s with the new script, whereas it used to be 14s (!) with my previous version with exactly the same visual result. (Strange enough, the final .JPG is also 45% smaller. I'm not complaining...)

Thank you very much for the help! The documentation is very comprehensive, but there's so much of it that I wouldn't have gotten to this point by myself.

Tom
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Compositing an image with multiple affine transformation

Post by anthony »

To crop the image, enlarging if needed to the 512x512 size area use
a viewport crop by adding a \!

Eg: -crop 512x512+0+0\! -flatten

Or use -extent 512x512+0+0 to get the same result!

This will always produce a 512x512 image with no virtual offset (so a +repage is not needed).
http://www.imagemagick.org/Usage/crop/#crop_viewport

I also do not see a -flatten, or -layers merge in your final processing
so that command will be producing one file per image as JPG can not handle multiple images.

And finally JPG can't handle transparency, as such transparent pixels will probably become black! Setting an -background color in the -flatten or -layers merge step will set an opaque background canvas for the JPEG image.

The -layers merge was developed so that 'layer' images (with any offset) can be merged together to produce larger composited 'layer' images, with all image offsets being preverved, even if they are negative (which -flatten and -mosaic does not do).

The final 'viewport crop' is just one way of converting the final 'layer' image (with offset) into a normal image. Another method as shown for 3D Cubes and Box examples) is to just junk the offset (to get everything in the smallest posible space) and add a little extra border.

NOTE -affine -transform actually call +distort to do its processing. (As of IM v6.4.2-7) with those options now classed as 'depreciated' (though -affine can still be used by -draw). Draw on the other hand still does its affine transformations of images as a separate (interpolation only distortion mapping of images)

The old IM Example, examples about how to use and understand -affine/-transform are still available in a sub-page of the distorts page, but will eventually be re-processed to use -distort AffineProjection instead.

Brain dump terminated to prevent overflow in recipient!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

anthony wrote: I also do not see a -flatten, or -layers merge in your final processing
so that command will be producing one file per image as JPG can not handle multiple images.
You're right, I pasted the wrong piece of code. This is the last line:

Code: Select all

cmd_line += " -background transparent -layers merge -crop 512x512+0+0 +repage ./tmp/final.jpg"
Brain dump terminated to prevent overflow in recipient!
I'm still parsing it, but no overflow yet.

As for pixels becoming black, after all tiles have been merged, they should overlap the final image completely.

Thanks for the info (and for all the hard work on the documentation pages!)
Tom
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Compositing an image with multiple affine transformation

Post by anthony »

wallclimber21 wrote: You're right, I pasted the wrong piece of code. This is the last line:

Code: Select all

cmd_line += " -background transparent -layers merge -crop 512x512+0+0 +repage ./tmp/final.jpg"
Okay. To cut down on the number of commands. change it too..

Code: Select all

cmd_line += " -background transparent -repage 512x512 -flatten ./tmp/final.jpg"
The -flatten takes the final canvas to overlay on as being the virtual canvas size (page) of the first image (that is not the offset, or the actual image size, but the virtual canvas size) which was just set into the images using +repage. It will not expand that canvas, just overlay each 'layer' image onto that canvas (or at least the parts visible on that canvas).

That will produce the desired viewport with the least CPU cycles, especially during the composition process.

See IM Examples, Layering Images, Flatten
http://www.imagemagick.org/Usage/layers/#flatten

And an side -mosaic auto-expands the canvas on the left and bottom edges as much as posible, but still anchors than canvas at +0+0

However -layers merge de-anchors the canvas and created the smallest 'layer' image that holds all the layer images given.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
wallclimber21

Re: Compositing an image with multiple affine transformation

Post by wallclimber21 »

anthony wrote: Okay. To cut down on the number of commands. change it too..

Code: Select all

cmd_line += " -background transparent +repage 512x512 -flatten ./tmp/final.jpg"
I believe this should be -repage instead of +repage, right? The latter results in an error.

Thanks for the detailed explanations, things are a bit less foggy now.

BTW, when I tried your version, speed didn't change significantly one way or the other.

Tom
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Compositing an image with multiple affine transformation

Post by anthony »

wallclimber21 wrote:
anthony wrote: Okay. To cut down on the number of commands. change it too..

Code: Select all

cmd_line += " -background transparent +repage 512x512 -flatten ./tmp/final.jpg"
I believe this should be -repage instead of +repage, right? The latter results in an error.
Yes, sorry about that. I fixed it in the original response, but not in the replys.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply