Table des matières

Projet Vision Active BUT3

Photo du dispositif

Simulation du dispositif

Vue de la caméra en simulation du dispositif

Vue de la caméra en simulation du dispositif avec segmentation laser

Image captée par la caméra réelle avec mire et longue durée d'exposition

Image RECTIFIÉE captée par la caméra réelle avec mire et longue durée d'exposition

Image captée par la caméra réelle avec longue durée d'exposition

Image captée par la caméra réelle avec courte durée d'exposition et laser sur l'objet

lien vers le TP de géométrie pour la vision

https://bvdp.inetdoc.net/wiki/doku.php?id=visionbut3#td_geometrie_pour_la_vision

Lien pour récupérer des séquences d'images à traiter

Stocker et dezipper sur D:\etudiants\ : https://bvdp.inetdoc.net/files/iut/3Dscanner/

chaque séquence a un identifiant unique et restera sur le serveur

dans votre code, utiliser des variables String:

fileLocation="D:\\etudiants\\"
sequence="imgs2024-03-03_18_32_31.576393R"
fileName=fileLocation+sequence+"\\"+"im_00000R.png"

Séquence sans objet sur le plan z=0: https://bvdp.inetdoc.net/files/iut/3Dscanner/imgs2024-03-04_13_39_08.694176R.zip

Code pour récupérer les paramètres de caméra

getCamera.py
import numpy as np
import cv2
from matplotlib import pyplot as plt
import math
#variables à régler pour pointer vers le bon dossier
fileLocation="D:\\etudiants\\"
sequence="imgs2024-03-03_18_32_31.576393R"
fileName=fileLocation+sequence+"\\"+"CalibResult.npz"
#paramètre de la mire
dimSquare=0.012 #dimension des carrés sur la mire en mètres-> les unités de longueur sont donc en mètres
with np.load(fileName) as X:
  mtx, dist, rvecs, tvecs = [X[i] for i in ('mtx','dist','rvecs','tvecs')]
 
#nbimages=len(rvecs)  
#for i in range(nbimages):   #si les différentes images d'étalonnage devaient être traitées
i=0 #pour récupérer les paramètres de l'image dans laquelle la mire est posée sur le plan horizontal
matroti, jacobian=cv2.Rodrigues(rvecs[i]) #Rodrigues permet de calculer la matrice de rotation correspondante    
axis = np.float32([[0,0,0], [3*dimSquare,0,0], [0,3*dimSquare,0], [0,0,3*dimSquare]]).reshape(-1,3)
imgpts, jac = cv2.projectPoints(axis, rvecs[i], tvecs[i], mtx,None) #pour ne pas utiliser les distorsions
 
#matrice de changement de repère contenant les paramètres extrinsèques
cRTw=np.concatenate((matroti,tvecs[i]),axis=1)
cRTw = np.vstack((cRTw,[0,0,0,1]))
print("cRTw: "+str(cRTw))
 
#paramètres intrinsèques de la caméra
alphau=mtx[0][0]
alphav=mtx[1][1]
pu=mtx[0][2]
pv=mtx[1][2]

Calcul de la position du centre optique

La position du centre optique $L$ de la caméra dans le repère de travail est obtenue à partir de la matrice caméra: $\tilde C= \left(\begin{array}{c c } C & \tilde c_4\end{array}\right)$

En observant que le point $L$ n'a pas d'image dans $P^2$ :

$ \left(C
\quad \tilde c_4\right)\ \left(\begin{array}{c c}
L\\1\end{array}\right) = \left(\begin{array}{c c} 0\\ 0\\0 \end{array} \right)\quad \rightarrow\quad L=- C^{-1} \  \tilde
c_4$

Calcul du rayon de projection

L'ensemble des points $M$ de la demi-droite (dans le repère de travail $\omega$) associés à un point $m$ dans le plan image est donné par: $M=L+\lambda\ \overrightarrow{L\  m}$, $\lambda$ étant un paramètre associé à la distance du point 3D au point $L$.

Soit $\tilde \Omega$ le point à l'infini dans la direction de $\overrightarrow{L\ m}$: $\tilde \Omega = \left(\begin{array}{c } \Omega \\0\end{array} \right)$, $m = C.\Omega $ et donc $\Omega = C^{-1} \ m$

On obtient: $M=- C^{-1}\ \tilde c_4 + \lambda\  C^{-1} \  m$ qui donne finalement:$M= C^{-1} \  \left(-\tilde c_4 + \lambda\  m \right)$

En fonction du facteur multiplicatif associé à la représentation homogène de $m$, $\lambda >0$ ou $\lambda <0$.

Projet et rapport à rendre par mail le 16/02/2025

Le projet rendu en .zip ne doit pas contenir les images fournies par l'enseignant mais doit permettre de les utiliser en réglant les variables indiquant leurs emplacements.

PCA pour ajustement d'un plan sur nuage de points 3D

pca.py
#analyse en composantes principales (PCA) pour ajuster un plan sur un nuage de points 3D
#exemple tiré de:
#https://www.bing.com/search?qs=UT&pq=numpy+pca+&sk=CSYN1&sc=6-10&q=numpy+pca+example&cvid=f8480d538ba0461fa6590f521609d926&gs_lcrp=EgRlZGdlKgYIARAAGEAyBggAEEUYOTIGCAEQABhAMgYIAhAAGEAyBggDEAAYQDIGCAQQABhAMgYIBRAAGEDSAQgzMTkxajBqNKgCCLACAQ&FORM=ANAB01&DAF0=1&PC=U531
 
import numpy as np
 
# Sample data: 5 samples with 3 features
data = np.array([[2.5, 2.4, 15],
                 [0.5, 0.7, 0.8],
                 [2.2, 2.9, 1.9],
                 [1.9, 2.2, 1.7],
                 [3.1, 3.0, 2.5]])
 
# Step 1: Standardize the data (mean = 0, variance = 1)
mean = np.mean(data, axis=0)
std_data = data - mean
 
# Step 2: Calculate the covariance matrix
cov_matrix = np.cov(std_data, rowvar=False)
 
# Step 3: Calculate the eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
 
# Step 4: Sort eigenvalues and eigenvectors
sorted_index = np.argsort(eigenvalues)[::-1]
sorted_eigenvalues = eigenvalues[sorted_index]
sorted_eigenvectors = eigenvectors[:, sorted_index]
 
# Step 5: Select the top k eigenvectors (here we choose k=2)
k = 2
eigenvector_subset = sorted_eigenvectors[:, 0:k]
 
# Step 6: Transform the data
pca_data = np.dot(std_data, eigenvector_subset)
 
print("Original Data:\n", data)
print("Mean:\n", mean)
print("Standardized Data:\n", std_data)
print("Covariance Matrix:\n", cov_matrix)
print("Eigenvalues:\n", eigenvalues)
print("Eigenvectors:\n", eigenvectors)
print("Sorted Eigenvalues:\n", sorted_eigenvalues)
print("Sorted Eigenvectors:\n", sorted_eigenvectors)
print("PCA Transformed Data:\n", pca_data)
 
 
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
 
fig = plt.figure()
 
# syntax for 3-D projection
ax = plt.axes(projection ='3d')
 
# defining axes
x = data[:,0]
y = data[:,1]
z = data[:,2]
#https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html
#affichage du nuage de points
ax.scatter(x, y, z,marker=".")
#affichage du centre de gravité du nuage de points
ax.scatter(mean[0], mean[1], mean[2],marker="*")
#affichage du vecteur normal au plan
#echelle=10
#calcul d'une echelle sympa
echelle=np.max(std_data)
 
ax.plot([mean[0],mean[0]+echelle*sorted_eigenvectors[0,2]],
        [mean[1],mean[1]+echelle*sorted_eigenvectors[1,2]],
        [mean[2],mean[2]+echelle*sorted_eigenvectors[2,2]])
#print(sorted_eigenvectors[0,2])
ax.axis('equal')
 
#paramètres du plan:
a=sorted_eigenvectors[0,2]
b=sorted_eigenvectors[1,2]
c=sorted_eigenvectors[2,2]
#le plan passe par mean -> calcul du paramètre d
d=-(a*mean[0]+b*mean[1]+c*mean[2])
 
print("a:"+str(a)+" b:"+str(b)+" c:"+str(c)+" d:"+str(d))     
 
# syntax for plotting
ax.set_title('3d Scatter plot geeks for geeks')
plt.show()

Tracé de polygones

poly.py
import cv2
import numpy as np
 
# Créer une image vide
img = np.zeros((512, 512, 3), np.uint8)
 
# Définir les points du polygone
pts = np.array([[100, 100], [300, 150], [200, 400], [50, 250]], np.int32)
pts = pts.reshape((-1, 1, 2))
 
# Dessiner et remplir le polygone
cv2.fillPoly(img, [pts], (0, 255, 0))
 
# Afficher l'image
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()