For a project I am trying to create a perspective distortion of an image to match a DVD case front template. So I want to automate this using ImageMagick (CLI) but I have a hard time understanding the mathematical aspects of this transformation.
convert \
-verbose mw2.png \
-alpha set \
-virtual-pixel transparent \
-distort Perspective-Projection '0,0 0,0 0,0 0,0' \
box.png
This code is en empty set of coordinates, I have read the documentation thoroughly but I can't seem to understand what parameter represents what point. The documentation gives me variables and names where I have no clue what they actually mean (more useful for a mathematical mastermind maybe). So if someone could explain me (visually prefered, or give me a link to useful information) on this subject because I have no clue on what I am doing. Just playing around with the parameters just wont do for this job and I need to calculate these points.
Here you will find an easy image of what I am trying to achieve (with CLI tools):
Update:
convert \
-virtual-pixel transparent \
-size 159x92 \
-verbose \
cd_empty.png \
\(mw2.png -distort Perspective '7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30'\) \
-geometry +3+20 \
-composite cover-after.png
Gives me as output:
cd_empty.png PNG 92x159 92x159+0+0 8-bit sRGB 16.1KB 0.000u 0:00.000
convert: unable to open image `(mw2.png': No such file or directory @ error/blob.c/OpenBlob/2641.
convert: unable to open file `(mw2.png' @ error/png.c/ReadPNGImage/3741.
convert: invalid argument for option Perspective : 'require at least 4 CPs' @ error/distort.c/GenerateCoefficients/807.
convert: no images defined `cover-after.png' @ error/convert.c/ConvertImageCommand/3044.
Correction by Kurt Pfeifle:
The command has a syntax error, because it does not surround the \(
and \)
delimiters by (at least one) blank on each side as required by ImageMagick!
Since there are no links to the source images provided, I cannot test the outcome of this corrected command:
convert \
-virtual-pixel transparent \
-size 159x92 \
-verbose \
cd_empty.png \
\( \
mw2.png -distort Perspective '7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30' \
\) \
-geometry +3+20 \
-composite \
cover-after.png
Did you see this very detailed explanation of ImageMagick's distortion algorithms? It comes with quite a few illustrations as well.
From looking at your example image, my guess is that you'll get there using a Four Point Distortion Method.
Of course, the example you gave with the 0,0 0,0 0,0 0,0
parameter does not do what you want.
Many of the distortion methods available in ImageMagick work like this:
Example:
Sx1,Sy1 Dx1,Dy1 Sx2,Sy2 Dx2,Dy2 Sx3,Sy3 Dx3,Dy3 ... Sxn,Syn Dxn,Dyn
x
is used to represent an X coordinate.y
is used to represent an Y coordinate.1
, 2
, 3
, ... n
is used to represent the 1st, 2nd, 3rd, ... nth pixel.S
is used here for the source pixel.D
is used here for the destination pixel.
-distort perspective
The distortion method perspective
will make sure that straight lines in the source image will remain straight lines in the destination image. Other methods, like barrel
or bilinearforward
do not: they will distort straight lines into curves.
The -distort perspective
requires a set of at least 4 pre-calculated pairs of pixel coordinates (where the last one may be zero). More than 4 pairs of pixel coordinates provide for more accurate distortions. So if you used for example:
-distort perspective '1,2 3,4 5,6 7,8 9,10 11,12 13,14 15,16'
(for readability reasons using more {optional} blanks between the mapping pairs than required) would mean:
You may have seen photo images where the vertical lines (like the corners of building walls) do not look vertical at all (due to some tilting of the camera when taking the snap). The method -distort perspective
can rectify this.
It can even achieve things like this, 'straightening' or 'rectifying' one face of a building that appears in the 'correct' perspective of the original photo:
==>
The control points used for this distortion are indicated by the corners of the red (source controls) and blue rectangles (destination controls) drawn over the original image:
==>
This particular distortion used
-distort perspective '7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30'
Complete command for your copy'n'paste pleasure:
convert \
-verbose \
http://i.stack.imgur.com/SN7sm.jpg \
-matte \
-virtual-pixel transparent \
-distort perspective '7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30' \
output.png
-distort perspective-projection
The method -distort perspective-projection
is derived from the easier understandable perspective
method. It achieves the exactly same distortion result as -distort perspective
does, but doesn't use (at least) 4 pairs of coordinate values (at least 16 integers) as parameter, but 8 floating point coefficients.
It uses...
-distort perspective
, where for values only integers are allowed);These 8 values represent a matrix of the form
sx ry tx
rx sy ty
px py
which is used to calculate the destination pixels from the source pixels according to this formula:
X-of-destination = (sx*xs + ry+ys +tx) / (px*xs + py*ys +1)
Y-of-destination = (rx*xs + sy+ys +ty) / (px*xs + py*ys +1)
(TO BE DONE --
I've no time right now to find out how to
properly format + put formulas into the SO editor)
To avoid (the more difficult) calculating of the 8 required cooefficients for a re-usable -distort perspective-projection
method, you can...
-distort perspective
,
-distort perspective
with a -verbose
parameter added,
The (above quoted) complete command example would spit out this info:
Perspective Projection:
-distort PerspectiveProjection \
'1.945622, 0.071451, -12.187838, 0.799032,
1.276214, -24.470275, 0.006258, 0.000715'
Thanks to ImageMagick Distorting Images Documentation, I ended up with this clean-understandable code:
$points = array(
0,0, # Source Top Left
0,0, # Destination Top Left
0,490, # Source Bottom Left
2.2,512, # Destination Bottom Left
490,838, # Source Bottom Right
490,768, # Destination Bottom Right
838,0, # Source Top Right
838,50 # Destination Top Right
);
$imagick->distortImage(Imagick::DISTORTION_PERSPECTIVE, $points, false);
Please keep in mind that each set of coordinates are separated into two parts. The first is the X axis and the second is the Y axis .. so when we say 838,0 at Destination Right Top, we mean the X axis of Destination Right Top is 838 and the Y axis of it is zero (0).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With