I have matrix filled with zeros and a rectangle filled by ones on a region of this matrix, like this
and I want to rotate the rectangle to an arbitrary angle (30° in this case) like this
import numpy as np
import matplotlib.pyplot as plt
n_x = 200
n_y = 200
data = np.zeros((n_x, n_y))
data[20:50, 20:40] = 1
plt.imshow(data)
plt.show()
How about using scipy?
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import rotate
n_x = 200
n_y = 200
data = np.zeros((n_x, n_y))
data[20:50, 20:40] = 1
angle = 30
data = rotate(data, angle)
plt.imshow(data)
plt.show()
Of course this is around the middle of the image. If you want to rotate around the center of the rectangle, I would suggest translating it to the middle of the image, rotate it and then translate it back.
From a mathematical point of view you could solve the problem by transforming
the cartesian coordinates of the ones into polar coordinates relative to the center of the rectangle.
r = sqrt(x²+y²)
phi = atan2(y,x)
(Note that x and y have to be relative to the center of rotation)
With polar coordinates it is no problem to rotate, since you just have to add the desired angle to phi and than transform back into cartesian coordinates.
x = r*cos(phi)
y = r*sin(phi)
(And again, the resulting coordinates would be with respect to the center of rotation, so you need to add them to the cartesian vector which points to the center)
Related
Given the sphere center coordinates and radius and the image in 3D how to get all pixels within the sphere using numpy in python ?
Assuming for the 3D image we have indicesX, indicesY, indicesZ arrays containing the pixels coordinates over X,Y and Z axis, centerX, centerY, centerZ contains the coordinates of center for the sphere and r is the radius.
One way you could do this is to construct a boolean mask using the equation for a sphere
mask = (np.square(indicesX - centerX) + np.square(indicesY - centerY) + np.square(indicesZ - centerZ)) <= np.square(r)
indicesX_in_sphere = indicesX[mask]
indicesY_in_sphere = indicesY[mask]
indicesZ_in_sphere = indicesZ[mask]
or you could use the mask directly on the values of the 3D image depending on your needs.
I have the following problem: I have a 3d numpy array representing a stack of images. I also have a point cloud (n,3) of some relevant locations in the 3d array, which I have plotted in there. I want to rotate both by an angle around the x-axis. I do the following:
#for point cloud
rotation_matrix = scipy.spatial.transform.Rotation.from_euler('x', x_rot, degrees=True)
rotated_stack_points = rotation_matrix.apply(stack_points)
#for 3d stack
rotated_marked_xy = scipy.ndimage.interpolation.rotate(gfp_stack, angle=-x_rot, axes=(1, 2), reshape=True)
Then I plot the rotated point cloud in the rotated 3d array. The problem is that there is always a xy offset between the points plotted pre rotation and after rotation and can't figure out why. This offset changes with the rotation angle, it's not fixed. Any ideas why this happens?
If you rotate by the same angle with different centers of rotation one output will be translated compared to the other.
The rotation matrix obtained by from euler will perform a rotation centered at the origin.
import scipy.spatial.transform
rotation_matrix = scipy.spatial.transform.Rotation.from_euler('x', 30, degrees=True)
rotation_matrix.apply([0,0,0])
The ndimage.rotate method rotates around the center of the image, and the reshape=True will extend the borders so that the corners lie in the new box.
import scipy.ndimage
import numpy as np
import matplotlib.pyplot as plt
x = np.ones((3, 100, 100))
xr = scipy.ndimage.rotate(x, 30, axes=(1,2))
plt.imshow(xr[0])
xr.shape
(3, 137, 137)
You can change the center of rotation by applying translate(-c) rotate translate(+c) sequence
I have a numpy array for an image that I read in from a FITS file. I rotated it by N degrees using scipy.ndimage.interpolation.rotate. Then I want to figure out where some point (x,y) in the original non-rotated frame ends up in the rotated image -- i.e., what are the rotated frame coordinates (x',y')?
This should be a very simple rotation matrix problem but if I do the usual mathematical or programming based rotation equations, the new (x',y') do not end up where they originally were. I suspect this has something to do with needing a translation matrix as well because the scipy rotate function is based on the origin (0,0) rather than the actual center of the image array.
Can someone please tell me how to get the rotated frame (x',y')? As an example, you could use
from scipy import misc
from scipy.ndimage import rotate
data_orig = misc.face()
data_rot = rotate(data_orig,66) # data array
x0,y0 = 580,300 # left eye; (xrot,yrot) should point there
P.S. The following two related questions' answers do not help me:
Find new coordinates of a point after rotation
New coordinates after image rotation using scipy.ndimage.rotate
As usual with rotations, one needs to translate to the origin, then rotate, then translate back. Here, we can take the center of the image as origin.
import numpy as np
import matplotlib.pyplot as plt
from scipy import misc
from scipy.ndimage import rotate
data_orig = misc.face()
x0,y0 = 580,300 # left eye; (xrot,yrot) should point there
def rot(image, xy, angle):
im_rot = rotate(image,angle)
org_center = (np.array(image.shape[:2][::-1])-1)/2.
rot_center = (np.array(im_rot.shape[:2][::-1])-1)/2.
org = xy-org_center
a = np.deg2rad(angle)
new = np.array([org[0]*np.cos(a) + org[1]*np.sin(a),
-org[0]*np.sin(a) + org[1]*np.cos(a) ])
return im_rot, new+rot_center
fig,axes = plt.subplots(2,2)
axes[0,0].imshow(data_orig)
axes[0,0].scatter(x0,y0,c="r" )
axes[0,0].set_title("original")
for i, angle in enumerate([66,-32,90]):
data_rot, (x1,y1) = rot(data_orig, np.array([x0,y0]), angle)
axes.flatten()[i+1].imshow(data_rot)
axes.flatten()[i+1].scatter(x1,y1,c="r" )
axes.flatten()[i+1].set_title("Rotation: {}deg".format(angle))
plt.show()
I have to analyze the data given as an image like:
What I do is
Earasing the axises manually.
Convert the image to (x,y) coordinates by imagemagick (collecting the coordinates of black pixels)
Adjusting the (x,y) values (according to the axis values (rather than the pixel coordinates), then y direction: in images, the y coordinate increases from top to bottom).
Sorting the data by x.
Loading the data in a SciPy script.
I wonder if there is a function to do any of the steps 1-4 in the same SciPy script.
Since SciPy has a range of functions for image recognition, I would like to know if there is a function to translate an image into the (x,y) coordinates of the black pixels creating the curve, and so on.
First, load the image with sp.misc.imread or PIL so that it resides in a numpy array that I'll refer to as img below. (If it is a color image convert it to grayscale with img = np.mean(img, axis=-1). Then:
img = img[:-k, :] # Erase axes manually, k is the height of the axis in pixels
y, x = np.where(img == 0) # Find x and y coordinates of all black pixels
y -= y.max() # invert y axis so (0,0) is in the bottom left corner
i = np.argsort(x); x, y = x[i], y[i] # Sort data by x
Assumed imports:
import numpy as np
import scipy as sp
I have a number of polygons in 3d from a geojson file, and I would like to make an elevation model. This means that I want a raster, where every pixel is the height of the polygon in this position.
I tried looking at gdal_rasterize, but the description says
As of now, only points and lines are drawn in 3D.
gdal_rasterize
I ended up using the scipy.interpolat-function called griddata. This uses a meshgrid to get the coordinates in the grid, and I had to tile it up because of memory restrictions of meshgrid.
import scipy.interpolate as il #for griddata
# meshgrid of coords in this tile
gridX, gridY = np.meshgrid(xi[c*tcols:(c+1)*tcols], yi[r*trows:(r+1)*trows][::-1])
## Creating the DEM in this tile
zi = il.griddata((coordsT[0], coordsT[1]), coordsT[2], (gridX, gridY),method='linear',fill_value = nodata) # fill_value to prevent NaN at polygon outline
The linear interpolation seems to do exactly what I want. See description at https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html