Innehållsförteckning:

Grundläggande 3D -skanner för digital 3D -kartläggning: 5 steg
Grundläggande 3D -skanner för digital 3D -kartläggning: 5 steg

Video: Grundläggande 3D -skanner för digital 3D -kartläggning: 5 steg

Video: Grundläggande 3D -skanner för digital 3D -kartläggning: 5 steg
Video: 3D-modellering och -design 2024, September
Anonim
Grundläggande 3D -skanner för digital 3D -kartläggning
Grundläggande 3D -skanner för digital 3D -kartläggning

I detta projekt kommer jag att beskriva och förklara de grundläggande grunderna för 3D-skanning och rekonstruktion som främst tillämpas på skanning av små halvplanobjekt, och vars verksamhet kan utvidgas till skannings- och rekonstruktionssystem som kan installeras på fjärrkontrollflygplan för att erhålla en 3D -modell. av de platser där flygplanet som tar dem installerade flyger

Den slutliga idén är att få en 3D -skanning av någon plats eller område, antingen dess yttre eller inre, för att använda den som en digital karta (som i filmen Prometeus)

Steg 1:

Bild
Bild

tanken är att installera hela 3d-skanningssystemet på ett fjärrstyrt plan, för att digitalisera den virtuella kartan över alla områden som det flyger över i 3d, men för detta började vi från början av lasertrianguleringens metod av skanning eller 3d -rekonstruktion genom lasertriangulering består i grunden av att leda en laserstråle genom ett prisma som genererar en laserstrimmel för att erhålla en hel laserremsa som kommer att projiceras på ett objekt som ska skannas, och när denna laserprojektion har erhållits på ytyta Från platsen för skanning måste bilden fångas med någon typ av kamera och helst känna till vinkeln som bildas med avseende på projektionsvinkeln för den utsända laserremsan, eftersom var och en av dessa bilder fångar de projicerade laserremsorna. På ytan av objektet kommer de att förbehandlas för att extrahera dimensionskarakteristika för objektet som ska skannas, och helt enkelt skanna remsor för remsor ovanför objektet för att få profilen på dess yta i det tvärgående segmentet av objektet och därefter fånga den projicerade remsan av följande tvärsnitt av objektet, för att lägga till alla projicerade ränder tillsammans Innan alla tvärsnitt av obto får vi en tredimensionell skanning av dess yta

Steg 2:

Bild
Bild

Eftersom vi har identifierat vårt mål, nästa steg att veta att för att lyfta måste du först ha fötterna stadigt på marken, så vi började på marken med en experimentell prototyp av en linjär 3d -skanner, för att validera den korrekta funktionen av den grundläggande 3d -skanner och som du kan se på bilden ovan använde jag en PC, OpenCV, Glut från OpenGL, en webbkamera, en laser, laser gårdsgenerator (i detta fall genom en rotationsspegel) ett elektroniskt linjärt förskjutningssystem (tillverkat med en skena och system extraherat från en gammal skrivare) från en bas på vilken jag placerar föremålen som ska skannas, trä och plasticine och som du kan se på bilden, på datorn: Jag lyckades generera och visa med Glut från OpenGL en tre- dimensionell modell reproducerad baserad på det skannade riktiga föremålet (i detta fall en leksaksspindel)

så det är mer än uppenbart att driftsprincipen är funktionell, och att den med sina respektive justeringar och anpassningar till ett flygande system kommer att kunna skanna och återge en 3d -karta över området där den flyger.

Men detta system kommer bara att tjäna till att få 3D -kartor över den yttre ytan på de platser det flyger över ??? …

Steg 3:

Bild
Bild

kartläggning av det inre av grottorna och kanalerna (precis som i Prometeus-filmen) Detta 3D-skanningssystem tjänar också till att rekonstruera tredimensionella modeller av det inre av stora och ihåliga föremål som grottor, byggnader, tunnlar etc. dess driftsprincip är exakt samma som redan beskrivits och som i princip består av följande:

  1. ta fotot av varje projektion av laserremsan på ytan som ska skannas
  2. filtrera och ta bort färg från bilden
  3. binarize färgen med en dynamisk bildtröskel
  4. applicera en kantdetektor för att känna igen den fångade profilen för varje laserprojektionstvärsnitt
  5. och med hjälp av segmentering välj lämplig kant för 3D -representationen av det tvärsnittet av objektet som ska skannas och rekonstrueras på den virtuella 3D -kartan
  6. sedan upprepas dessa steg helt enkelt för varje foto som tas på ett under sätt av laserstrimlorna som kontinuerligt projiceras av varje delsektion i delsektionen.
  7. lager för lager av representationen av tvärsektionerna läggs till successivt tills man erhåller ett punktmoln bildat av många representationer av tvärsnitt av objektet som ska kartläggas

Steg 4:

Bild
Bild

Sedan skickar jag programmen för bildbehandling av projektionerna på de ytliga laserremsorna. och av den virtuella 3d-rekonstruktionen av dessa sussiva transversala representationer i den utarbetade tredimensionella kartmodellen:

bildbehandling:

n

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

char f = 0; char namn = {"0.jpg"}; int n = 0, s, x, y; CvScalar sp; FIL *NuPu;

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

IplImage* img0 = cvLoadImage ("00.jpg", 0); om (f == '0') {för (y = 1; yheight-2; y ++) {för (x = 1; xwidth-2; x ++) {sp = cvGet2D (img0, y, x); if (sp.val [0]> 50) {Writepoints (); n ++;}}}} else {för (y = 1; yheight-2; y ++) {för (x = 1; xwidth-2; x ++) { sp = cvGet2D (img1, y, x); if (sp.val [0]> 50) {Writepoints (); n ++;}}}} char buffert [33]; itoa (n, buffert, 10); fprintf (NuPu, "Fin:"); fprintf (NuPu, buffert); 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); returnera 0; }

3D -rekonstruktion:

#include ////////////////////ifif #_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) med namnrymd std; int s, Boton = 1, Pulbut = 1; float mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5,0; const int Avance = 1; stränglinje, Aux; char Character = 'H'; FIL *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; statisk rödmärkning [100]; rödingbuffert [3]; GLfloat anguloCuboX = 0,0f; GLfloat anguloCuboY = 0,0f; GLfloat anguloEsfera = 0,0f; Glint ancho = 500; Glint alt=500; int hazPerspectiva = 0; void omforma (int bredd, int höjd) {glViewport (0, 0, bredd, höjd); glMatrixMode (GL_PROJECTION); glLoadIdentity (); om (hazPerspectiva) gluPerspective (23.0f, (GLfloat) bredd/(GLfloat) höjd, 1.0f, 20.0f); annars glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); ancho = bredd; alt=höjd; } void Kolorear (int K) {float Hip; x = (cx [s] -320)/480; y = (cy [s] -240)/640; Höft = sqrt (pow (x, 2)+pow (y, 2)); om ((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); för (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, buffert [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_BITMB_MIT_BITM_);* / /*glColor3f (1. 0f, 1.0f, 1.0f); setOrthographicProjection (); glPushMatrix (); glLoadIdentity (); renderBitmapString (30, 15, (void *) teckensnitt, "GLUT Tutorial ---_ ------ _@ 3D Tech"); */ glFlush (); glutSwapBuffers (); anguloCuboX+= 0,1 f; 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"); om (myfile.is_open ()) {s = 0; while (getline (myfile, line)) {if ((line [0]! = 'N') && (line [0]! = 'F')) {Aux = line; rad [0] = 48; rad [1] = 48; rad [2] = 48; rad [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 (); } annars cout <1780) NP = 1700; cout <void idle () {display (); } ogiltigt tangentbord (osignerad char -nyckel, int x, int y) {switch (key) {case 'p': case 'P': hazPerspectiva = 1; omforma (ancho, alto); ha sönder; fall 'o': fall 'O': hazPerspectiva = 0; omforma (ancho, alto); ha sönder; fall 27: // escape exit (0); ha sönder; }} void raton (int -knapp, int -tillstånd, int x, int y) { / * GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 * / Boton = -knapp; Pulbut = tillstånd; // mx = y; visa(); } void ratmov (int x, int y) {if ((Boton == 0) & (Pulbut == 0)) {mx = y; min = x; } om ((Boton == 2) & (Pulbut == 0)) {mtx = (y/200) -1; mty = (x/200) -1; } om ((Boton == 1) & (Pulbut == 0)) {mtz =-(y/40) -5; } display (); } int main (int argc, char ** argv) { /*glutAddMenuEntry () glutAddSubMenu () glutAttachMenu () glutCreateMenu () glutSetMenu () glutStrokeCharacter () glutStrokeLength ()* / /*glReadPixels () rambuffert glGetPixelMapfv () returnerar den angivna pixelkartan glGetPixelMapuiv () returnerar den angivna pixelkartan glGetPointerv () Returnerar adressen till den angivna pekaren.*/ Init (); leer (); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (ancho, alto); glutCreateWindow ("Cubo 1"); i det(); glutDisplayFunc (display); glutReshapeFunc (omforma); glutIdleFunc (inaktiv); glutMouseFunc (raton); glutMotionFunc (ratmov); glutKeyboardFunc (tangentbord); glutMainLoop (); returnera 0; }

Steg 5:

Bild
Bild

för tillfället måste jag sluta! … men i nästa kapitel lovar jag dig att jag kommer att implementera det på min hallon pi 3 eller mitt jetson nanoboard, redan monterat på några fjärrstyrda flygplan, eller på någon spindelrobot för att skanna inuti grottor

Rekommenderad: