Índice:

Scanner 3D básico para mapeamento 3D digital: 5 etapas
Scanner 3D básico para mapeamento 3D digital: 5 etapas

Vídeo: Scanner 3D básico para mapeamento 3D digital: 5 etapas

Vídeo: Scanner 3D básico para mapeamento 3D digital: 5 etapas
Vídeo: SCANNER DE BANCADA SHINING 3D - GUIA RÁPIDO DE ESCANEAMENTO * 2024, Setembro
Anonim
Scanner 3D básico para mapeamento 3D digital
Scanner 3D básico para mapeamento 3D digital

Neste projeto, vou descrever e explicar os fundamentos básicos da digitalização e reconstrução 3D aplicada principalmente à digitalização de pequenos objetos semiplanos, e cuja operação pode ser estendida a sistemas de digitalização e reconstrução que podem ser instalados em aeronaves de controle remoto para obter um modelo 3D. dos locais onde voa o avião que os leva instalado

A ideia final é obter uma digitalização 3D de algum lugar ou área, seja seu exterior ou interior, para utilizá-lo como um mapa digital (como no filme do Prometeus)

Passo 1:

Imagem
Imagem

a ideia é instalar todo o sistema de escaneamento 3d em um plano de controle remoto, a fim de digitalizar o mapa virtual de qualquer área sobre a qual voe em 3d, mas para isso partimos do início da operação de triangulação a laser o método de digitalização ou reconstrução 3d por triangulação a laser consiste basicamente em passar um feixe de laser através de um prisma que gera uma faixa de laser para obter uma faixa de laser inteira que será projetada em um objeto a ser digitalizado, e uma vez que essa projeção de laser tenha sido obtida no superfície superfície Do local a ser escaneado, a imagem deve ser capturada com algum tipo de câmera e de preferência conhecendo o ângulo que se forma em relação ao ângulo de projeção da faixa de laser emitida, pois cada uma dessas imagens captura as faixas de laser projetadas. Na superfície do objeto, eles serão pré-processados para extrair as características dimensionais do objeto a ser digitalizado, e simplesmente digitalizar tira por tira acima do objeto para obter o perfil de sua superfície naquele segmento transversal do objeto e, posteriormente, capturar a tira projetada da seguinte seção transversal do objeto, para somar todas as listras projetadas juntas. Antes de todas as seções transversais do obto, obtemos uma varredura tridimensional de sua superfície

Passo 2:

Imagem
Imagem

Já que identificamos nosso objetivo, o próximo passo sabendo que para decolar é preciso primeiro ter os pés bem assentes no chão, por isso partimos no solo com um protótipo experimental de um scanner linear 3D, para validar o correto funcionamento do básico Scanner 3D e como você pode ver na imagem acima, usei um PC, OpenCV, Glut of OpenGL, uma webcam, um laser, gerador de laser farm (neste caso através de um espelho rotacional) um sistema eletrônico de deslocamento linear (feito com trilho e sistema extraído de uma impressora antiga) de uma base na qual coloco os objetos a serem digitalizados, madeira e plasticina e como vocês podem ver na foto, no computador: Consegui gerar e exibir com o Glut do OpenGL um três- modelo dimensional reproduzido com base no objeto real digitalizado (neste caso, uma aranha de brinquedo)

portanto, é mais do que evidente que o princípio de funcionamento é funcional, e que com seus respectivos ajustes e adaptações a um sistema voador será capaz de escanear e reproduzir um mapa 3D da área em que voa.

Mas este sistema servirá apenas para obter mapas 3D da superfície externa dos locais por onde sobrevoa ???…

Etapa 3:

Imagem
Imagem

mapeamento do interior das cavernas e dutos (assim como no filme Prometeus) Este sistema de digitalização 3D também serve para reconstruir modelos tridimensionais do interior de objetos grandes e ocos, como cavernas, edifícios, túneis, etc. seu princípio de funcionamento é exatamente o mesmo já descrito e que consiste basicamente no seguinte:

  1. capture a foto de cada projeção da faixa de laser na superfície a ser digitalizada
  2. filtrar e remover a cor da imagem
  3. binarize a cor com um limiar de imagem dinâmico
  4. aplique um detector de borda para reconhecer o perfil capturado de cada seção transversal de projeção de laser
  5. e usando a segmentação, selecione a borda apropriada para a representação 3d daquela seção transversal do objeto a ser digitalizado e reconstruído no mapa 3D virtual
  6. em seguida, essas etapas são simplesmente repetidas para cada foto tirada em uma subseção das faixas de laser continuamente projetadas por cada subseção na subseção.
  7. camada por camada da representação das seções transversais são adicionadas sucessivamente até a obtenção de uma nuvem de pontos formada por várias representações das seções transversais do objeto a ser mapeado

Passo 4:

Imagem
Imagem

Em seguida, passo os programas para processamento de imagem das projeções das tiras de laser superficiais. e da reconstrução virtual em 3D dessas representações transversais no modelo de mapa tridimensional elaborado:

processamento de imagem:

n

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

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

void Writepoints () {char bufferx [33], buffery [33]; itoa (x, bufferx, 10); itoa (y, buffery, 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; 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);

cvWaitKey (0); //_execlp("calc.exe "," calc.exe ", argstr, NULL); cvDestroyAllWindows (); cvReleaseImage (& imagem); cvReleaseImage (& img); cvReleaseImage (& img0); cvReleaseImage (& img1); cvReleaseImage (& img2); return 0; }

Reconstrução 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) usando namespace std; int s, Boton = 1, Pulbut = 1; float mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5,0; const int Avance = 1; linha de string, Aux; char Caracter = 'H'; ARQUIVO * NuPu; int NP, h, w; flutuante G = 0, n = 0, cx [5000], cy [5000], x, y, ax, ay, az; fonte int = (int) GLUT_BITMAP_8_BY_13; etiqueta de char estática [100]; buffer char [3]; GLfloat anguloCuboX = 0,0f; GLfloat anguloCuboY = 0,0f; GLfloat anguloEsfera = 0,0f; GLint ancho = 500; GLint alto = 500; int hazPerspectiva = 0; void reshape (largura interna, altura interna) {glViewport (0, 0, largura, altura); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (hazPerspectiva) gluPerspective (23.0f, (GLfloat) largura / (GLfloat) height, 1.0f, 20.0f); senão glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); ancho = largura; alto = altura; } 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 ((Hip> = 0) && (Hip = 0,07) && (Hip = 0,14) && (Hip = 0,21) && (Hip = 0,28) && (Hip = 0,35) && (Hip = 0,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, para "Hello Text" 0; s <3; s ++) {glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, buffer [s]);} glTranslatef (mty, -mtx, mtz); glRotatef (mx, 1.0f, 0.0f, 0.0f); glRotatef (meu, 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"); glutBitmap_ROM24 '); * / / * 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; alto = 500; } void leer () {ifstream myfile ("A: / Respaldo set 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; linha [0] = 48; linha [1] = 48; linha [2] = 48; linha [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 ++; }} meuarquivo.close (); } else cout <1780) NP = 1700; cout <void idle () {display (); } teclado vazio (tecla sem sinal, int x, int y) {switch (tecla) {case 'p': case 'P': hazPerspectiva = 1; remodelar (ancho, alto); pausa; caso 'o': caso 'O': hazPerspectiva = 0; remodelar (ancho, alto); pausa; caso 27: // escape exit (0); pausa; }} void raton (int botão, int estado, int x, int y) {/ * GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 * / Boton = botão; Pulbut = estado; // mx = y; exibição(); } void ratmov (int x, int y) {if ((Botão == 0) & (Pulbut == 0)) {mx = y; meu = x; } if ((Botão == 2) & (Pulbut == 0)) {mtx = (y / 200) -1; mty = (x / 200) -1; } if ((Botão == 1) & (Pulbut == 0)) {mtz = - (y / 40) -5; } exibição(); } int main (int argc, char ** argv) {/ * glutAddMenuEntry () glutAddSubMenu () glutAttachMenu () glutCreateMenu () glutSetMenu () glutStrokeCharacter () glutStrokeLength () * / / * glReadPixels de leitura de um bloco de pixels () buffer de quadro glGetPixelMapfv () retorna o mapa de pixel especificado glGetPixelMapuiv () retorna o mapa de pixel especificado glGetPointerv () Retorna o endereço do ponteiro especificado. * / Init (); olhar malicioso (); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (ancho, alto); glutCreateWindow ("Cubo 1"); iniciar(); glutDisplayFunc (display); glutReshapeFunc (remodelar); glutIdleFunc (idle); glutMouseFunc (raton); glutMotionFunc (ratmov); glutKeyboardFunc (teclado); glutMainLoop (); return 0; }

Etapa 5:

Imagem
Imagem

por enquanto, tenho que parar! … Mas no próximo capítulo prometo que irei implementá-lo no meu raspberry pi 3 ou no meu jetson nanoboard, já montado em alguma aeronave de controle remoto, ou em algum robô aranha para escanear o interior de cavernas

Recomendado: