Spisu treści:

Podstawowy skaner 3D do cyfrowego mapowania 3D: 5 kroków
Podstawowy skaner 3D do cyfrowego mapowania 3D: 5 kroków

Wideo: Podstawowy skaner 3D do cyfrowego mapowania 3D: 5 kroków

Wideo: Podstawowy skaner 3D do cyfrowego mapowania 3D: 5 kroków
Wideo: Skanowanie popielnicy twarzowej w technologii 3D 2024, Listopad
Anonim
Podstawowy skaner 3D do cyfrowego mapowania 3D
Podstawowy skaner 3D do cyfrowego mapowania 3D

W tym projekcie opiszę i wyjaśnię podstawowe podstawy skanowania i rekonstrukcji 3D stosowane przede wszystkim do skanowania małych obiektów półpłaszczyznowych, a których działanie można rozszerzyć o systemy skanowania i rekonstrukcji, które można zainstalować na samolotach zdalnie sterowanych w celu uzyskania model 3D. miejsc, w których samolot, który je zabiera, zainstalował muchy

Ostatecznym pomysłem jest uzyskanie skanu 3D jakiegoś miejsca lub obszaru, na zewnątrz lub wewnątrz, aby użyć go jako mapy cyfrowej (jak w filmie Prometeusza)

Krok 1:

Obraz
Obraz

chodzi o zainstalowanie całego systemu skanowania 3d na zdalnie sterowanym samolocie, aby zdigitalizować wirtualną mapę dowolnego obszaru, nad którym leci w 3d, ale w tym celu rozpoczęliśmy od początku działanie metody triangulacji laserowej skanowania lub rekonstrukcji 3D za pomocą triangulacji laserowej zasadniczo polega na przepuszczeniu wiązki laserowej przez pryzmat generujący pasek laserowy w celu uzyskania całego paska laserowego, który zostanie rzutowany na skanowany obiekt, a po uzyskaniu projekcji laserowej na powierzchnia Z miejsca do skanowania obraz musi być uchwycony za pomocą pewnego rodzaju kamery i najlepiej znając kąt, który jest utworzony w odniesieniu do kąta rzutu emitowanego paska laserowego, ponieważ każdy z tych obrazów rejestruje wyświetlane paski laserowe. Na powierzchni obiektu zostaną one wstępnie przetworzone w celu wyodrębnienia cech wymiarowych obiektu, który ma być zeskanowany, i po prostu zeskanuj pasek po pasku nad obiektem, aby uzyskać profil jego powierzchni w tym poprzecznym segmencie obiektu, a następnie uchwycić rzutowany pasek o kolejnym przekroju obiektu, aby zsumować wszystkie rzutowane paski ze sobą Przed wszystkimi przekrojami obto uzyskujemy trójwymiarowy skan jego powierzchni

Krok 2:

Obraz
Obraz

Ponieważ określiliśmy nasz cel, następnym krokiem jest świadomość, że aby wystartować, musisz najpierw mocno stąpać po ziemi, więc rozpoczęliśmy na ziemi od eksperymentalnego prototypu liniowego skanera 3d, aby sprawdzić poprawność działania podstawowego skaner 3d i jak widać na powyższym obrazku użyłem komputera PC, OpenCV, Glut of OpenGL, kamerki internetowej, lasera, generatora farmy laserowej (w tym przypadku poprzez lustro obrotowe) elektronicznego systemu przemieszczenia liniowego (wykonanego z szyny i system wypakowany ze starej drukarki) z bazy, na której umieszczam obiekty do zeskanowania, drewno i plastelina i jak widać na zdjęciu, na komputerze: udało mi się wygenerować i wyświetlić za pomocą Glut z OpenGL trzy- model wymiarowy odtworzony na podstawie zeskanowanego obiektu rzeczywistego (w tym przypadku pająka-zabawki)

więc jest bardziej niż oczywiste, że zasada działania jest funkcjonalna i że dzięki odpowiednim dostosowaniom i adaptacjom do systemu latającego będzie w stanie zeskanować i odtworzyć trójwymiarową mapę obszaru, w którym lata.

Ale ten system będzie służył tylko do uzyskania map 3D zewnętrznej powierzchni miejsc, nad którymi przelatuje???…

Krok 3:

Obraz
Obraz

mapowanie wnętrz jaskiń i kanałów (tak jak w filmie Prometeusz) Ten system skanowania 3D służy również do rekonstrukcji trójwymiarowych modeli wnętrza dużych i pustych w środku obiektów takich jak jaskinie, budynki, tunele itp. jego zasadą działania jest dokładnie to samo, co już opisano i które zasadniczo składa się z następujących elementów:

  1. Zrób zdjęcie każdego rzutu paska laserowego na skanowaną powierzchnię
  2. filtruj i usuwaj kolor z obrazu
  3. zbinaryzować kolor z dynamicznym progiem obrazu
  4. zastosuj detektor krawędzi, aby rozpoznać przechwycony profil każdego przekroju projekcji laserowej;
  5. i za pomocą segmentacji wybierz odpowiednią granicę dla reprezentacji 3D tego przekroju obiektu, który ma być zeskanowany i zrekonstruowany na wirtualnej mapie 3D
  6. następnie te kroki są po prostu powtarzane dla każdego zdjęcia wykonanego w podsekcji pasków laserowych wyświetlanych w sposób ciągły przez każdą podsekcję w podsekcji.
  7. warstwa po warstwie reprezentacji przekrojów są dodawane sukcesywnie aż do uzyskania chmury punktów utworzonej z wielu reprezentacji przekrojów obiektu przeznaczonego do mapowania

Krok 4:

Obraz
Obraz

Następnie przekazuję programy do obróbki obrazu rzutów powierzchniowych pasków laserowych. oraz wirtualną rekonstrukcję 3D tych suspensywnych reprezentacji poprzecznych w opracowanym trójwymiarowym modelu mapy:

przetwarzanie obrazu:

n

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

znak f=0; nazwa znaku={"0.jpg"}; int n=0, s, x, y; CvScalar sp; PLIK *NuPu;

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

IplImage* img0=cvLoadImage("00.jpg", 0); if(f=='0') { for(y=1;ywysokość-2;y++) { for(x=1;xszerokość-2;x++) { sp=cvGet2D(img0, y, x); if(sp.val[0]>50){Punkty zapisu();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, bufor, 10); fprintf(NuPu, "Fin:"); fprintf(NuPu, bufor); fprintf(NuPu, "\n"); fzamknij (NuPu);

cvWaitKey(0); //_execlp("calc.exe", "calc.exe", argstr, NULL); cvZniszczWszystkieOkna(); cvReleaseImage(&obraz); cvReleaseImage(&img); cvReleaseImage(&img0); cvReleaseImage(&img1); cvReleaseImage(&img2); zwróć 0; }

Rekonstrukcja 3D:

#include ////////////////// #ifdef _APPLE_ #include #else #include #include #endif #include #include #include #include #include #include

#define fioletowa 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, moj=0, mtx=0, mty=0, mtz=-5,0; const int Avance=1; linia strunowa, Aux; char Znak='H'; PLIK *NuPu; int NP, h, w; float G=0, n=0, cx[5000], cy[5000], x, y, ax, ay, az; int czcionka=(int)GLUT_BITMAP_8_BY_13; etykieta ze znakami statycznymi[100]; bufor znaków [3]; GLfloat anguloCuboX = 0.0f; GLfloat anguloCuboY = 0.0f; GLfloat anguloEsfera = 0.0f; GLint ancho=500; GLint alto=500; int hazPerspectiva = 0; void reshape(int szerokość, int wysokość) { glViewport(0, 0, szerokość, wysokość); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(hazPerspectiva) gluPerspective(23.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f); w przeciwnym razie glOrtho(-1, 1, -1, 1, -10, 10); glMatrixMode(GL_MODELVIEW); Ancho = szerokość; alt=wysokość; } void Kolorear(int K) { float Hip; x=(cx[s]-320)/480; y=(cy[s]-240)/640; Hip=sqrt(pow(x, 2)+pow(y, 2)); if((biodro>=0)&&(biodro=.07)&&(biodro=.14)&&(biodro=.21)&&(biodro=.28)&&(biodro=.35)&&(biodro=.42) &&(Hip<=.49)){fiolet;} } void drawNuPu(void) { glColor3f(1, 1, 1); glPoczątek(GL_LINES); glVertex3f(.2, 0, 0); glVertex3f(-.2, 0, 0); glVertex3f (0, 0,2, 0); glVertex3f(0, -0,2, 0); gLend(); rojo; glPoczątek(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_HROMAN_24);;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,);*/ /*glColor3f(1. 0f, 1,0f, 1,0f); setOrthographicProjection(); glPushMatrix(); glLoadIdentity(); renderBitmapString(30, 15, (void *)font, "Poradnik GLUT ---_------_@Technologia 3D");*/ glFlush(); glutSwapBufory(); 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 (mojplik.is_open()) { s=0; while(getline(myfile, line)) { if((line[0]!='N')&&(line[0]!='F')) { Aux=line; linia[0]=48; linia[1]=48; linia[2]=48; linia[3]=48; cy[s]=atoi(linia.c_str()); Pomoc[4]=48; Aux[5]=48; Aux[6]=48; //Pomoc[7]=48; cx[s]=atoi(Aux.c_str()); s++; } } mójplik.zamknij(); } w przeciwnym razie cout <1780)NP=1700; cout< void bezczynny() { display(); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'p': case 'P': hazPerspectiva=1; zmienić kształt(ancho, alt); przerwa; przypadek 'o': przypadek 'O': hazPerspectiva=0; zmienić kształt(ancho, alt); przerwa; przypadek 27: // wyjście ewakuacyjne(0); przerwa; } } void raton(int przycisk, int stan, 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=stan; //mx=y; wyświetlacz(); } void ratmov(int x, int y) { if((Boton==0)&(Pulbut==0)) { mx=y; mój=x; } if((Boton==2)&(Pulbut==0)) { mtx=(y/200)-1; mty=(x/200)-1; } if((Boton==1)&(Pulbut==0)) { mtz=-(y/40)-5; } wyświetlacz(); } int main(int argc, char **argv) { /*glutAddMenuEntry() glutAddSubMenu() glutAttachMenu() glutCreateMenu() glutSetMenu() glutStrokeCharacter() glutStrokeLength()*/ /*glReadPixels() odczytuje blok pikseli z bufor ramki glGetPixelMapfv() zwraca określoną mapę pikseli glGetPixelMapuiv() zwraca określoną mapę pikseli glGetPointerv() Zwraca adres podanego wskaźnika.*/ Init(); chytre spojrzenie(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(ancho, alt); glutCreateWindow("Cubo 1"); w tym(); glutDisplayFunc(wyświetlanie); glutReshapeFunc(przekształcenie); funkcja glutIdle(bezczynny); glutMouseFunc(raton); glutMotionFunc(ratmov); glutKeyboardFunc(klawiatura); glutMainLoop(); zwróć 0; }

Krok 5:

Obraz
Obraz

na razie muszę przestać! …ale w następnym rozdziale obiecuję, że zaimplementuję go na mojej raspberry pi 3 lub mojej nanoboardzie jetson, zamontowanych już na jakimś zdalnie sterowanym samolocie, lub na jakimś pajęczym robocie do skanowania wnętrz jaskiń

Zalecana: