2

What I want to do is to rotate a 2D numpy array over a given angle. The approach I'm taking is using a rotation matrix. The rotation matrix I defined as:

angle = 65.
theta = (angle/180.) * numpy.pi

rotMatrix = numpy.array([[numpy.cos(theta), -numpy.sin(theta)], 
                         [numpy.sin(theta),  numpy.cos(theta)]])

The matrix I want to rotate is shaped (1002,1004). However, just for testing purposes I created a 2D array with shape (7,6)

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]])

Now, when I apply the rotation matrix on my 2D array I get the following error:

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):

What am I doing wrong?

1
  • 4
    This doesn't make sense. You can't rotate single numbers, you can only rotate co-ordinates. So you need co-ordinate pairs somewhere - i.e. the array should be sized (1002, 2). Commented Dec 30, 2013 at 13:40

5 Answers 5

8

You seem to be looking for scipy.ndimage.rotate, or similar. If you specifically want 90, 180, or 270 degree rotations, which do not require interpolation, then numpy.rot90 is better.

Sign up to request clarification or add additional context in comments.

Comments

7

Matrix dimensions will need to be compatible in order to obtain a matrix product. You are trying to multiply a 7x6 matrix with a 2x2 matrix. This is not mathematically coherent. It only really makes sense to apply a 2D rotation to a 2D vector to obtain the transformed coordinates.

The result of a matrix product is defined only when the left hand matrix has column count equal to right hand matrix row count.

4 Comments

How would I be able to rotate my (1002, 1004) array over any angle?
The outcome you seek does not really make sense. If you are trying to rotate vectors of such high dimension, you will need the appropriate multidimensional rotation matrix. A 2D rotation cannot be used to rotate a 1004 dimensional vector! Perhaps you are misunderstanding the distinction between a 2D array and a 2D coordinate system?
I have a camera image. This camera has 1002 by 1004 pixels. The data is represented by a 2D numpy array where each element denotes the intensity of a pixel thus creating the image. The image I have is a linear line which is tilted under an angle. I would like to get rid of this angle to simplify further python operations. The coordinates axis correspond to real time x and y.
Then it sounds like it is the pixel coordinates that you need to rotate, not the values inside them. Under a 2D rotation, it will be the pixel coordinates (x,y) that get rotated to a transformed pixel whose new coordinates will be (x',y'). It makes no sense to rotate the intensity values. It sounds like you need to create an output array and map the intensity values to these new coordinates - ie, intensity at (x,y) in your image will map to a point (x',y') in your output array where (x',y') is the rotated pixel coordinate. Practically this is a problem because a pixel grid is discrete
2

You may want to look at skimage.transform. This module has several useful functions including rotation. No sense in rewriting something that is already done.

Comments

1

I guess there is a misunderstanding. You cannot rotate an image by multiplying it with the rotation matrix. What you actually need to do is to multiply a matrix containing the image coordinates (of shape 2 x (n*m) for an image of shape n x m ) with the rotation matrix. This might look like this in 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()

Comments

0

You can not rotate any ndim vector using 2D matrix.

I did not find an in built function in numpy. I was hoping that this is a very common functionality and should be there. Let me know if you find it.

Mean while I have create function of my own.

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


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.