Это дополнительный вопрос к Обрезке и изменении размера изображения вокруг настраиваемая точка фокусировки, где я получил полезные ответы о том, какие части команды использовать для imagemagick, чтобы достичь того, что я хочу: уменьшить масштаб изображения, но вместо использования предопределенной гравитации (например, «Центр» или «Север») , Я хочу использовать настраиваемую точку фокусировки на изображении, которая должна быть новым центром масштабированного изображения, чтобы гарантировать, что «важная точка» изображения всегда видна при обрезке / изменении размера.
Это работает довольно хорошо, за исключением расчета фактического размера. Я предполагаю, что что-то не так с моей математикой, потому что в результирующем выводе отсутствуют некоторые части, которые могут быть видны, если изображение уменьшается больше, чем я рассчитываю. Я не могу найти ошибку, которую делаю, может быть, кто-нибудь подскажет мне правильное направление.
Чем я сейчас занимаюсь:
# 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
Насколько я понимаю, второй аргумент distort SRT imagemagick (здесь scale_factor
) определяет, насколько в% изображение должно быть уменьшено. Моя идея заключалась в том, чтобы вычислить расстояния от всех сторон до точки фокусировки, взять наименьшее расстояние, преобразовать его в подходящий аргумент и использовать его для определения величины масштабирования.
Цель состоит в том, чтобы максимально масштабировать изображение, чтобы изображение на выходе не обрезалось слишком сильно, чтобы показать как можно больше исходного изображения. Мой вывод сейчас слишком сильно отрезает.
Я попытался визуализировать это для лучшего понимания:
Исходное изображение можно найти здесь: https://unsplash.com/photos/p-I9wV811qk
Что я делаю неправильно? Как правильно рассчитать значение для уменьшения масштаба изображения, чтобы было видно как можно больше изображения?
Редактировать 1
В конце будет создано несколько вариантов изображения с разными соотношениями сторон. Рядом с заданными 295x195 будет еще один размер 1440x560; Особенно в этом случае простое «кадрирование с гравитацией», скорее всего, обрежет среднюю или верхнюю часть изображения, таким образом, точку фокусировки, чтобы гарантировать, что жизненно важная часть всегда видна.
Редактировать 2 на ответ от fmw42
Код работает до сих пор, так что изменение размера и обрезка выполняется без использования SRT. К сожалению, результат далек от того, который у меня есть сейчас (но, возможно, я сделал что-то не так при адаптации сценария).
То, что я сделал, было
- используя изображение из моего вопроса
- замена
px
иpy
значениями точки фокусировки из моего вопроса - сохраняя расчет
scale
, но используяwd=295
иht=195
, поскольку это желаемая целевая культура