Page 1 of 1
Compositing an image with multiple affine transformation
Posted: 2009-01-25T13:03:02-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T13:23:41-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T14:17:50-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T14:49:42-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T15:38:37-07:00
by fmw42
You might want to see my script, recursion, at
http://www.fmwconcepts.com/imagemagick/index.html
It uses -distort SRT
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T16:10:48-07:00
by wallclimber21
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.
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T23:22:18-07:00
by fmw42
wallclimber21 wrote:
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.
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-25T23:50:58-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-26T19:16:16-07:00
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!
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-26T21:00:21-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-26T23:03:29-07:00
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.
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-28T23:51:14-07:00
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
Re: Compositing an image with multiple affine transformation
Posted: 2009-01-29T18:25:44-07:00
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.