Tabla de contenido:
Video: Escáner 3D básico para mapeo digital 3D: 5 pasos
2024 Autor: John Day | [email protected]. Última modificación: 2024-01-30 08:41
En este proyecto, describiré y explicaré los fundamentos básicos del escaneo y reconstrucción 3D aplicados principalmente al escaneo de pequeños objetos semiplanos, y cuyo funcionamiento se puede extender a sistemas de escaneo y reconstrucción que se pueden instalar en aviones de control remoto para obtener un modelo 3D. de los lugares donde vuela el avión que los lleva instalado
La idea final es obtener un escaneo 3D de algún lugar o zona, ya sea su exterior o su interior, para utilizarlo como mapa digital (como en la película de Prometeus)
Paso 1:
la idea es instalar todo el sistema de escaneo 3d en un plano teledirigido, con el fin de digitalizar el mapa virtual de cualquier zona sobre la que vuele en 3d, pero para ello partimos desde el inicio de la operación de la triangulación láser el método de exploración o reconstrucción 3d por triangulación láser consiste básicamente en pasar un rayo láser a través de un prisma que genera una franja láser para obtener una franja láser completa que se proyectará sobre un objeto a escanear, y una vez obtenida esta proyección láser en el superficie superficie Desde el lugar a escanear, la imagen debe ser capturada con algún tipo de cámara y preferiblemente conociendo el ángulo que se forma con respecto al ángulo de proyección de la franja láser emitida, ya que cada una de estas imágenes captura las franjas láser proyectadas. Sobre la superficie del objeto, serán preprocesados para extraer las características dimensionales del objeto a escanear, y simplemente escanear tira a tira encima del objeto para obtener el perfil de su superficie en ese segmento transversal del objeto, y posteriormente capturar la franja proyectada de la siguiente sección transversal del objeto, para sumar todas las franjas proyectadas juntas Antes de todas las secciones transversales del obto obtenemos un escaneo tridimensional de su superficie
Paso 2:
Ya que hemos identificado nuestro objetivo, el siguiente paso sabiendo que para despegar primero debes tener los pies firmes en el suelo, por eso empezamos en el suelo con un prototipo experimental de un escáner 3d lineal, para validar el correcto funcionamiento del básico. Escáner 3d y como se puede ver en la imagen de arriba, utilicé un PC, OpenCV, Glut de OpenGL, una webcam, un láser, un generador de granja láser (en este caso a través de un espejo rotacional) un sistema electrónico de desplazamiento lineal (hecho con un riel). y sistema extraído de una impresora antigua) de una base sobre la que coloco los objetos a escanear, madera y plastilina y como se puede ver en la foto, en la computadora: logré generar y mostrar con Glut desde OpenGL un tres- modelo dimensional reproducido en base al objeto real escaneado (en este caso, una araña de juguete)
por lo que es más que evidente que el principio de funcionamiento es funcional, y que con sus respectivos ajustes y adaptaciones a un sistema de vuelo podrá escanear y reproducir un mapa 3d de la zona en la que vuela.
Pero este sistema solo servirá para obtener mapas en 3D de la superficie externa de los lugares sobre los que sobrevuela ???…
Paso 3:
mapeo del interior de las cuevas y conductos (como en la película Prometeus) Este sistema de escaneo 3D también sirve para reconstruir modelos tridimensionales del interior de objetos grandes y huecos como cuevas, edificios, túneles, etc. su principio de funcionamiento es exactamente igual al ya descrito y que básicamente consiste en lo siguiente:
- capturar la foto de cada proyección de la franja láser en la superficie a escanear
- filtrar y eliminar el color de la imagen
- binarizar el color con un umbral de imagen dinámico
- aplicar un detector de bordes para reconocer el perfil capturado de cada sección transversal de proyección láser
- y utilizando la segmentación, seleccione el borde apropiado para la representación en 3D de esa sección transversal del objeto que se escaneará y reconstruirá en el mapa virtual en 3D.
- luego, estos pasos simplemente se repiten para cada foto tomada en una subsección de las rayas láser proyectadas continuamente por cada subsección en la subsección.
capa a capa de la representación de las secciones transversales se van añadiendo sucesivamente hasta obtener una nube de puntos formada por muchas representaciones de las secciones transversales del objeto a cartografiar
Paso 4:
Luego paso los programas para el procesamiento de imágenes de las proyecciones de las tiras láser superficiales. y de la reconstrucción virtual en 3D de estas representaciones transversales en el elaborado modelo de mapa tridimensional:
procesamiento de imágenes:
norte
#include #include "cv.h" #include "highgui.h" #include // # include #include #include #include
char f = 0; char name = {"0.jpg"}; int n = 0, s, x, y; CvScalar sp; ARCHIVO * NuPu;
Void Writepoints () {char bufferx [33], buffery [33]; itoa (x, bufferx, 10); itoa (y, buffery, 10); fprintf (NuPu, bufferx); fprintf (NuPu, "\ t"); fprintf (NuPu, búfer); fprintf (NuPu, "\ n"); }
anular 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; nombre [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 ++;}}}} búfer de caracteres [33]; itoa (n, tampón, 10); fprintf (NuPu, "Fin:"); fprintf (NuPu, búfer); fprintf (NuPu, "\ n"); fclose (NuPu);
cvWaitKey (0); //_execlp("calc.exe "," calc.exe ", argstr, NULL); cvDestroyAllWindows (); cvReleaseImage (& imagen); cvReleaseImage (& img); cvReleaseImage (& img0); cvReleaseImage (& img1); cvReleaseImage (& img2); return 0; }
Reconstrucción 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; flotar mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5.0; const int Avance = 1; línea de cuerda, Aux; char Caracter = 'H'; ARCHIVO * NuPu; int NP, h, w; flotante G = 0, n = 0, cx [5000], cy [5000], x, y, ax, ay, az; int fuente = (int) GLUT_BITMAP_8_BY_13; etiqueta de carbón estático [100]; tampón de carbón [3]; GLfloat anguloCuboX = 0.0f; GLfloat anguloCuboY = 0.0f; GLfloat anguloEsfera = 0.0f; GLint ancho = 500; GLint alto = 500; int hazPerspectiva = 0; remodelación vacía (ancho int, alto int) {glViewport (0, 0, ancho, alto); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (hazPerspectiva) gluPerspective (23.0f, (GLfloat) width / (GLfloat) height, 1.0f, 20.0f); más glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); ancho = ancho; alto = altura; } void Kolorear (int K) {flotar Hip; x = (cx [s] -320) / 480; y = (cy [s] -240) / 640; Cadera = raíz cuadrada (pow (x, 2) + pow (y, 2)); si ((Cadera> = 0) && (Cadera =.07) && (Cadera =.14) && (Cadera =.21) && (Cadera =.28) && (Cadera =.35) && (Cadera =.42) && (Hip <=. 49)) {violeta;}} vacío drawNuPu (vacío) {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; for_ROM; 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, "Texto de saludo"); glutBitmapCharacter '(GLUT_24, MAP_7); * / / * glColor3f (1. 0f, 1.0f, 1.0f); setOrthographicProjection (); glPushMatrix (); glLoadIdentity (); renderBitmapString (30, 15, (void *) fuente, "Tutorial 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); ancho = 500; alto = 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 (miarchivo.is_open ()) {s = 0; while (getline (miarchivo, línea)) {if ((línea [0]! = 'N') && (línea [0]! = 'F')) {Aux = línea; línea [0] = 48; línea [1] = 48; línea [2] = 48; línea [3] = 48; cy [s] = atoi (línea.c_str ()); Aux [4] = 48; Aux [5] = 48; Aux [6] = 48; // Aux [7] = 48; cx [s] = atoi (Aux.c_str ()); s ++; }} myfile.close (); } más cout <1780) NP = 1700; cout <vacío inactivo () {pantalla (); } teclado vacío (tecla de carácter sin firmar, int x, int y) {interruptor (tecla) {caso 'p': caso 'P': hazPerspectiva = 1; remodelar (ancho, alto); rotura; caso 'o': caso 'O': hazPerspectiva = 0; remodelar (ancho, alto); rotura; caso 27: // escape exit (0); rotura; }} 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 = botón; Pulbut = estado; // mx = y; monitor(); } void ratmov (int x, int y) {if ((Boton == 0) & (Pulbut == 0)) {mx = y; mi = x; } if ((Boton == 2) & (Pulbut == 0)) {mtx = (y / 200) -1; mty = (x / 200) -1; } if ((Boton == 1) & (Pulbut == 0)) {mtz = - (y / 40) -5; } monitor(); } int main (int argc, char ** argv) {/ * glutAddMenuEntry () glutAddSubMenu () glutAttachMenu () glutCreateMenu () glutSetMenu () glutStrokeCharacter () glutStrokeLength () * / / * bloque de píxeles readPix () frame buffer glGetPixelMapfv () devuelve el mapa de píxeles especificado glGetPixelMapuiv () devuelve el mapa de píxeles especificado glGetPointerv () Devuelve la dirección del puntero especificado. * / Init (); mirada lasciva(); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (ancho, alto); glutCreateWindow ("Cubo 1"); en eso(); glutDisplayFunc (pantalla); glutReshapeFunc (remodelar); glutIdleFunc (inactivo); glutMouseFunc (raton); glutMotionFunc (ratmov); glutKeyboardFunc (teclado); glutMainLoop (); return 0; }
Paso 5:
por el momento tengo que parar! … Pero en el próximo capítulo te prometo que lo implementaré en mi raspberry pi 3 o mi nanoboard jetson, ya montado en algún avión teledirigido, o en algún robot araña para escanear el interior de cuevas
Recomendado:
Consejos de mapeo: 3 pasos
Sugerencias de mapeo: sea cual sea su actividad, ya sea caminar, hacer senderismo, andar en bicicleta o incluso conducir, puede registrar las rutas que realiza. Luego, puede compartir esas rutas con amigos y familiares. Además, puede usar la ruta grabada para agregar ubicaciones a cualquier foto que pueda h
Escáner de emergencia para ancianos: 6 pasos
Escáner de emergencia para personas mayores: Este proyecto se basa en ayudar a las personas mayores. Las personas mayores suelen estar solas en su casa y es posible que no estén cerca de ayuda inmediata si se han caído. La solución actual en el mercado es el uso de un SOS que llevan alrededor
Escáner de cartas para una máquina de cartas coleccionables: 13 pasos (con imágenes)
Escáner de tarjetas para una máquina de tarjetas comerciales: Escáner de tarjetas para una máquina de tarjetas comerciales El registro de cambios se puede encontrar en el último paso. Pero en resumen, mis hijos y yo hemos acumulado una gran cantidad de Trading Cards b
Mapeo Análogo: Manual Para Mascarilla De Proyector: 14 Pasos
Mapeo Análogo: Manual Para Mascarilla De Proyector: Para qu é sirve un Mapping An á logo? ¿Tienes ganas de hacer una proyección que salga del formato rectangular? Pero no es posible, porque desde el proyector siempre saldr á un imagen rectangular (aunque sea luz negra y que en
Cómo hacer un mapeo de proyección con la tapa Pi: 9 pasos (con imágenes)
Cómo hacer un mapeo de proyección con Pi Cap: Nos hemos inspirado en sus proyectos y hemos creado un tutorial de mapeo de proyección utilizando Pi Cap. Si desea que su proyecto funcione de forma inalámbrica a través de WiFi, este es el tutorial para usted. Usamos MadMapper como un software de mapeo de proyección