I am currently working on eeg signals, so here basically we have electrodes which are placed on head of a person and we get 3d coordinates of each electrodes so basically i am trying to find 2d coordinates from these 3d coordinates but with the help of equirectangular projection ( the same way how we project globe on a plane paper).
Here are the few links for better understanding:
https://www.earthdatascience.org/courses/use-data-open-source-python/intro-vector-data-python/spatial-data-vector-shapefiles/geographic-vs-projected-coordinate-reference-systems-python/
https://www.coursera.org/lecture/introduction-gis-mapping/associating-points-from-3d-to-2d-y7kIx
https://mathworld.wolfram.com/MercatorProjection.html
I think it should be the following but maybe you can confirm if this is correct:
import math
def cartesian_to_spherical(x,y,z):
r=math.sqrt(x**2+y**2+z**2)
theta=math.acos(z/r)
phi=math.atan(y/x)
return r,theta,phi
def spherical_to_mercator(r,theta,phi):
x=theta
y=0.5*math.log((1+math.sin(phi))/(1-math.sin(phi)))
return x,y
r,theta,phi=cartesian_to_spherical(2,3,1) # fill in your x,y,z here
x,y=spherical_to_mercator(r,theta,phi)
print("x = ",x," y = ",y)
Related
I need to rotate a polygon (which I am provided as a KML file) on a map, so that its shape remains the same.
Here is the function I use on each coordinate in turn to perform the rotation:
def rotate(
points,
origin,
angle
):
# Convert to radians:
rotation_angle = np.deg2rad(angle)
# Build transformer:
R = np.array([[np.cos(rotation_angle), -np.sin(rotation_angle)], [np.sin(rotation_angle), np.cos(rotation_angle)]])
# Convert list to at least 2 dimension arrays...
o = np.atleast_2d(origin)
p = np.atleast_2d(points)
# Return transformed points:
return np.squeeze((R # (p.T-o.T) + o.T).T)
When I perform this on all the coordinates in a rectangle and rotate 90 degrees anti-clockwise, I get a parallelogram. I am thinking this is because the scaling of distances along the arc between two lines of latitude and longitude are different.
Here is an example of what I am seeing:
The green rectangle is the original shape, the red parallelogram is the rotated shape, and the origin is shown for ease of understanding.
I have spent too long trying to make this work and there is obviously a simple way to achieve this which both I and trusty Google are missing!
I have several pairs of images + cloud of 3D points that correspond to the same view. There are no rules for the change of coordinates. Everything is stored in a table.
Rows : image x coordinate
Columns : image y coordinate
Cell: 3D points (x,y,z) coordinates.
Practically, this is a NumPy array of dimensions (1920, 1080, 3).
The other way around, finding the coordinate of the 3D point when you have the coordinate in the image is pretty straightforward.
def image_to_xyz(self,image_points):
"""
Takes a point in the image
Return corresponding xyz coordinates
"""
xyz = self.xyz
image_points_x = image_points[:,0]
image_points_y = image_points[:,1]
xyz_points = xyz[image_points_x,image_points_y]
return xyz_points
For the other way around, it is easy, but dirty, to make a for loop and search for a corresponding point with a precision threshold. I tried it.
It's in python, I can't use Julia, so the loop took several minutes to complete. Way too much...
Do you have better suggestions?
Thanks
I have a vector field that is defined in a 2D plane. This means that the Z component of the position is constant, but vectors are 3D. I have plotted this using quiver3 as below:
[X,Y] = meshgrid(-pi/2:pi/8:pi/2,-pi/2:pi/8:pi/2);
Z=ones(size(X));
U=rand(size(X));
V=rand(size(X));
W=rand(size(X));
H=quiver3(X,Y,Z,U,V,W,'r');
H.ShowArrowHead = 'off';
The above code does the job, but it does not look good. Is it possible to represent the vector field like the below picture with 3D rods?
the below code transforms a detected 2D-image point to it's 3D location on a defined plane Grid in 3D-world.
This mean Z=0, and taking into account that the Extrinsics and Intrinsics are known, we can compute the corresponding 3D_point of the detected 2D-image point:
import cv2
import numpy as np
#load extrinsics & intrinsics
with np.load('parameters_cam1.npz') as X:
mtx, dist = [X[i] for i in ('mtx','dist','rvecs','tvecs')]
with np.load('extrincic.npz') as X:
rvecs1,tvecs1 = [X[i] for i in('rvecs1','tvecs1')]
#prepare rotation matrix
R_mtx, jac=cv2.Rodrigues(rvecs1)
#prepare projection matrix
Extrincic=cv2.hconcat([R_mtx,tvecs1])
Projection_mtx=mtx.dot(Extrincic)
#delete the third column since Z=0
Projection_mtx = np.delete(Projection_mtx, 2, 1)
#finding the inverse of the matrix
Inv_Projection = np.linalg.inv(Projection_mtx)
#detected image point (extracted from a que)
img_point=np.array([pts1_blue[0]])
#adding dimension 1 in order for the math to be correct (homogeneous coordinates)
img_point=np.vstack((img_point,np.array(1)))
#calculating the 3D point which located on the 3D plane
3D_point=Inv_Projection.dot(img_point)
#show results
print('3D_pt_method1\n',3D_point)
#output
3D_pt_method1
[[0.01881387]
[0.0259416 ]
[0.04150276]]
By normalizing the point (dividing by the third value) the result is
`X_World=0.45331611680765327 # 45.3 cm from defined world point cm which is correct
Y_world=0.6250572251098481 # 62.5 cm which is also correct
By evaluating the results, it turns out that they are correct.
I now that we can't retrieve the the Z coordinate of the 3D world point since depth information is lost going from 3d to 2d. The following equation also performs the inverse projection of the 2D point onto 3D world and can be found in all literature, and the result is an equation which represents a line on which the 3D_ world point must lie on
I put the equation 3.15 into code, however without setting Z=0, meaning to say with out deleting the third column of the projection matrix like i did in the previous method (Just as it's written) by doing the following the following:
#inverting the rotation matrix
INV_R=np.linalg.inv(R_mtx)
#inverting the camera matrix
INV_k=np.linalg.inv(mtx)
#multiplying the tow matrices
kinv_Rinv=INV_k.dot(INV_R)
#calcuating the 3D_point X which expressed in eq.3.15
3D_point=kinv_Rinv.dot(img_point)+tvecs1
#print the results
print('3D_pt_method2\n',3D_point)
and the result was
3D_pt_method2 #how should one understand these coordinates ?
[[-9.12505825]
[-5.57152147]
[40.12264881]]
My question is, How should i understand or interpret this result? as it doesn't make any sense compared to the previous method where Z=0. the 3D 3x1 resulted vector seems to give an intuition that it's values represents simply the 3D X, Y and Z of the detected image_point. However, this is not true if we compare X and Y with the previous method!!
So what is literally the difference between 3D_pt_method1 and 3D_pt_method2???
I hope i could express my self and really appreciate helping me understand the difference between the two implementations!
Note: the Grid that represents my defined World-plane and can be seen in the below image in which the distance between every two yellow points is 40 cm
Thanks in advance
You miss the key variable "w" in method2.
You can get help from referring to this article: https://blog.csdn.net/zhou4411781/article/details/103876478
This article is written in Chinese, but you can just try to get the point from those formula in that article if you cannot understand Chinese.
Simply speaking:
You said right "I know that we can't retrieve the the Z coordinate of the 3D world point since depth information is lost going from 3d to 2d. "
This also means: If you know the depth (the Z axis value in world coordination), you can get 3d ordinate by 2d ordinate and the depth. As well, if you know the X or Y axis value in world coordination, you can also get the result.
I am trying to find intersection points between 3d object .stl file (that I imported to python using numpy-stl) and 3d plot(that I generated using matplotlib). The 3d object is a cad drawing and 3d plot is a bunch of curves in 3d. I can plot them on the same figure but I have no idea how I can find intersection points between the trajectory and the drawing. My idea was to convert the curve into .stl using save() function from the numpy-stl module after plotting it and show them together on a cad application like freeCAD together and find intersection using the application's functionality. But it does not work as simple because the plots are point based and .stl is triangle based. If anyone has any advice on how to approach this problem, please let me know!!
Here is the code to plot both .stl object and the 3d plot. This is what I have so far.
#allInitialE is 1D list, allX, allY, allZ are all 2D lists
from stl import mesh
from numpy import *
from mpl_toolkits import mplot3d
from matplotlib import pyplot as plt
fig = plt.figure()
ax = plt.axes(projection = '3d')
your_mesh = mesh.Mesh.from_file('fileName.stl')
your_mesh.translate([0,7,0])
ax.add_collection3d(mplot3d.art3d.Poly3DCollection(your_mesh.vectors))
ax.view_init(azim = -90, elev = 0)
maxE = max(allInitialE)
ax.set_xlabel('x axis (m)') # y and z are flipped to make it easier for me to visualize
ax.set_ylabel('z axix (m)')
ax.set_zlabel('y axix (m)')
plt.title('Particle Trajectory')
for k in range(numParticles): #iterate through each of the particles' xyz data
e = allInitialE[k]
if e < maxE/3:
ax.plot3D(allX[k], allZ[k], allY[k], 'g-')
elif e < maxE/2:
ax.plot3D(allX[k], allZ[k], allY[k], 'b-')
else:
ax.plot3D(allX[k], allZ[k], allY[k], 'r-')
plt.show()
1 idea: Is there any way to convert .stl object to a set of plane functions? If so, I could make the plots into lines and find intersection between the plane and the line?
2nd idea: Or, since .stl are vector based, I can use vector calculation? i.e. see if a vector on a curve (line segment) has a common point as a triangle on a .stl object (triangle is defined by three vectors).
Please give me any idea you may have! Thank you so much.
Another way might be to use VTK. You can convert your numpy-stl object (obj) to a vtkPolyData
import vedo
import vtk
import itertools
obj = your_mesh
verts = list(itertools.chain(*(obj.vectors)))
faces = [[i*3, i*3+1, i*3+2] for i in range(len(verts)//3)]
vpoly = vedo.Mesh([verts, faces]).clean().polydata()
Then you could use vtkCutter https://discourse.vtk.org/t/get-intersection-of-polydata-line-and-a-plane/3894/3 or vtkIntersectionPolyDataFilter VTK check polydata point objects for intersection
Concerning your 1st idea, yes, you can convert your STL file into a set of triangles, just check out:
your_mesh.vectors
which is an array of triangle 3D vertices. From those you can construct a plane, and then calculate intersection between segment and plane.
Concerning the 2nd idea, you could do that only if your trajectory crosses exactly to a vertex, otherwise it would not detect the intersection. (Or you would need to give it a margin).
I found a way using pyoctree, which has a function to find intersection between line segments and mesh. Here is the link: https://pypi.org/project/pyoctree/
I was able to use rayIntersection() to do what I wanted to do, really quick. This Intersection between line and triangle in 3D also helped, but the calculation was very slow when it dealt with 60K+ points in a curve.