Calculating error between two STL files in python - python

In Python, I'm trying to calculate error (similarity) between two different objects, scanned and saved as STL files. Since the objects having different amount of points and triangles, my approach creates an error. How can I calculate error between these objects?
The code:
import open3d as o3d
import numpy as np
import matplotlib.cm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Load the two STL files into open3d PointCloud objects
mesh1 = o3d.io.read_triangle_mesh("Mesh1.stl")
mesh2 = o3d.io.read_triangle_mesh("Mesh2.stl")
# Perform ICP to align the two meshes
reg_p2p = o3d.pipelines.registration.registration_icp(
source=mesh2,
target=mesh1,
max_correspondence_distance=0.1,
nn_method=o3d.pipelines.registration.TransformationEstimationPointToPoint()
)
mesh2_aligned = mesh2.transform(reg_p2p.transformation)
# Calculate the difference between the vertices of the two meshes
difference = mesh1.vertices - mesh2_aligned.vertices
# Use a colormap to assign a color to each vertex based on the deviation
colors = matplotlib.cm.jet(np.abs(difference) / np.abs(difference).max())
# Plot the two meshes as 3D surfaces
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(mesh1.vertices[:, 0], mesh1.vertices[:, 1], mesh1.vertices[:, 2], color=colors)
ax.plot_surface(mesh2_aligned.vertices[:, 0], mesh2_aligned.vertices[:, 1], mesh2_aligned.vertices[:, 2], color=colors)
# Show the plot
plt.show()
This code creates this error, due to the shape and size differences:
TypeError Traceback (most recent call last)
Cell In [72], line 12
9 mesh2 = o3d.io.read_triangle_mesh("Mesh2.stl")
11 # Perform ICP to align the two meshes
...
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]]), estimation_method: open3d.cpu.pybind.pipelines.registration.TransformationEstimation = TransformationEstimationPointToPoint without scaling., criteria: open3d.cpu.pybind.pipelines.registration.ICPConvergenceCriteria = ICPConvergenceCriteria class with relative_fitness=1.000000e-06, relative_rmse=1.000000e-06, and max_iteration=30) -> open3d.cpu.pybind.pipelines.registration.RegistrationResult
Invoked with: kwargs: source=TriangleMesh with 884924 points and 295032 triangles., target=TriangleMesh with 471383 points and 522678 triangles., max_correspondence_distance=0.1, nn_method=TransformationEstimationPointToPoint without scaling.
Thanks.

Related

String format for plotting labels, but the entire string is given for legend entry

I have an array of integers that serve as identification for various dots on a graph.
k = [42., 64., 73., 31., 31., 31., 31., 2., 5., 16.]
plt.plot(x, y, 'o', label='name{}'.format(k))
plt.legend()
When I make the plot, the entire array of numbers is shown in the legend for each entry. What I need is each k-value labeled with its own x-y pair, as in (x[0], y[0]) and label(k[0]). How can I make the script stop showing the whole array for each label?
Is something like usable? I made some random x and y values and merged the data into Pandas DataFrame.
#!/usr/bin/env ipython
# ---------------------
import numpy as np
import matplotlib.pylab as plt
import pandas as pd
k = [42., 64., 73., 31., 31., 31., 31., 2., 5., 16.]
x = np.random.random((np.size(k)));
y = np.random.random((np.size(k)));
# ----------------------------------------------
# let us have data collected to some object, that we can easily manipulate (e.g. Pandas DataFrame, dictionary...):
data = {'x':x,'y':y,'k':[int(vv) for vv in k]};
df = pd.DataFrame.from_dict(data);df = df.set_index('k')
# ----------------------------------------------
for indval in set(df.index):
plt.plot(df.loc[indval].x, df.loc[indval].y, 'o', label=indval,ms = 10)
plt.legend()
plt.show()

Plot getting bolder after each iteration

So, I am generating plots on the same figure over a given iteration. As I have multiple plots there, I want them to start faded and as the iteration goes further, they get bolder and bolder. It is important to have plots with the same color.
A made up code in case you have any want to try yourself:
from scipy.stats import norm
import matplotlib.pyplot as plt
import numpy as np
i = np.array([1,1.2,1.4,1.6,1.8,2.0,3.0,4.0,5.0,6.0,7.0])
x = np.arange(-10, 10, .1)
for i in range(0,len(i)):
rv1 = norm(loc = 0., scale = 1.0*i)
plt.plot(x,rv1.pdf(x), color ='b')
plt.show()
I want my plot to resemble something like this:
You can do that using the alpha argument to plot, e.g.:
from scipy.stats import norm
import matplotlib.pyplot as plt
import numpy as np
idx = np.array([1,1.2,1.4,1.6,1.8,2.0,3.0,4.0,5.0,6.0,7.0])
xxx = np.arange(-10, 10, .1)
for i in range(0,len(idx)):
rv1 = norm(loc = 0., scale = 1.0*i)
plt.plot(xxx,rv1.pdf(xxx), color ='b', alpha=i / len(idx))
plt.show()
Note that I renamed some variables.
You can use a variable line width and the transparency parameter, alpha as following. Start with some initial values and then increase the line thickness by 20% (for example) and decrease the alpha by 10%
P.S: I read the comment of IOBE and added it to my for loop for readers. Don't call the iterator variable and the array by the same name i. I have now used ii in the for loop
wid = 0.8
alpha=0.9
for ii in range(0,len(i)):
rv1 = norm(loc = 0., scale = 1.0*ii)
plt.plot(x,rv1.pdf(x), color ='b', lw=wid, alpha=alpha)
wid *= 1.2
alpha *= 0.9

Extracting Data From Matplotlib Figure

I have a simple figure which I have used matplotlib.plot function in order to plot it.
For example:
Is there a way to extract the data points and paste it (like in matlab) to excel sheet which I didn't know about?
I want to assume that many figures were created randomly and I didn't know which data/figure I needed until I see the results.
To extract the data-points, you can assign a variable to your plot:
graph = plt.plot(your_data)
data_points = graph[0].get_data()
Example that extracts the data-points of a line plot and saves them to a csv file:
In[1]: import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-1, 1, 5)
y = 2*x + 1
xy = plt.plot(x, y)
data = xy[0].get_data()
print(data)
plt.show()
with open('data.csv', 'w') as myfile:
writer = csv.writer(myfile)
writer.writerow(['x', 'y'])
for i in range(len(data[0])):
writer.writerow([data[0][i], data[1][i]])
Out[1]: (array([-1. , -0.5, 0. , 0.5, 1. ]), array([-1., 0., 1., 2., 3.]))

Matplotlib: Plot movements in 3D

I have a solver that solves a system of equations in 3 variables. Each iteration, it has a new guess on all three variables. The guesses over iterations look like this:
array([[ 0.86063431, 0.07119279, 1.70377142],
[ 0.86391084, 0.07014899, 1.72184785],
[ 0.86332177, 0.069444 , 1.71182579],
[ 0.86192988, 0.06913941, 1.69818289],
[ 0.86166436, 0.06916367, 1.69527615]])
(Here for 5 iterations). I would like to plot these using matplotlib. I was thinking about having a dot for each of these coordinates, and have a line connecting them to show the order of coordinates.
Is this a good way of visualizing this? How would I do that using matplotlib?
You can plot this as a 3D trajectory with matplotlib:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
points = np.array([[ 0.86063431, 0.07119279, 1.70377142],
[ 0.86391084, 0.07014899, 1.72184785],
[ 0.86332177, 0.069444 , 1.71182579],
[ 0.86192988, 0.06913941, 1.69818289],
[ 0.86166436, 0.06916367, 1.69527615]]).T
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.plot(points[0], points[1], points[2], marker = 'x')
ax.scatter(*points.T[0], color = 'red')
plt.show()

IndexError: too many indices for array Numpy Plotting CCDF with CSV

I am trying to plot a CCDF using numpy and input is csv with #keywords as col[0] and frequency as col[1].
Input
#Car,45
#photo,4
#movie,6
#life,1
Input has more than 10K rows and two column out of which col[0] is not used at all and only the frequency from col[1] is used to plot the CCDF. The data has no empty rows in-between nor eof has any blank row.
Code:
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from pylab import*
import math
from matplotlib.ticker import LogLocator
data = np.genfromtxt('input.csv', delimiter=",")
d0=data[:,1]
X0 = np.sort(d0)
cdf0 = np.arange(len(X0))/float(len(X0))
#cumulative = np.cumsum(data)
ccdf0 = 1 - cdf0
plt.plot(X0,ccdf0, color='b', marker='.', label='Frequency')
plt.legend(loc='upper right')
plt.xlabel('Freq (x)')
plt.ylabel('ccdf(x)')
plt.gca().set_xscale("log")
#plt.gca().set_yscale("log")
plt.show()
Error
Traceback (most recent call last):
File "00_plot_ccdf.py", line 17, in <module>
d0=data[:,1]
IndexError: too many indices for array
Thanks in Advance
genfromtxt by default treats lines starting with # as comments, so actually your data is empty:
In [1]: genfromtxt('test.csv', delimiter=',')
/usr/lib/python3/dist-packages/numpy/lib/npyio.py:1385: UserWarning: genfromtxt: Empty input file: "test.csv"
warnings.warn('genfromtxt: Empty input file: "%s"' % fname)
Out[1]: array([], dtype=float64)
data is a 1-dimensional empty array and so [:,1] is too many indices.
To disable this pass comments=None to genfromtxt:
In [20]: genfromtxt('test.csv', delimiter=',', comments=None)
Out[20]:
array([[ nan, 45.],
[ nan, 4.],
[ nan, 6.],
[ nan, 1.]])
Since you need only the 2. column, you can also limit the results to that directly:
In [21]: genfromtxt('test.csv', delimiter=',', comments=None, usecols=(1,))
Out[21]: array([ 45., 4., 6., 1.])

Categories

Resources