I have an image stored in a numpy array. I have created a function to rotate that data by an angle theta. To perform the rotation the function converts the index coordinates of the image (i,j) to (x,y) and applies a rotation matrix. Then the function returns a meshgrid for the rotated (X, Y) coordinates.
I would like to overlay the non-rotated image and the rotated image on the same coordinate system and extract specific vertical & horizontal profiles. I cannot navigate the rotated image properly because it can only be navigated with 'ij' using the map_coordinates function(as far as I know).
Setup and function definitions:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt
def rotate_image(arr, dpi, theta_degrees = 0.0, pivot_point = [0,0]):
theta_radians = (np.pi/180.0)* theta_degrees
c = round(np.cos(theta_radians), 3)
s = round(np.sin(theta_radians), 3)
rotation_matrix = np.array([[c, -s, 0],
[s, c, 0],
[0, 0, 1]])
#print(rotation_matrix)
width, height = arr.shape
pivot_point_xy = np.array([(25.4 / dpi[0])* pivot_point[0], (25.4/dpi[1])*pivot_point[1]])
pivot_shift_vector = np.array([[pivot_point_xy[0]],
[pivot_point_xy[1]],
[0]])
x = (25.4 / dpi[0]) * np.array(range(width)) #convert pixels to mm units
y = (25.4 / dpi[1]) * np.array(range(height))#convert pixels to mm units
XX , YY = np.meshgrid(x,y)
ZZ = arr
coordinates = np.stack([XX,YY,ZZ])
#shift to rotation point, apply rotation, shift back to original coordinates
coordinates_reshape = np.reshape(coordinates, (3,-1))
translated_coordinates = coordinates_reshape - pivot_shift_vector
rotated_coordinates = np.matmul(rotation_matrix, translated_coordinates)
final_coordinates = rotated_coordinates + pivot_shift_vector
final_coordinates_reshaped = np.reshape(final_coordinates, (3, width, height))
return final_coordinates_reshaped
Example plots:
img = np.arange(1,26).reshape((5,5))
rotated_img_0 = rotate_image(img, theta_degrees= 0, dpi =[1,1], pivot_point = [2.5,2.5])
rotated_img_1 = rotate_image(img, theta_degrees= 45, dpi =[1,1], pivot_point = [2.5,2.5])
# plot
fig, ax = plt.subplots(2, 1, figsize = (10,20))
ax[0].pcolormesh(*rotated_img_0, vmin=0, vmax=rotated_img_0[2].max())
ax[0].pcolormesh(*rotated_img_1, vmin=0, vmax=rotated_img_1[2].max(), alpha = 0.7)
ax[0].hlines(60, rotated_img_1[0].min(), rotated_img_1[0].max() , color = 'black')
ax[1].contourf(*rotated_img_0, vmin=0, vmax=rotated_img_0[2].max())
ax[1].contourf(*rotated_img_1, vmin=0, vmax=rotated_img_1[2].max(), alpha = 0.7)
ax[1].hlines(60, rotated_img_1[0].min(), rotated_img_1[0].max() , color = 'black')
plt.show()
I tried to adapt from scipy the interpolate2d methods outlined here but it doesn't work on rotated data: https://docs.scipy.org/doc//scipy-0.17.0/reference/generated/scipy.interpolate.interp2d.html
Map_coordinates also works on the non-rotated data using 'ij' coordinates. Simple slicing of i,j would also be ok for my purposes.
I would like to be able to extract the same profile from each chart at the same xy coordinates.
Although this isn't a direct answer I decided that it was best to go around the problem. I rewrote the rotate_image function so that simple array slicing can be used to extract the profiles using map_coordinates function.
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
def rotate_image(img, theta_degrees = 0.0, pivot_point = np.array([[0],
[0]])):
width , height = img.shape
#compute the 2D rotation matrix
theta_radians = (np.pi/180.0)* theta_degrees
c = round(np.cos(theta_radians), 3)
s = round(np.sin(theta_radians), 3)
rotation_matrix = np.array([[c, -s],
[s, c]])
#create a sampling point cloud using meshgrid
X, Y = range(width), range(height)
XX , YY = np.meshgrid(X, Y)
coordinates = np.stack([XX, YY])
coordinates_reshape = np.reshape(coordinates, (2,-1))
#rotate the image around the chosen pivot point
translated_coordinates = coordinates_reshape - pivot_point
rotated_coordinates = np.matmul(rotation_matrix,
translated_coordinates)
final_coordinates = rotated_coordinates + pivot_point
final_coordinates_reshaped = np.reshape(final_coordinates, (2, width,
height))
#use scipy map_coordinates function to resample the image at the new
#coordinates
rotated_image = ndimage.map_coordinates(img,
final_coordinates_reshaped, mode = 'constant')
return rotated_image
img = np.random.rand(100, 100)*100
rotated_img = rotate_image(img, 20, np.array([[50],[50]]))
#graph Results
fig, ax = plt.subplots(2,1)
ax[0].imshow(rotated_img)
ax[0].hlines(50, 0, 99)
ax[1].plot(rotated_img[50])