我想要做的是将 2D numpy 数组旋转给定角度。我采用的方法是使用旋转矩阵。我定义的旋转矩阵为:
angle = 65.
theta = (angle/180.) * numpy.pi
rotMatrix = numpy.array([[numpy.cos(theta), -numpy.sin(theta)],
[numpy.sin(theta), numpy.cos(theta)]])
我要旋转的矩阵形状为(1002,1004)。然而,仅出于测试目的,我创建了一个形状为 (7,6) 的 2D 数组
c = numpy.array([[0,0,6,0,6,0], [0,0,0,8,7,0], [0,0,0,0,5,0], [0,0,0,3,4,0], [0,0,2,0,1,0], [0,8,0,0,9,0], [0,0,0,0,15,0]])
现在,当我在 2D 数组上应用旋转矩阵时,出现以下错误:
c = numpy.dot(rotMatrix, c)
print c
c = numpy.dot(rotMatrix, c)
ValueError: matrices are not aligned
Exception in thread Thread-1 (most likely raised during interpreter shutdown):
我做错了什么?
您似乎正在寻找 scipy.ndimage.rotate 或类似的。如果您特别想要 90、180 或 270 度旋转(不需要插值),那么 numpy.rot90 更好。
矩阵维度需要兼容才能获得矩阵乘积。您正在尝试将 7x6 矩阵与 2x2 矩阵相乘。这在数学上是不连贯的。只有对 2D 向量应用 2D 旋转以获得变换后的坐标才真正有意义。
仅当左手矩阵的列数等于右手矩阵的行数时,矩阵乘积的结果才被定义。
您可能想查看skimage.transform。该模块有几个有用的功能,包括旋转。重写已经完成的事情是没有意义的。
我想这里面有一个误会。您不能通过将图像与旋转矩阵相乘来旋转图像。您实际上需要做的是将包含图像坐标的矩阵(对于形状为
2 x (n*m)
的图像,形状为 n x m
)与旋转矩阵相乘。
这在 numpy 中可能看起来像这样:
import numpy as np
image = np.arange(10000).reshape((100, 100))
theta = np.radians(180) # rotate 180 degrees
rot_matrix = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
# some steps to create coordinate matrix
x_len, y_len = image.shape
x_range = np.arange(x_len)
y_range = np.arange(y_len)
x_coords, y_coords = np.meshgrid(x_range, y_range)
coordinates = np.vstack([x_coords.flatten(), y_coords.flatten()])
# example for coordniates for image with shape n x n like:
# x: x0, x1, x2, ... xn-2, xn-1, xn
# y: y0, y1, y2, ... yn-2, yn-1, yn
# here we apply matrix multiplication
rotated_coordinates = rot_matrix @ coordinates
rotated_coordinates = rotated_coordinates.astype(int)
rotated_image = np.zeros(image.shape)
# This might generate missing values that need to be interpolated! Will be skipped here
rotated_image[rotated_coordinates[0], rotated_coordinates[1]] = image.flatten()
您无法使用 2D 矩阵旋转任何 ndim 向量。
我没有在 numpy 中找到内置函数。我希望这是一个非常常见的功能并且应该存在。如果你找到了请告诉我。
也就是说,我有自己的创建功能。
def rotate(vector, theta, rotation_around=None) -> np.ndarray:
"""
reference: https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions
:param vector: list of length 2 OR
list of list where inner list has size 2 OR
1D numpy array of length 2 OR
2D numpy array of size (number of points, 2)
:param theta: rotation angle in degree (+ve value of anti-clockwise rotation)
:param rotation_around: "vector" will be rotated around this point,
otherwise [0, 0] will be considered as rotation axis
:return: rotated "vector" about "theta" degree around rotation
axis "rotation_around" numpy array
"""
vector = np.array(vector)
if vector.ndim == 1:
vector = vector[np.newaxis, :]
if rotation_around is not None:
vector = vector - rotation_around
vector = vector.T
theta = np.radians(theta)
rotation_matrix = np.array([
[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]
])
output: np.ndarray = (rotation_matrix @ vector).T
if rotation_around is not None:
output = output + rotation_around
return output.squeeze()
if __name__ == '__main__':
angle = 30
print(rotate([1, 0], 30)) # passing one point
print(rotate([[1, 0], [0, 1]], 30)) # passing multiple points