gpt4 book ai didi

python - 图像的二维旋转

转载 作者:行者123 更新时间:2023-12-03 23:59:59 27 4
gpt4 key购买 nike

Image while trying to do a 90 degrees rotation. Left one is original image.我正在尝试以任何给定的角度旋转图像。
我以图像的中心为原点旋转。
但是代码没有按预期进行旋转。
我附上下面的代码。

import math
import numpy as np
import cv2

im = cv2.imread("Samples\\baboon.jpg", cv2.IMREAD_GRAYSCALE)
new = np.zeros(im.shape,np.uint8)

new_x = im.shape[0] // 2
new_y = im.shape[1] // 2

x = int(input("Enter the angle : "))

trans_mat = np.array([[math.cos(x), math.sin(x), 0],[-math.sin(x), math.cos(x), 0],[0, 0, 1]])

for i in range(-new_x, im.shape[0] - new_x):
for j in range(-new_y, im.shape[1] - new_y):
vec = np.matmul([i, j, 1], trans_mat)
if round(vec[0] + new_x) < 512 and round(vec[1] + new_y) < 512:
new[round(vec[0]+new_x), round(vec[1]+new_y)] = im[i+new_x,j+new_y]

cv2.imshow("rot",new)
cv2.imshow("1",im)
cv2.waitKey(0)
cv2.destroyAllWindows()

最佳答案

看起来您正在尝试实现最近邻重采样器。您正在做的是遍历图像并将每个输入像素映射到输出图像中的新位置。这可能会导致诸如像素错误地相互覆盖、输出像素留空等问题。
我建议(根据经验)您正在向后看问题。与其查看输入像素在输出中的位置,不如考虑每个输出像素在输入中的位置。这样,您对最近的邻居就没有歧义,并且整个图像数组将被填充。
您想围绕中心旋转。您使用的当前旋转矩阵围绕 (0, 0) 旋转.为了弥补这一点,您需要将图像的中心转换为 (0, 0) ,旋转,然后平移回来。我不会开发完整的仿射矩阵,而是向您展示如何手动执行各个操作,然后如何将它们组合到变换矩阵中。
手工计算
首先得到一个输入和输出图像:

im = cv2.imread("Samples\\baboon.jpg", cv2.IMREAD_GRAYSCALE)
new = np.zeros_like(im)
然后确定旋转中心。清楚您的尺寸 x通常是列(dim 1),而不是行(dim 0):
center_row = im.shape[0] // 2
center_col = im.shape[1] // 2
计算图像中每个像素的径向坐标,形状为相应的维度:
row_coord = np.arange(im.shape[0])[:, None] - center_row
col_coord = np.arange(im.shape[1]) - center_col
row_coordcol_coord是与输出图像中心的距离。现在计算它们在输入中来自的位置。请注意,我们可以使用广播来避免循环的需要。我在这里遵循您对角度定义的原始约定,并找到反向旋转以确定源位置。这里的最大区别是度数的输入被转换为弧度,因为这是三角函数所期望的:
angle = float(input('Enter Angle in Degrees: ')) * np.pi / 180.0 
source_row = row_coord * np.cos(angle) - col_coord * np.sin(angle) + center_row
source_col = row_coord * np.sin(angle) + col_coord * np.cos(angle) + center_col
如果保证所有索引都在输入图像内,您甚至不需要预先分配输出。你真的可以做 new = im[source_row, source_col] .但是,您需要屏蔽索引:
mask = source_row >= 0 & source_row < im.shape[0] & source_col >= 0 & source_col < im.shape[1]
new[mask] = im[source_row[mask].round().astype(int), source_col[mask].round().astype(int)]
仿射变换
现在让我们来看看如何使用仿射变换。首先,您要从坐标中减去中心。假设您有一个列向量 [[r], [c], [1]] .转换为零将是矩阵
[[r']    [[1  0 -rc]  [[r]
[c'] = [0 1 -cc] . [c]
[1 ]] [0 0 1 ]] [1]]
然后应用(向后)旋转:
[[r'']    [[cos(a) -sin(a) 0]  [[r']
[c''] = [sin(a) cos(a) 0] . [c']
[ 1 ]] [ 0 0 1]] [1 ]]
最后,您需要转换回中心:
[[r''']    [[1  0 rc]  [[r'']
[c'''] = [0 1 cc] . [c'']
[ 1 ]] [0 0 1]] [ 1 ]]
如果你将这三个矩阵从右到左依次相乘,你会得到
   [[cos(a)   -sin(a)    cc * sin(a) - rc * cos(a) + rc]
M = [sin(a) cos(a) -cc * cos(a) - rc * sin(a) + cc]
[ 0 0 1 ]]
如果你构建一个完整的输出坐标矩阵而不是我们开始的子集数组,你可以使用 np.matmul ,又名 @运算符为您做乘法。但是,对于这样一个简单的情况,不需要这种复杂程度:
matrix = np.array([[np.cos(angle), -np.sin(angle),  col_center * np.sin(angle) - row_center * np.cos(angle) + row_center],
[np.sin(angle), np.cos(angle), -col_center * np.cos(angle) - row_center * np.sin(angle) + col_center],
[0, 0, 1]])

coord = np.ones((*im.shape, 3, 1))
coord[..., 0, :] = np.arange(im.shape[0]).reshape(-1, 1, 1, 1)
coord[..., 1, :] = np.arange(im.shape[1]).reshape(-1, 1, 1)

source = (matrix @ coord)[..., :2, 0]
其余的处理与手动计算非常相似:
mask = (source >= 0 & source_row < im.shape).all(axis=-1)
new[mask] = im[source[0, mask].round().astype(int), source_col[1, mask].round().astype(int)]

关于python - 图像的二维旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63383183/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com