Taula de continguts:
Vídeo: Escàner 3D bàsic per a mapatge digital 3D: 5 passos
2024 Autora: John Day | [email protected]. Última modificació: 2024-01-30 08:12
En aquest projecte, descriuré i explicaré els fonaments bàsics de l'escaneig i la reconstrucció en 3D aplicats principalment a l'escaneig d'objectes semiplans petits, i el funcionament dels quals es pot estendre als sistemes d'escaneig i reconstrucció que es poden instal·lar en avions de control remot per obtenir un model 3D. dels llocs on l’avió que els porta instal·lats vola
La idea final és obtenir un escaneig 3D d'algun lloc o zona, ja sigui exterior o interior, per utilitzar-lo com a mapa digital (com a la pel·lícula de Prometeu)
Pas 1:
la idea és instal·lar tot el sistema d’escaneig 3D en un pla controlat a distància, per tal de digitalitzar el mapa virtual de qualsevol àrea sobre la qual vola en 3d, però per a això vam començar des del començament de l’operació de la triangulació làser. d’escaneig o reconstrucció en 3D mitjançant triangulació làser consisteix bàsicament a fer passar un feix làser a través d’un prisma que genera una banda làser per obtenir una franja làser sencera que es projectarà sobre un objecte a escanejar i, una vegada obtinguda aquesta projecció làser a la superfície superficial Des del lloc on s’escaneja, la imatge s’ha de capturar amb algun tipus de càmera i, preferentment, conèixer l’angle que es forma respecte a l’angle de projecció de la banda làser emesa, ja que cadascuna d’aquestes imatges captura les tires làser projectades. A la superfície de l'objecte, es processaran prèviament per extreure les característiques dimensionals de l'objecte a escanejar i simplement escanejar tira per tira per sobre de l'objecte per obtenir el perfil de la seva superfície en aquest segment transversal de l'objecte i posteriorment capturar la franja projectada de la següent secció transversal de l’objecte, per afegir totes les franges projectades juntes Abans de totes les seccions transversals de l’obto obtenim una exploració tridimensional de la seva superfície
Pas 2:
Com que hem identificat el nostre objectiu, el següent pas sabent que per enlairar-se primer s’ha de tenir els peus ferms a terra, de manera que vam començar a terra amb un prototip experimental d’un escàner lineal en 3D, per validar el correcte funcionament del sistema bàsic. Escàner 3D i, com podeu veure a la imatge superior, he utilitzat un PC, OpenCV, Glut d’OpenGL, una càmera web, un làser, un generador de làser (en aquest cas a través d’un mirall rotatori) un sistema de desplaçament lineal electrònic (fet amb un rail i sistema extret d’una antiga impressora) d’una base sobre la qual col·loco els objectes a escanejar, fusta i plastilina i, com podeu veure a la foto, a l’ordinador: he aconseguit generar i mostrar amb Glut d’OpenGL un tres- model dimensional reproduït basat en l'objecte real escanejat (en aquest cas una aranya de joguina)
per tant, és més que evident que el principi de funcionament és funcional i que, amb els seus respectius ajustos i adaptacions a un sistema de vol, podrà escanejar i reproduir un mapa en 3D de la zona on vola.
Però aquest sistema només servirà per obtenir mapes 3D de la superfície externa dels llocs sobre els quals sobrevola ??? …
Pas 3:
cartografiar l'interior de les coves i conductes (igual que a la pel·lícula Prometeus) Aquest sistema d'escaneig 3D també serveix per reconstruir models tridimensionals de l'interior d'objectes grans i buits com coves, edificis, túnels, etc. exactament el mateix que ja s’ha descrit i que consisteix bàsicament en el següent:
- captura la foto de cada projecció de la franja làser a la superfície a escanejar
- filtreu i elimineu el color de la imatge
- binaritzar el color amb un llindar d'imatge dinàmica
- apliqueu un detector de vores per reconèixer el perfil capturat de cada secció transversal de projecció làser
- i mitjançant la segmentació, seleccioneu la vora adequada per a la representació en 3D d'aquesta secció transversal de l'objecte que voleu escanejar i reconstruir al mapa 3D virtual
- llavors aquests passos es repeteixen simplement per a cada fotografia feta d'una manera secundària de les ratlles làser projectades contínuament per cada sub-secció en la sub-secció.
capa per capa de la representació de les seccions transversals s’afegeixen successivament fins a obtenir un núvol de punts format per moltes representacions de seccions transversals de l’objecte a cartografiar
Pas 4:
Després passo els programes per al processament d’imatges de les projeccions de les tires làser superficials. i de la reconstrucció virtual 3D d'aquestes representacions transversals sussives en el model de mapa tridimensional elaborat:
processament d'imatge:
n
#include #include "cv.h" #include "highgui.h" #include // # include #include #include #include
char f = 0; char name = {"0.jpg"}; int n = 0, s, x, y; CvScalar sp; FITXA * NuPu;
void Writepoints () {char bufferx [33], buffery [33]; itoa (x, bufferx, 10); itoa (y, buffery, 10); fprintf (NuPu, bufferx); fprintf (NuPu, "\ t"); fprintf (NuPu, memòria intermèdia); fprintf (NuPu, "\ n"); }
void noteblockInit () {NuPu = fopen ("NuPu.txt", "w"); fseek (NuPu, 0, 0); fprintf (NuPu, "NP:"); fprintf (NuPu, "\ n"); }
int main () {char argstr [128]; noteblockInit (); cout << "Teklea! …:" f; nom [0] = f; cout <
IplImage * img0 = cvLoadImage ("00.jpg", 0); if (f == '0') {for (y = 1; yheight-2; y ++) {for (x = 1; xwidth-2; x ++) {sp = cvGet2D (img0, y, x); if (sp.val [0]> 50) {Writepoints (); n ++;}}}} else {for (y = 1; yheight-2; y ++) {for (x = 1; xwidth-2; x ++) { sp = cvGet2D (img1, y, x); if (sp.val [0]> 50) {Writepoints (); n ++;}}}} buff buff [33]; itoa (n, buffer, 10); fprintf (NuPu, "Fin:"); fprintf (NuPu, memòria intermèdia); fprintf (NuPu, "\ n"); fclose (NuPu);
cvWaitKey (0); //_execlp("calc.exe "," calc.exe ", argstr, NULL); cvDestroyAllWindows (); cvReleaseImage (& image); cvReleaseImage (& img); cvReleaseImage (& img0); cvReleaseImage (& img1); cvReleaseImage (& img2); retorn 0; }
Reconstrucció 3D:
#include ////////////////// #ifdef _APPLE_ #include #else #include #include #endif #include #include #include #include #include #include
#define violeta glColor3f (1, 0, 1) #define azul glColor3f (0, 0, 1) #define turkeza glColor3f (0, 1, 1) #define verde glColor3f (0, 1, 0) #define amarillo glColor3f (1, 1, 0) #define naranja glColor3f (1,.3, 0) #define rojo glColor3f (1, 0, 0) using namespace std; int s, Boton = 1, Pulbut = 1; float mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5,0; const int Avance = 1; línia de corda, Aux; char Caracter = 'H'; FITXA * NuPu; int NP, h, w; float G = 0, n = 0, cx [5000], cy [5000], x, y, ax, ay, az; int font = (int) GLUT_BITMAP_8_BY_13; etiqueta de caràcters estàtics [100]; buff buffer [3]; GLfloat anguloCuboX = 0,0f; GLfloat anguloCuboY = 0,0f; GLfloat anguloEsfera = 0,0f; GLint ancho = 500; GLint alt=500; int hazPerspectiva = 0; void reshape (int width, int height) {glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (hazPerspectiva) gluPerspective (23.0f, (GLfloat) width / (GLfloat) height, 1.0f, 20.0f); else glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); ancho = ample; alt=alçada; } void Kolorear (int K) {flotador Hip; x = (cx [s] -320) / 480; y = (cy [s] -240) / 640; Hip = sqrt (pow (x, 2) + pow (y, 2)); if ((Hip> = 0) && (Hip =.07) && (Hip =.14) && (Hip =.21) && (Hip =.28) && (Hip =.35) && (Hip =.42) && (Hip <=. 49)) {violeta;}} void drawNuPu (void) {glColor3f (1, 1, 1); glBegin (GL_LINES); glVertex3f (.2, 0, 0); glVertex3f (-. 2, 0, 0); glVertex3f (0,.2, 0); glVertex3f (0, -.2, 0); glEnd (); vermell; glBegin (GL_POINTS); for (n = 0; n <10; n ++) {for (s = 0; s void setOrthographicProjection () {glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); gluOrtho2D (0, w, 0, h); glScalef (1, -1, 1); glTranslatef (0, -h, 0); glMatrixMode (GL_MODELVIEW);} void renderBitmapString (float x, float y, void * font, char * string) {char * c; glRasterPos2f (x, y); for (c = string; * c! = '\ 0'; c ++) {glutBitmapCharacter (font, * c);}} void display () {// mx = 468; itoa (mx, buffer, 10); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glLoadIdentity (); glColor3f (1.0, 1.0, 1.0); glRasterPos2f (-1,.9); // glutBitmapString (GLUT_BITMAP_TIMES;; s <3; s ++) {glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, buffer [s]);} glTranslatef (mty, -mtx, mtz); glRotatef (mx, 1.0f, 0.0f, 0.0f); glRotatef (my, 0.0f, 1.0f, 0.0f); drawNuPu (); /*glColor3f(1.0, 1.0, 1.0); glRasterPos2f (.5,.5); // glutBitmapString (GLUT_BITMAP_TIMES_ROMAN_24, "Hello Text"); glutBitmapCharacter (GLUT_B_MAP); * / / * glColor3f (1. 0f, 1.0f, 1.0f); setOrthographicProjection (); glPushMatrix (); glLoadIdentity (); renderBitmapString (30, 15, font (void *), "Tutorial GLUT ---_ ------ _ @ 3D Tech"); * / glFlush (); glutSwapBuffers (); anguloCuboX + = 0,1f; anguloCuboY + = 0,1f; anguloEsfera + = 0.2f; } void init () {glClearColor (0, 0, 0, 0); glEnable (GL_DEPTH_TEST); ancho = 500; alt=500; } void leer () {ifstream myfile ("A: / Respaldo sept 2016 / D / Respaldos / Respaldo compu CICATA abril 2015 / usb1 / rekostruccion 3D en Especialidad CICATA / Software / Reconstruccion 3D / R3d_0 / bin / Debug / NuPu.txt"); if (myfile.is_open ()) {s = 0; while (getline (myfile, line)) {if ((line [0]! = 'N') && (line [0]! = 'F')) {Aux = line; línia [0] = 48; línia [1] = 48; línia [2] = 48; línia [3] = 48; cy [s] = atoi (line.c_str ()); Aux [4] = 48; Aux [5] = 48; Aux [6] = 48; // Aux [7] = 48; cx [s] = atoi (Aux.c_str ()); s ++; }} myfile.close (); } else cout <1780) NP = 1700; cout <void idle () {display (); } void keyboard (tecla de caràcter sense signar, int x, int y) {commutador (tecla) {cas 'p': cas 'P': hazPerspectiva = 1; remodelar (ancho, alto); trencar; cas 'o': cas 'O': hazPerspectiva = 0; remodelar (ancho, alto); trencar; cas 27: // escape escape (0); trencar; }} void raton (botó int, estat int, int x, int y) {/ * GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 * / Boton = botó; Pulbut = estat; // mx = y; display (); } void ratmov (int x, int y) {if ((Boton == 0) & (Pulbut == 0)) {mx = y; el meu = x; } if ((Boton == 2) & (Pulbut == 0)) {mtx = (y / 200) -1; mty = (x / 200) -1; } if ((Boton == 1) & (Pulbut == 0)) {mtz = - (y / 40) -5; } display (); } int main (int argc, char ** argv) {/ * glutAddMenuEntry () glutAddSubMenu () glutAttachMenu () glutCreateMenu () glutSetMenu () glutStrokeCharacter () glutStrokeLength () * / / * glReadPixels () llegir un bloc de píxels () frame buffer glGetPixelMapfv () retorna el mapa de píxels especificat glGetPixelMapuiv () retorna el mapa de píxels especificat glGetPointerv () Retorna l'adreça del punter especificat. * / Init (); leer (); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (ancho, alto); glutCreateWindow ("Cubo 1"); init (); glutDisplayFunc (pantalla); glutReshapeFunc (remodelació); glutIdleFunc (inactiu); glutMouseFunc (raton); glutMotionFunc (ratmov); glutKeyboardFunc (teclat); glutMainLoop (); retorn 0; }
Pas 5:
de moment he de parar! … però al capítol següent us prometo que ho implementaré al meu raspberry pi 3 o al meu jetson nanoboard, ja muntat en algun avió controlat a distància, o en algun robot aranya per escanejar l'interior de les coves
Recomanat:
Consells de mapatge: 3 passos
Consells de mapatge: sigui quina sigui la vostra activitat, ja sigui caminant, caminant, amb bicicleta o fins i tot conduint, podeu enregistrar les rutes que feu. A continuació, podeu compartir aquestes rutes amb amics i familiars. A més, podeu utilitzar la ruta enregistrada per afegir ubicacions a qualsevol foto que pugueu fer
El mapificador - Sistema de mapatge + notificació: 9 passos
The Mappifier - Mapping + System Notification: La conducció nocturna és molt divertida. Però sovint resulta ser un malson, en forma d’animals que creuen la carretera (sobretot aquells gats i gossos de carrer que esperen que conduïu a prop d’ells perquè puguin creuar-se !!). Així que vaig pensar en fer-ho tan
Llum de pista Raspberry PI d’alerta primerenca mitjançant dades de mapatge de vol: 14 passos (amb imatges)
Llum de pista Raspberry PI d’alerta primerenca amb dades de mapatge de vol: aquesta llum va sorgir de diversos motius pel fet que sempre m’interessen els avions que volen a sobre i, durant l’estiu, els caps de setmana sovint n’hi ha uns de força emocionants. Encara que sols escoltar-los mentre van passant
Escàner CT i escàner 3D amb Arduino: 12 passos (amb imatges)
Escàner CT i 3D amb Arduino: la tomografia computada (TC) o la tomografia axial computaritzada (TAC) s’associa amb més freqüència a la imatge del cos perquè permet als clínics veure l’estructura anatòmica del pacient sense haver de fer cap cirurgia. Imatge dins de l'home b
Com fer un mapatge de projecció amb el límit Pi: 9 passos (amb imatges)
Com fer un mapatge de projecció amb el Pi Cap: ens hem inspirat en els vostres projectes i hem creat un tutorial de mapatge de projecció amb Pi Cap. Si voleu que el vostre projecte funcioni sense fils mitjançant WiFi, aquest és el vostre tutorial. Vam utilitzar MadMapper com a programari de mapatge de projecció