[这是Crop and resize image around a custom focus point的后续问题,在此我获得了有关用于imagemagick的哪些命令部件以实现我想要的功能的有用答案:缩小图像,而不是使用预定义的引力(例如“ Center “或” North“),我想在图像上使用自定义焦点,该焦点应该是缩放图像的新中心,以确保在裁剪/调整大小时始终可以看到图像的“重要点”。
这非常有效,除了实际尺寸计算。我想我的数学有问题,因为如果图像缩小的幅度超过了我的计算,结果输出将丢失一些可见的部分。我找不到我正在做的错误,也许有人可以向我提示正确的方向。
我目前在做什么:
# Example image from https://unsplash.com/photos/p-I9wV811qk
source_image = 'input.jpg'
source_image_size = [3008, 2000]
target_image_size = [295, 195]
# Focus point position, in percentages.
focus_point = {
x: 46.7087766,
y: 24.2
}
# Calculate the focus point in px on the source image.
source_focus_point = [
source_image_size[0] / 100.0 * focus_point[:x],
source_image_size[1] / 100.0 * focus_point[:y]
]
# Calculate the distances to the focus point in percentage,
# from all four image sides, and use the smalles value.
smallest_percentage_distance = [
focus_point[:x],
(100.0 - focus_point[:x]),
focus_point[:y],
(100.0 - focus_point[:y])
].min
# Scale image to reach smallest percentage distance.
scale_factor = smallest_percentage_distance / 100.0
# Calculate the focus point on the target image for the transformation,
# which will be on the center of the new image.
target_focus_point = [
target_image_size[0].to_f / 2.0,
target_image_size[1].to_f / 2.0
]
# Define how many degrees the image should be rotated.
rotation_degrees = 0
command = [
'convert',
source_image,
"-set option:distort:viewport #{target_image_size.join('x')}",
"-distort SRT '#{source_focus_point.join(',')} #{scale_factor} #{rotation_degrees} #{target_focus_point.join(',')}'",
'output2.jpg'
].join ' '
结果命令是:
convert input.jpg -set option:distort:viewport 295x195 -distort SRT '1405.000000128,484.0 0.242 0 147.5,97.5' output.jpg
据我所知,imagemagick扭曲了SRT的第二个参数(此处为scale_factor
),它定义了按比例缩小图像的百分比。我的想法是计算各方到焦点的距离,取最小距离,将其转换为合适的参数,然后使用该参数定义缩放比例。
目标是尽可能缩放图像,以确保输出图像不会裁剪过多,以便尽可能多地显示原始图像。我的输出现在截断太多。
我做错了什么?如何计算正确缩小图像的值,以使尽可能多的图片可见?
编辑1最后,将生成具有不同纵横比的图像的多个变体。在给定的295x195旁边,另一个将为1440x560;特别是在这种情况下,一个简单的“重力重播”很可能会裁剪出图像的中部或上部,因此,确保始终可见关键部分的焦点就可以了。
输入:
# get image dimensions and aspect ratio
WxH=`convert barn.jpg -format "%wx%h" info:`
ww=`echo "$WxH" | cut -dx -f1`
hh=`echo "$WxH" | cut -dx -f2`
aspect=`convert xc: -format "%[fx:$ww/$hh]" info:`
# define centering point
px=200
py=200
# compute distances to each side of the image
dleft=$px
dright=$((ww-px-1))
dtop=$py
dbottom=$((hh-py-1))
# find the minimum distance and to which side
dminx=`convert xc: -format "%[fx:round(min($dleft,$dright))]" info:`
dminy=`convert xc: -format "%[fx:round(min($dtop,$dbottom))]" info:`
dmin=`convert xc: -format "%[fx:round(min($dminx,$dminy))]" info:`
# compute crop width, height and scale percent
if [ $dmin -eq $dminx ]; then
wd=$((2*dminx))
ht=`convert xc: -format "%[fx:round($wd/$aspect)]" info:`
scale=`convert xc: -format "%[fx:100*$ww/$wd]" info:`
else
ht=$((2*dminy))
wd=`convert xc: -format "%[fx:round($ht*$aspect)]" info:`
scale=`convert xc: -format "%[fx:100*$hh/$ht]" info:`
fi
# compute x and y offsets to the top left corner of crop region
xoff=`convert xc: -format "%[fx:round($px-$wd/2)]" info:`
yoff=`convert xc: -format "%[fx:round($py-$ht/2)]" info:`
# crop and resize the image to original dimensions
convert barn.jpg -crop ${wd}x${ht}+${xoff}+${yoff} +repage -resize $scale% barn_result.jpg
结果: