Я немного новичок ie, пытаюсь повернуть изображение в Python Подушка, не меняя положение центра повернутого изображения. ИЛИ с помощью подушки вращайте взгляды ... возвращая центр в исходное положение вращения.
В Pillow (Image.py) есть функция, которая поворачивает изображение. Эта функция выглядит следующим образом: -
def rotate(
self,
angle,
resample=NEAREST,
expand=0,
center=None,
translate=None,
fillcolor=None,
):
"""
Returns a rotated copy of this image. This method returns a
copy of this image, rotated the given number of degrees counter
clockwise around its centre.
:param angle: In degrees counter clockwise.
:param resample: An optional resampling filter. This can be
one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),
:py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2
environment), or :py:attr:`PIL.Image.BICUBIC`
(cubic spline interpolation in a 4x4 environment).
If omitted, or if the image has mode "1" or "P", it is
set to :py:attr:`PIL.Image.NEAREST`. See :ref:`concept-filters`.
:param expand: Optional expansion flag. If true, expands the output
image to make it large enough to hold the entire rotated image.
If false or omitted, make the output image the same size as the
input image. Note that the expand flag assumes rotation around
the center and no translation.
:param center: Optional center of rotation (a 2-tuple). Origin is
the upper left corner. Default is the center of the image.
:param translate: An optional post-rotate translation (a 2-tuple).
:param fillcolor: An optional color for area outside the rotated image.
:returns: An :py:class:`~PIL.Image.Image` object.
"""
angle = angle % 360.0
# Fast paths regardless of filter, as long as we're not
# translating or changing the center.
if not (center or translate):
if angle == 0:
return self.copy()
if angle == 180:
return self.transpose(ROTATE_180)
if angle == 90 and expand:
return self.transpose(ROTATE_90)
if angle == 270 and expand:
return self.transpose(ROTATE_270)
# Calculate the affine matrix. Note that this is the reverse
# transformation (from destination image to source) because we
# want to interpolate the (discrete) destination pixel from
# the local area around the (floating) source pixel.
# The matrix we actually want (note that it operates from the right):
# (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
# (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
# (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
# The reverse matrix is thus:
# (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
# (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
# (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
# In any case, the final translation may be updated at the end to
# compensate for the expand flag.
w, h = self.size
if translate is None:
post_trans = (0, 0)
else:
post_trans = translate
if center is None:
# FIXME These should be rounded to ints?
rotn_center = (w / 2.0, h / 2.0)
else:
rotn_center = center
angle = -math.radians(angle)
matrix = [
round(math.cos(angle), 15),
round(math.sin(angle), 15),
0.0,
round(-math.sin(angle), 15),
round(math.cos(angle), 15),
0.0,
]
def transform(x, y, matrix):
(a, b, c, d, e, f) = matrix
return a * x + b * y + c, d * x + e * y + f
matrix[2], matrix[5] = transform(
-rotn_center[0] - post_trans[0], -rotn_center[1] - post_trans[1], matrix
)
matrix[2] += rotn_center[0]
matrix[5] += rotn_center[1]
if expand:
# calculate output size
xx = []
yy = []
for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
x, y = transform(x, y, matrix)
xx.append(x)
yy.append(y)
nw = math.ceil(max(xx)) - math.floor(min(xx))
nh = math.ceil(max(yy)) - math.floor(min(yy))
# We multiply a translation matrix from the right. Because of its
# special form, this is the same as taking the image of the
# translation vector as new translation vector.
matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
w, h = nw, nh
return self.transform((w, h), AFFINE, matrix, resample, fillcolor=fillcolor)
Эта функция также применяет некоторый перевод (смещение положения), чтобы удерживать повернутые углы изображения внутри изображения. Часть кода, которая применяет перевод, это строка
matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
, что я хотел бы сделать, это извлечь значения матрицы [2] и матрицы [5], чтобы я мог отменить этот перевод, когда вращение вызывается в moviepy.
Для достижения чего-то подобного ...
import moviepy.editor as mped
image_clip = mped.ImageClip("image.jpg", duration=3)
rotated_image = image_clip.rotate(20).set_position((pillow_rotate_x.
(-matrix[2]),pillow_rotate_y.(-matrix[5]))
Чтобы отменить перевод подушки и вернуть центр изображения в то место, где он был первоначально повернут at.
Мне было интересно, как этого можно достичь с наименьшим повторением кода?
Например, с помощью следующего кода: -
import moviepy.editor as mped
import sys
import numpy as np
print("Python Version", sys.version)
baboon = mped.ImageClip("baboon.png", duration=3)
colour_clip = mped.ColorClip(size=[500, 50], color=np.array([250, 90, 0]).astype(np.uint8), duration=3) # important to use .astype(np.uint8)
cameraman = mped.ImageClip("cameraman.jpg", duration=3)
print("baboon_size", baboon.size)
print("colour_clip size", colour_clip.size)
print("cameraman size", cameraman.size)
rot_trans_col_clip = colour_clip.add_mask().rotate(20)
rot_trans_cameraman = cameraman.add_mask().rotate(20)
stacked_clips = mped.CompositeVideoClip([baboon, rot_trans_col_clip, rot_trans_cameraman])
stacked_clips.write_videofile('rotated_imagery_on_baboon.mp4', fps=5)
С помощью приведенного выше кода вы может наслоить несколько различных типов контента и вращать их.
Два входных файла изображения бабуина и оператора можно скачать здесь: - https://drive.google.com/file/d/17_s1IunwIAy1npJrsLRicieTG4NZYV4o/view?usp=sharing https://drive.google.com/file/d/1G5YbApGX035-9mJtuz9GNgLr6jGywk-Z/view?usp=sharing
С приведенным ниже кодом перевода (который находится внутри файла image.py подушки)
matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
его влияние на изображения иллюстрируется здесь: -
https://drive.google.com/file/d/1d_prYqb-fqizFcV0MD0rMXOIny2L0KW5/view?usp=sharing Вы можете увидеть здесь, что Центры двух повернутых изображений были перемещены, так что их углы все еще видны (не обрезаны).
Без кода перевода подушки внутри функции вращения подушки это выглядит так: -
https://drive.google.com/file/d/17POoZcuk9QAxJrnwD2LFsYd--SXdR9JA/view?usp=sharing
Здесь вы можете видеть, что, хотя углы немного обрезаны, центры изображений не сместились.
Это результат, который Я хочу. Тем не менее, Подушка поворота применяет перевод в конце.
Интересно, если вы установите на раскрытие подушки разворачивание = False: -
rot_trans_cameraman = cameraman.add_mask().rotate(20, unit='deg', expand=False)
вы получите это: -
https://drive.google.com/open?id=1QEzJN3NlWK_sjxPLGC_BNs2xfxxfhAIH
с одинаковыми центральными точками. Таким образом, кажется, что без флага расширения, установленного в false, центральные точки перемещаются, однако, если для него установлено значение false, все углы обрезаются симметрично.
Причина, по которой это было бы полезно, заключается в том, что если Вы определяете угол поворота подушки, чтобы получить результат c, вместо того, чтобы включить перевод, зависящий от размера изображений.
Итак, мой вопрос: как восстановить расположение центров вращения?