Compositing an image with multiple affine transformation
Compositing an image with multiple affine transformation
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
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
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
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
This almost solves my problem:
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
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
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
-
- Posts: 1015
- Joined: 2005-03-21T21:16:57-07:00
Re: Compositing an image with multiple affine transformation
See if +distort does what you want.
It is described near the bottom of http://imagemagick.org/script/command-l ... hp#distort
Pete
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.
See my message in this topic for a link to a zip of all the files.
- 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
You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html
It uses -distort SRT
It uses -distort SRT
Re: Compositing an image with multiple affine transformation
I tried it like this: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
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
Google already directed me to your recursion page before I posted here.You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html
It uses -distort SRT
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
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
- 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
wallclimber21 wrote:I tried it like this:el_supremo wrote:See if +distort does what you want.
It is described near the bottom of http://imagemagick.org/script/command-l ... hp#distortbut the orig.jpg is still abutted against the left and top sides of the 512x512 canvas instead of being in the middle of it.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
Google already directed me to your recursion page before I posted here.You might want to see my script, recursion, at http://www.fmwconcepts.com/imagemagick/index.html
It uses -distort SRT
I tried the following:It almost does what it needs to do except that it doesn't expand beyond the size of the original image.Code: Select all
convert orig.jpg -channel RGBA -matte -virtual-pixel transparent -distort SRT "0,0 0.5 10 100,100" final.jpg
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
That did the trick!
For posterity, my solution looks like this:
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
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}`
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
- 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
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!
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/
https://imagemagick.org/Usage/
Re: Compositing an image with multiple affine transformation
You're right, I pasted the wrong piece of code. This is the last line: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.
Code: Select all
cmd_line += " -background transparent -layers merge -crop 512x512+0+0 +repage ./tmp/final.jpg"
I'm still parsing it, but no overflow yet.Brain dump terminated to prevent overflow in recipient!
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
- 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
Okay. To cut down on the number of commands. change it too..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"
Code: Select all
cmd_line += " -background transparent -repage 512x512 -flatten ./tmp/final.jpg"
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/
https://imagemagick.org/Usage/
Re: Compositing an image with multiple affine transformation
I believe this should be -repage instead of +repage, right? The latter results in an error.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"
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
- 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
Yes, sorry about that. I fixed it in the original response, but not in the replys.wallclimber21 wrote:I believe this should be -repage instead of +repage, right? The latter results in an error.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"
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/