Skip to content

Instantly share code, notes, and snippets.

@MrPanch
Created February 25, 2021 13:14
Show Gist options
  • Save MrPanch/5d561fc4b0d9ba203365e867beb247a7 to your computer and use it in GitHub Desktop.
Save MrPanch/5d561fc4b0d9ba203365e867beb247a7 to your computer and use it in GitHub Desktop.
import cv2
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import math
def plot_one_image(image: np.ndarray) -> None:
"""
Отобразить изображение с помощью matplotlib.
Вспомогательная функция.
:param image: изображение для отображения
:return: None
"""
fig, axs = plt.subplots(1, 1, figsize=(8, 7))
axs.imshow(image)
axs.axis('off')
plt.plot()
plt.show()
def rotate(image, point: tuple, angle: float) -> np.ndarray:
"""
Повернуть изображение по часовой стрелке на угол от 0 до 360 градусов и преобразовать размер изображения.
:param image: исходное изображение
:param point: значение точки (x, y), вокруг которой повернуть изображение
:param angle: угол поворота
:return: повернутное изображение
"""
M1 = np.float32([[1, 0, point[1]], [0, 1, point[0]]])
image_shift = cv2.warpAffine(image.copy(), M1, (image.shape[1] + point[0], image.shape[0] + point[1]))
height, width = image.shape[:2] # image shape has 3 dimensions
image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape
rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.)
# rotation calculates the cos and sin, taking absolutes of those.
abs_cos = abs(rotation_mat[0,0])
abs_sin = abs(rotation_mat[0,1])
# find the new width and height bounds
bound_w = int(height * abs_sin + width * abs_cos)
bound_h = int(height * abs_cos + width * abs_sin)
# subtract old image center (bringing image back to origo) and adding the new image center coordinates
rotation_mat[0, 2] += bound_w/2 - image_center[0]
rotation_mat[1, 2] += bound_h/2 - image_center[1]
# rotate image with the new bounds and translated rotation matrix
rotated_mat = cv2.warpAffine(image, rotation_mat, (bound_w, bound_h))
return rotated_mat
# angle = math.radians(angle) # converting degrees to radians
# cosine = math.cos(angle)
# sine = math.sin(angle)
#
# x1y1 = M @ np.array([0,0,1]).T
# x1y2 = M @ np.array([0, image.shape[1], 1])
# x2y1 = M @ np.array([image.shape[0], 0, 1])
# x2y2 = M @ np.array([image.shape[0], image.shape[1], 1])
#
# border_points = np.vstack((x1y1, x1y2, x2y1, x2y2))
# print(x1y1, x1y2, x2y1, x2y2)
# x_min = min(border_points[:,0])
# x_max = max(border_points[:,0])
# y_min = min(border_points[:,1])
# y_max = max(border_points[:,1])
#
# new_width = round(x_max-x_min)
# new_height = round(y_max-y_min)
#
# result = cv2.warpAffine(image_shift.copy(), M, (500, 500))
#
#
# return result
def apply_warpAffine(image, points1, points2) -> np.ndarray:
"""
Применить афинное преобразование согласно переходу точек points1 -> points2 и
преобразовать размер изображения.
:param image:
:param points1:
:param points2:
:return: преобразованное изображение
"""
M = cv2.getAffineTransform(points1, points2)
h, w, _ = image.shape
x1y1 = M @ np.array([0,0,1]).T
x1y2 = M @ np.array([0, h, 1]).T
x2y1 = M @ np.array([w, 0, 1]).T
x2y2 = M @ np.array([w, h, 1]).T
border_points = np.vstack((x1y1, x1y2, x2y1, x2y2))
x_min = min(border_points[:,0])
x_max = max(border_points[:,0])
y_min = min(border_points[:,1])
y_max = max(border_points[:,1])
M[0, 2] -= x_min
M[1, 2] -= y_min
image = cv2.warpAffine(image.copy(), M, (round(x_max - x_min), round(y_max - y_min)))
return image
if __name__ == '__main__':
test_image = cv2.imread('task_3/lk.jpg')
test_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)
test_point_1 = np.float32([[50, 50], [400, 50], [50, 200]])
test_point_2 = np.float32([[100, 100], [200, 20], [100, 250]])
transformed_image = apply_warpAffine(test_image, test_point_1, test_point_2)
plot_one_image(transformed_image)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment