Sommario:

Scanner 3D di base per la mappatura 3D digitale: 5 passaggi
Scanner 3D di base per la mappatura 3D digitale: 5 passaggi

Video: Scanner 3D di base per la mappatura 3D digitale: 5 passaggi

Video: Scanner 3D di base per la mappatura 3D digitale: 5 passaggi
Video: Prima volta che provo uno scanner, il Creality CR 3D Scanner 2024, Dicembre
Anonim
Scanner 3D di base per la mappatura 3D digitale
Scanner 3D di base per la mappatura 3D digitale

In questo progetto descriverò e spiegherò i fondamenti di base della scansione e ricostruzione 3D applicata principalmente alla scansione di piccoli oggetti semipiani e il cui funzionamento può essere esteso ai sistemi di scansione e ricostruzione che possono essere installati su velivoli telecomandati per ottenere un modello 3D. dei luoghi dove l'aereo che li porta installato vola

L'idea finale è quella di ottenere una scansione 3D di un luogo o di un'area, sia esterna che interna, per utilizzarla come mappa digitale (come nel film di Prometeus)

Passo 1:

Immagine
Immagine

l'idea è quella di installare l'intero sistema di scansione 3d su un aereo telecomandato, in modo da digitalizzare la mappa virtuale di qualsiasi area su cui si sorvola in 3d, ma per questo siamo partiti dall'inizio dell'operazione di triangolazione laser il metodo della scansione o ricostruzione 3d mediante triangolazione laser consiste essenzialmente nel far passare un raggio laser attraverso un prisma che genera una striscia laser per ottenere un'intera striscia laser che verrà proiettata su un oggetto da scansionare, e una volta ottenuta tale proiezione laser sul superficie superficie Dal luogo da scansionare, l'immagine deve essere catturata con qualche tipo di macchina fotografica e preferibilmente conoscendo l'angolo che si forma rispetto all'angolo di proiezione della striscia laser emessa, poiché ciascuna di queste immagini cattura le strisce laser proiettate. Sulla superficie dell'oggetto, verranno pretrattati per estrarre le caratteristiche dimensionali dell'oggetto da scansionare, e semplicemente scansionare striscia per striscia sopra l'oggetto per ottenere il profilo della sua superficie in quel segmento trasversale dell'oggetto, e successivamente catturare la striscia proiettata della successiva sezione trasversale dell'oggetto, per sommare tutte le strisce proiettate insieme Prima di tutte le sezioni trasversali dell'obto si ottiene una scansione tridimensionale della sua superficie

Passo 2:

Immagine
Immagine

Dato che abbiamo individuato il nostro obiettivo, il passo successivo sapendo che per decollare bisogna prima avere i piedi ben saldi a terra, quindi siamo partiti a terra con un prototipo sperimentale di scanner 3d lineare, per validare il corretto funzionamento della base Scanner 3d e come potete vedere nell'immagine sopra, ho utilizzato un PC, OpenCV, Glut di OpenGL, una webcam, un laser, generatore di laser farm (in questo caso tramite uno specchio rotativo) un sistema elettronico di spostamento lineare (realizzato con un binario e sistema estratto da una vecchia stampante) da una base su cui poggio gli oggetti da scansionare, legno e plastilina e come potete vedere nella foto, sul computer: sono riuscito a generare e visualizzare con Glut da OpenGL un tre- modello dimensionale riprodotto sulla base dell'oggetto reale scansionato (in questo caso un ragno giocattolo)

quindi è più che evidente che il principio di funzionamento è funzionale, e che con le relative regolazioni e adattamenti ad un sistema di volo sarà in grado di scansionare e riprodurre una mappa 3d dell'area in cui vola.

Ma questo sistema servirà solo per ottenere mappe 3D della superficie esterna dei luoghi su cui sorvola???…

Passaggio 3:

Immagine
Immagine

mappatura dell'interno delle grotte e dei condotti (proprio come nel film Prometeus) Questo sistema di scansione 3D serve anche a ricostruire modelli tridimensionali dell'interno di oggetti grandi e cavi come grotte, edifici, gallerie, ecc. Il suo principio di funzionamento è esattamente uguale a quanto già descritto e che sostanzialmente consiste in quanto segue:

  1. cattura la foto di ogni proiezione della striscia laser sulla superficie da scansionare
  2. filtra e rimuovi il colore dall'immagine
  3. binarizzare il colore con una soglia dell'immagine dinamica
  4. applicare un rilevatore di bordi per riconoscere il profilo catturato di ciascuna sezione trasversale di proiezione laser
  5. e utilizzando la segmentazione selezionare il bordo appropriato per la rappresentazione 3d di quella sezione trasversale dell'oggetto da scansionare e ricostruire sulla mappa 3D virtuale
  6. quindi questi passaggi vengono semplicemente ripetuti per ogni foto scattata in modo subordinato alle strisce laser proiettate in modo continuo da ciascuna sottosezione in sottosezione.
  7. strato per strato della rappresentazione delle sezioni trasversali vengono aggiunti successivamente fino ad ottenere una nuvola di punti formata da tante rappresentazioni delle sezioni trasversali dell'oggetto da mappare

Passaggio 4:

Immagine
Immagine

Poi passo ai programmi per l'elaborazione delle immagini delle proiezioni delle strisce laser superficiali. e della ricostruzione virtuale 3d di queste rappresentazioni sussive trasversali nel modello cartografico tridimensionale elaborato:

elaborazione delle immagini:

n

#include #include "cv.h" #include "highgui.h" #include //#include #include #include #include

carattere f=0; nome carattere={"0.jpg"}; int n=0, s, x, y; CvScalar sp; FILE *NuPu;

void Writepoints() { char bufferx[33], buffery[33]; itoa (x, bufferx, 10); itoa (y, buffer, 10); fprintf(NuPu, bufferx); fprintf(NuPu, "\t"); fprintf(NuPu, buffer); 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; nome[0]=f; cout<

IplImage* img0=cvLoadImage("00.jpg", 0); if(f=='0') { for(y=1;yaltezza-2;y++) { for(x=1;xlarghezza-2;x++) { sp=cvGet2D(img0, y, x); if(sp.val[0]>50){Writepoints();n++;} } } } else { for(y=1;yaltezza-2;y++) { for(x=1;xlarghezza-2;x++) { sp=cvGet2D(img1, y, x); if(sp.val[0]>50){Writepoints();n++;} } } } char buffer[33]; itoa (n, tampone, 10); fprintf(NuPu, "Fina:"); fprintf(NuPu, buffer); 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); restituisce 0; }

Ricostruzione 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, mio=0, mtx=0, mty=0, mtz=-5.0; const int Avance=1; linea di stringa, Aux; carattere Carattere='H'; FILE *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; etichetta carattere statico[100]; buffer di caratteri[3]; GLfloat anguloCuboX = 0.0f; GLfloat anguloCuboY = 0.0f; GLfloat anguloEsfera = 0.0f; GLint ancora=500; GLint alto=500; int hazPerspectiva = 0; void reshape(int larghezza, int altezza) { glViewport(0, 0, larghezza, altezza); 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 = larghezza; alto = altezza; } void Kolorear(int K) { float Hip; x=(cx[s]-320)/480; y=(cy[s]-240)/640; Anca=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); gEnd(); rosso; 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_ROMAN_24, "Hello Text");;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_BITMAP_TIMES_ROMAN_24, '7');*/ /*glColor3f(1. 0f, 1.0f, 1.0f); setOrthographicProjection(); glPushMatrix(); glLoadIdentity(); renderBitmapString(30, 15, (void *)font, "Esercitazione 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); ancora = 500; contralto = 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 (miofile.is_open()) { s=0; while(getline(myfile, line)) { if((line[0]!='N')&&(line[0]!='F')) { Aux=line; riga[0]=48; riga[1]=48; riga[2]=48; riga[3]=48; cy[s]=atoi(line.c_str()); Ausiliario[4]=48; Ausiliario[5]=48; Ausiliario[6]=48; //Aux[7]=48; cx[s]=atoi(Aux.c_str()); s++; } } miofile.close(); } else cout <1780)NP=1700; cout< void inattivo() { display(); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'p': case 'P': hazPerspectiva=1; rimodellare(ancho, alto); rottura; case 'o': case 'O': hazPerspectiva=0; rimodellare(ancho, alto); rottura; case 27: // escape exit(0); rottura; } } void raton(int button, int state, int x, int y) { /* GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 */ Boton=button; Pulbut=stato; //mx=y; Schermo(); } void ratmov(int x, int y) { if((Boton==0)&(Pulbut==0)) { mx=y; mio=x; } if((Boton==2)&(Pulbut==0)) { mtx=(y/200)-1; mty=(x/200)-1; } if((Boton==1)&(Pulbut==0)) { mtz=-(y/40)-5; } Schermo(); } int main(int argc, char **argv) { /*glutAddMenuEntry() glutAddSubMenu() glutAttachMenu() glutCreateMenu() glutSetMenu() glutStrokeCharacter() glutStrokeLength()*/ /*glReadPixels() legge un blocco di pixel dal frame buffer glGetPixelMapfv() restituisce la mappa di pixel specificata glGetPixelMapuiv() restituisce la mappa di pixel specificata glGetPointerv() Restituisce l'indirizzo del puntatore specificato.*/ Init(); leer(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(ancho, alto); glutCreateWindow("Cubo 1"); dentro(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutIdleFunc(idle); glutMouseFunc(raton); glutMotionFunc(ratmov); glutKeyboardFunc(tastiera); glutMainLoop(); restituisce 0; }

Passaggio 5:

Immagine
Immagine

per il momento mi devo fermare! …ma nel prossimo capitolo vi prometto che lo realizzerò sul mio raspberry pi 3 o sulla mia nanoboard jetson, già montata su qualche aereo telecomandato, o su qualche robot ragno per scansionare l'interno delle caverne

Consigliato: