I need to create a tridimensional map. I would create an x axis with values between 0 and 255 with step 0.5. The same thing with the y axis.
And then I would assign a value for each coordinate (for example at the point (10.5,10)).
Matrix is not the solution because I can't decide values in the x and y axes.
Can you help me?
EDIT: I try to explain better the question. This is a piece of my code:
img = cv2.imread('Lena256.bmp',0)
M = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)
img_rotate = cv2.warpAffine(img,M,(cols,rows))
Then I locate some point in the img_rotate: for example p=(10,10). I want to map "p" to the corresponding point in the original image. To do that I have written this code:
T = np.zeros((rows,cols))
T[10][10] = 1
M_INV = cv2.getRotationMatrix2D((cols/2,rows/2),-angle,1)
T = cv2.warpAffine(T,M_INV,(cols,rows))
In this way it works. But if I locate a point with no integer coordinates (in the img_rotate), for example (10.5,10), I should to create a matrix T with double dimensions where I could assign values 0, 0.5, 1, ecc in order to identify point (10.5,10). And then I could apply the inverse rotation.
I hope to be enough clear
You could use a dictionary:
d = {
(10.5, 10): 23,
(0,0): 42,
(-100,999): 15,
#etc
}
Then you can access the value at some coordinates (x,y) by doing d[x,y]. (or d.get((x,y), default_value_goes_here) if you're not sure whether that coordinate exists in the collection yet)
you can use np.meshgrid for that
import numpy as np
x_ = np.linspace(0., .5, 255)
y_ = np.linspace(1., .5, 255)
# You can make what you want in z ex:
z_ = np.linspace(3., 4., 30)
x, y, z = np.meshgrid(x_, y_, z_, indexing='ij')
Related
I found an article which is about epipolar geometry.
I calculated the fundamental matrix. Now Iam trying to find the line on which a corresponding point lays as described in the article:
I calculated the line which is in homogeneous coordinates. How could I plot this line into the picture like in the example? I thought about transforming the line from homogeneous to inhomogeneous coordinates. I think this can be achieved by dividing x and y by z
For example, homogeneous:
x=0.0295
y=0.9996
z=-265.1531
to inhomogeneous:
x=0.0295/-265.1531
y=0.9996/-265.1531
so:
x=-0.0001112564778612809
y=0.0037698974667842843
Those numbers seem wrong to me, because theyre so small. Is this the correct approach?
How could I plot my result into an image?
the x, y and z you have are the parameters of the "Epipolar Lines" equation that appear under the "line in the image" formula in the slides, but labelled a, b and c respectively, i.e:
au + bv + c = 0
solutions to this are points on the line. e.g. in Python I'd define a as some points on the picture's x-axis, and solve for b:
import numpy as np
F = np.array([
[-0.00310695, -0.0025646, 2.96584],
[-0.028094, -0.00771621, 56.3813],
[13.1905, -29.2007, -9999.79],
])
p_l = np.array([
[343.53],
[221.70],
[ 1.0],
])
lt = F # p_l
# if you want to normalise
lt /= np.sqrt(sum(lt[:2] ** 2))
# should give your values [0.0295, 0.9996, -265.2]
print(lt)
a, b, c = lt.ravel()
x = np.array([0, 400])
y = -(x*a + c) / b
and then just draw a line between these points
I have a 2D Numpy array that represents an image, and I want to create a surface plot of image intensity using matplotlib.surface_plot. For this function, I need to convert the 2D array A[x,y] => z into three arrays: [x0,...,xN], [y0,...,yN] and [z0,...,zN]. I can see how to do this conversion element-by-element:
X = []
Y = []
Z = []
for x in range( A.shape[ 0 ] ):
for y in range( A.shape[ 1 ] ):
X.append( x )
Y.append( y )
Z.append( A[x,y] )
but I'm wondering whether there is a more Pythonic way to do this?
a very simple way to do this could be to basically use the code shown in the matplotlib example. assuming x and y representing the sizes of the two dims in your image array A, you could do
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
# generate some input data that looks nice on a color map:
A = np.mgrid[0:10:0.1,0:10:0.1][0]
X = np.arange(0, A.shape[0], 1)
Y = np.arange(0, A.shape[1], 1)
X, Y = np.meshgrid(X, Y)
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, A, cmap='viridis',
linewidth=0, antialiased=False)
gives
You possibly don't need to construct the actual grid, because some pyplot functions accept 1d arrays for x and y, implying that a grid is to be constructed. It seems that Axes3D.plot_surface (which I presume you meant) does need 2d arrays as input, though.
So to get your grid the easiest way is using np.indices to get the indices corresponding to your array:
>>> import numpy as np
...
... # dummy data
... A = np.random.random((3,4)) # randoms of shape (3,4)
...
... # get indices
... x,y = np.indices(A.shape) # both arrays have shape (3,4)
...
... # prove that the indices correspond to the values of A
... print(all(A[i,j] == A[x[i,j], y[i,j]] for i in x.ravel() for j in y.ravel()))
True
The resulting arrays all have the same shape as A, which should be correct for most use cases. If for any reason you really need a flattened 1d array, you should use x.ravel() etc. to get a flattened view of the same 2d array.
I should note though that the standard way to visualize images (due to the short-wavelength variation of the data) is pyplot.imshow or pyplot.pcolormesh which can give you pixel-perfect visualization, albeit in two dimensions.
We agree X, Y and Z have different sizes (N for X and Y and N^2 for Z) ? If yes:
X looks not correct (you add several times the same values)
something like:
X = list(range(A.shape[0])
Y = list(range(A.shape[1])
Z = [A[x,y] for x in X for y in Y]
I am converting mesh-grid points (2D Maze) into Adjacency matrix which I will use later to find the shortest path between the given coordinates. Please have a look into my code:
import numpy as np
import numpy.matlib #for matrices
def cutblocks(xv,yv,allBlocks):
x_new,y_new = np.copy(xv), np.copy(yv)
ori_x,ori_y = xv[0][0], yv[0][0]
for block in allBlocks:
block = sorted(block)
block_xmin = np.min((block[0][0], block[2][0]))
block_xmax = np.max((block[0][0], block[2][0]))
block_ymin = np.min((block[0][1], block[1][1]))
block_ymax = np.max((block[0][1], block[1][1]))
rx_min, rx_max = int((block_xmin-ori_x)/stepSize)+1, int((block_xmax-ori_x)/stepSize)+1
ry_min, ry_max = int((block_ymin-ori_y)/stepSize)+1, int((block_ymax-ori_y)/stepSize)+1
for i in range(rx_min,rx_max):
for j in range(ry_min,ry_max):
x_new[j][i] = np.nan
for i in range(ry_min,ry_max):
for j in range(rx_min,rx_max):
y_new[i][j] = np.nan
return x_new, y_new
stepSize = 0.2
##Blocks that should be disabled
allBlocks = [[(139.6, 93.6), (143.6, 93.6), (143.6, 97.6), (139.6, 97.6)],
[(154.2, 93.4), (158.2, 93.4), (158.2, 97.4), (154.2, 97.4)],
[(139.2, 77.8), (143.2, 77.8), (143.2, 81.8), (139.2, 81.8)],
[(154.2, 77.8), (158.2, 77.8), (158.2, 81.8), (154.2, 81.8)],
[(139.79999999999998, 86.4),
(142.6, 86.4),
(142.6, 88.0),
(139.79999999999998, 88.0)],
[(154.79999999999998, 87.2),
(157.6, 87.2),
(157.6, 88.8),
(154.79999999999998, 88.8)]]
x = np.arange(136.0, 161.0, stepSize)
y = np.arange(75.0, 101.0, stepSize)
xv, yv = np.meshgrid(x, y)
xv, yv = cutblocks(xv,yv,allBlocks)
MazeSize = xv.shape[0]*xv.shape[1]
adj = np.matlib.zeros((MazeSize,MazeSize)) #initialize AdjacencyMatrix
#make 1 whenever there is a connection between neighboring coordinates
mazeR, mazeC = 0,0
for row in range(xv.shape[0]):
for col in range(xv.shape[1]):
if xv[row][col]>0 and col+1<xv.shape[1] and round(np.abs(xv[row][col] - xv[row][col+1]),2) == stepSize:
adj[mazeR,mazeC+1] = 1
break
mazeC = mazeC+1
mazeR = mazeR+1
This code generates a mesh-grid in which some of the points are disabled because they are walls in the maze. The cost for every step (between connected vertices) is 1. My questions are:
1) The adjacency Matrix would be N.N and N=x.y (. is multiply). is that correct?
2) What could be the efficient way of finding and assigning the neighbors to values 1 in the adjacency matrix. ( I tried it but it doesn't work correctly)
3) Should I use graphs for this kind of problems ? My final goal is find the shortest path between the 2 coordinates (vertices).
Thanks
I'm trying to register two 3d volumes. An attempt at this can found here. The code first generates two different volumes, both containing exactly one sphere of radius 4. I'm then trying to align them using the default translation parameter map. However, as can be seen in the last line (and from the plots if running locally), the result volume is not aligned with the fixed volume at all. When attempting the same procedure, in 2d this time, the resulting image does appear to be correctly aligned with the fixed image, as can be seen here. Am I using the SimpleElastix API incorrectly? I looked through the Github repo of SimpleElastix, but I could not find any examples of 3d image registration (at least not using volumes generated in Python and then converting them to ITK images).
Code from 3d example:
vol1 = np.zeros((50, 50, 50))
for x in range(vol.shape[0]):
for y in range(vol.shape[1]):
for z in range(vol.shape[2]):
vol1[x, y, z] = np.linalg.norm(np.subtract([x, y, z], [5, 3, 2])) < 4
vol2 = np.zeros((50, 50, 50))
for x in range(vol.shape[0]):
for y in range(vol.shape[1]):
for z in range(vol.shape[2]):
vol1[x, y, z] = np.linalg.norm(np.subtract([x, y, z], [20, 30, 10])) < 4
img_a = sitk.GetImageFromArray(vol1)
img_b = sitk.GetImageFromArray(vol2)
parameterMap = sitk.GetDefaultParameterMap('translation')
itk_filter = sitk.ElastixImageFilter()
itk_filter.LogToConsoleOn()
itk_filter.SetFixedImage(img_a)
itk_filter.SetMovingImage(img_b)
itk_filter.SetParameterMap(parameterMap)
itk_filter.Execute()
result_vol = sitk.GetArrayFromImage(itk_filter.GetResultImage())
np.max(np.abs(vol1 - result_vol))
Code from 2d example:
vol1 = np.zeros((50, 50))
for x in range(vol1.shape[0]):
for y in range(vol1.shape[1]):
vol1[x, y] = np.linalg.norm(np.subtract([x, y], [20, 20])) < 4
vol2 = np.zeros((50, 50))
for x in range(vol2.shape[0]):
for y in range(vol2.shape[1]):
vol2[x, y] = np.linalg.norm(np.subtract([x, y], [4, 5])) < 4
img_a = sitk.GetImageFromArray(vol1)
img_b = sitk.GetImageFromArray(vol2)
parameterMap = sitk.GetDefaultParameterMap('translation')
itk_filter = sitk.ElastixImageFilter()
itk_filter.LogToConsoleOn()
itk_filter.SetFixedImage(img_a)
itk_filter.SetMovingImage(img_b)
itk_filter.SetParameterMap(parameterMap)
itk_filter.Execute()
result_vol = sitk.GetArrayFromImage(itk_filter.GetResultImage())
np.max(np.abs(vol1 - result_vol))
The registration probably fails because the spheres do not overlap. You could try to smooth the images a bit more using e.g. sitk.DiscreteGaussian(). However, in this artificial example it is highly likely that simply moving the spheres closer to each other would result in a good registration.
Note it is difficult to register binary images as there is very little gradient information in these kinds of images: Gradients are non-zero at the border only, and zero everywhere else because of the regions are flat intensity-wise.
Very similar to RBF interpolation fails: LinAlgError: singular matrix but I think the problem is different, as I have no duplicated coordinates.
Toy example:
import numpy as np
import scipy.interpolate as interp
coords = (np.array([-1, 0, 1]), np.array([-2, 0, 2]), np.array([-1, 0, 1]))
coords_mesh = np.meshgrid(*coords, indexing="ij")
fn_value = np.power(coords_mesh[0], 2) + coords_mesh[1]*coords_mesh[2] # F(x, y, z)
coords_array = np.vstack([x.flatten() for x in coords_mesh]).T # Columns are x, y, z
unique_coords_array = np.vstack({tuple(row) for row in coords_array})
unique_coords_array.shape == coords_array.shape # True, i.e. no duplicate coords
my_grid_interp = interp.RegularGridInterpolator(points=coords, values=fn_value)
my_grid_interp(np.array([0, 0, 0])) # Runs without error
my_rbf_interp = interp.Rbf(*[x.flatten() for x in coords_mesh], d=fn_value.flatten())
## Error: numpy.linalg.linalg.LinAlgError: singular matrix -- why?
What am I missing? The example above uses the function F(x, y, z) = x^2 + y*z. I'd like to use Rbf to approximate that function. As far as I can tell there are no duplicate coordinates: compare unique_coords_array to coords_array.
I believe the problem is your input:
my_rbf_interp = interp.Rbf(*[x.flatten() for x in coords_mesh],d=fn_value.flatten())
Should you change to:
x,y,z = [x.flatten() for x in coords_mesh]
my_rbf_interp = interp.Rbf(x,y,z,fn_value.flatten())
And it should work. I think your original formulation is repeating lines in the matrix that goes for solve and thus having a very similar problem to duplicates (i.e. Singular Matrix).
Also if you would do:
d = fn_value.flatten()
my_rbf_interp = interp.Rbf(*(x,y,z,d))
It should work also.