Inhoudsopgave:

Basis 3D-scanner voor digitale 3D-toewijzing: 5 stappen
Basis 3D-scanner voor digitale 3D-toewijzing: 5 stappen

Video: Basis 3D-scanner voor digitale 3D-toewijzing: 5 stappen

Video: Basis 3D-scanner voor digitale 3D-toewijzing: 5 stappen
Video: 3. Scannen - Excent FlitZ Prothese 2024, September
Anonim
Basis 3D-scanner voor digitale 3D-mapping
Basis 3D-scanner voor digitale 3D-mapping

In dit project zal ik de basisprincipes van 3D-scannen en reconstructie beschrijven en uitleggen die voornamelijk worden toegepast op het scannen van kleine semi-vlakke objecten, en waarvan de werking kan worden uitgebreid tot scan- en reconstructiesystemen die kunnen worden geïnstalleerd op op afstand bestuurbare vliegtuigen om een 3D-model. van de plaatsen waar het vliegtuig dat ze brengt, vliegt

Het uiteindelijke idee is om een 3D-scan te maken van een plaats of gebied, zowel de buitenkant als de binnenkant, om deze te gebruiken als een digitale kaart (zoals in de film van Prometeus)

Stap 1:

Afbeelding
Afbeelding

het idee is om het volledige 3D-scansysteem op een op afstand bestuurbaar vliegtuig te installeren om de virtuele kaart van elk gebied waarover het in 3D vliegt te digitaliseren, maar hiervoor zijn we begonnen vanaf het begin van de werking van de lasertriangulatiede methode van scannen of 3D-reconstructie door lasertriangulatie bestaat in feite uit het passeren van een laserstraal door een prisma dat een laserstreep genereert om een volledige laserstreep te verkrijgen die op een te scannen object wordt geprojecteerd, en zodra deze laserprojectie is verkregen op de oppervlakte oppervlak Van de plaats die moet worden gescand, moet het beeld worden vastgelegd met een soort camera en bij voorkeur de hoek kennen die wordt gevormd met betrekking tot de projectiehoek van de uitgezonden laserstreep, aangezien elk van deze beelden de geprojecteerde laserstroken vastlegt. Op het oppervlak van het object worden ze voorbewerkt om de dimensionale kenmerken van het te scannen object te extraheren en eenvoudig strook voor strook boven het object te scannen om het profiel van het oppervlak in dat transversale segment van het object te verkrijgen, en vervolgens vast te leggen de geprojecteerde strook van de volgende dwarsdoorsnede van het object, om alle geprojecteerde strepen bij elkaar op te tellen Vóór alle dwarsdoorsneden van de obto verkrijgen we een driedimensionale scan van het oppervlak

Stap 2:

Afbeelding
Afbeelding

Omdat we ons doel hebben geïdentificeerd, is de volgende stap, wetende dat om op te stijgen, je eerst stevig op de grond moet staan, dus zijn we op de grond begonnen met een experimenteel prototype van een lineaire 3D-scanner, om de juiste werking van de basis te valideren 3D-scanner en zoals je kunt zien in de afbeelding hierboven, gebruikte ik een pc, OpenCV, Glut of OpenGL, een webcam, een laser, een laserfarmgenerator (in dit geval door een roterende spiegel) een elektronisch lineair verplaatsingssysteem (gemaakt met een rail en systeem geëxtraheerd uit een oude printer) van een basis waarop ik de te scannen objecten, hout en plasticine plaats en zoals je op de foto kunt zien, op de computer: ik slaagde erin om met Glut van OpenGL een drie- dimensionaal model gereproduceerd op basis van het gescande echte object (in dit geval een speelgoedspin)

het is dus meer dan duidelijk dat het werkingsprincipe functioneel is en dat het met zijn respectievelijke aanpassingen en aanpassingen aan een vliegend systeem in staat zal zijn om een 3D-kaart te scannen en te reproduceren van het gebied waarin het vliegt.

Maar dit systeem zal alleen dienen om 3D-kaarten te verkrijgen van het buitenoppervlak van de plaatsen waar het overheen vliegt???…

Stap 3:

Afbeelding
Afbeelding

het in kaart brengen van het interieur van de grotten en kanalen (net als in de Prometeus-film) Dit 3D-scansysteem dient ook om driedimensionale modellen te reconstrueren van het interieur van grote en holle objecten zoals grotten, gebouwen, tunnels, enz. Het werkingsprincipe is precies hetzelfde als al beschreven en die in wezen uit het volgende bestaat:

  1. maak de foto van elke projectie van de laserstreep op het te scannen oppervlak
  2. filter en verwijder kleur uit afbeelding
  3. binariseer de kleur met een dynamische beelddrempel
  4. pas een randdetector toe om het vastgelegde profiel van elke laserprojectiedwarsdoorsnede te herkennen
  5. en selecteer met behulp van segmentatie de juiste rand voor de 3D-weergave van die dwarsdoorsnede van het object dat moet worden gescand en gereconstrueerd op de virtuele 3D-kaart
  6. vervolgens worden deze stappen eenvoudig herhaald voor elke foto die is genomen op een submanier van de laserstrepen die continu worden geprojecteerd door elke subsectie in subsectie.
  7. laag voor laag van de weergave van de doorsneden worden achtereenvolgens toegevoegd totdat een puntenwolk wordt verkregen die wordt gevormd door vele weergaven van doorsneden van het in kaart te brengen object

Stap 4:

Afbeelding
Afbeelding

Daarna slaag ik voor de programma's voor beeldverwerking van de projecties van de oppervlakkige laserstrips. en van de virtuele 3D-reconstructie van deze sussieve transversale representaties in het uitgewerkte driedimensionale kaartmodel:

afbeelding verwerken:

N

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

char f=0; char naam={"0.jpg"}; int n=0, s, x, y; CvScalar sp; BESTAND *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]; notitieblokInit(); cout<<"Teklea!…:"f; naam[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++;} } } } char buffer[33]; itoa (n, buffer, 10); fprintf(NuPu, "Fin:"); fprintf(NuPu, buffer); fprintf(NuPu, "\n"); fclose (NuPu);

cvWachtKey(0); //_execlp("calc.exe", "calc.exe", argstr, NULL); cvDestroyAllWindows(); cvReleaseImage(&afbeelding); cvReleaseImage(&img); cvReleaseImage(&img0); cvReleaseImage(&img1); cvReleaseImage(&img2); retourneer 0; }

3D-reconstructie:

#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) met namespace std; int s, Boton=1, Pulbut=1; float mx=0, my=0, mtx=0, mty=0, mtz=-5,0; const int Avance=1; tekenreeks, Aux; karakter Karakter='H'; BESTAND *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; statisch tekenlabel [100]; char-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 breedte, int hoogte) { glViewport (0, 0, breedte, hoogte); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(hazPerspectiva) gluPerspective(23.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f); anders glOrtho(-1, 1, -1, 1, -10, 10); glMatrixMode(GL_MODELVIEW); ancho = breedte; alt=hoogte; } void Kolorear(int K) { float Hip; x=(cx[s]-320)/480; y=(cy[s]-240)/640; Heup=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(); rojo; 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); for;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, "Hallo tekst"); glutBitmapCharacter(GLUT_BITMAP_TIMES_'ROMAN_24, '7);*/ /*glColor3f(1. 0f, 1.0f, 1.0f); setOrthographicProjection(); glPushMatrix(); glLoadIdentity(); renderBitmapString(30, 15, (void *)font, "GLUT Tutorial ---_------_@ 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 april 2015/usb1/rekostruccion 3D en Especialidad CICATA/Software/Reconstructccion 3D/R3d_0\bin/Debug/NuPu.txt"); if (mijnbestand.is_open()) { s=0; while(getline(mijnbestand, regel)) { if((line[0]!='N')&&(line[0]!='F')) { Aux=line; lijn[0]=48; lijn[1]=48; lijn[2]=48; lijn[3]=48; cy[s]=atoi(line.c_str()); Hulp[4]=48; Hulp[5]=48; Hulp[6]=48; //Aux[7]=48; cx[s]=atoi(Aux.c_str()); s++; } } mijnbestand.close(); } else cout <1780)NP=1700; cout< ongeldig inactief () { display (); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'p': case 'P': hazPerspectiva=1; hervormen (ancho, alt); pauze; geval 'o': geval 'O': hazPerspectiva=0; hervormen (ancho, alt); pauze; geval 27: // ontsnappingsuitgang (0); pauze; } } void raton (int-knop, int-status, int x, int y) { /* GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 */ Boton=knop; Pulbut=staat; //mx=j; Scherm(); } void ratmov(int x, int y) { if((Boton==0)&(Pulbut==0)) { mx=y; mijn=x; } if((Boton==2)&(Pulbut==0)) { mtx=(y/200)-1; mty=(x/200)-1; } if((Boton==1)&(Pulbut==0)) { mtz=-(y/40)-5; } Scherm(); } int main(int argc, char **argv) { /*glutAddMenuEntry() glutAddSubMenu() glutAttachMenu() glutCreateMenu() glutSetMenu() glutStrokeCharacter() glutStrokeLength()*/ /*glReadPixels() framebuffer glGetPixelMapfv() geeft de gespecificeerde pixelkaart terug glGetPixelMapuiv() geeft de gespecificeerde pixelkaart terug glGetPointerv() Geeft het adres van de gespecificeerde aanwijzer.*/ Init(); koeloven(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(ancho, alt); glutCreateWindow("Cubo 1"); in het(); glutDisplayFunc(weergave); glutReshapeFunc(hervormen); glutIdleFunc(inactief); glutMouseFunc(raton); glutMotionFunc(ratmov); glutKeyboardFunc(toetsenbord); glutMainLoop(); retourneer 0; }

Stap 5:

Afbeelding
Afbeelding

voorlopig moet ik stoppen! … maar in het volgende hoofdstuk beloof ik je dat ik het zal implementeren op mijn Raspberry pi 3 of mijn jetson nanoboard, al gemonteerd op een op afstand bestuurbaar vliegtuig, of op een spinrobot om het interieur van grotten te scannen

Aanbevolen: