Оглавление:

Базовый 3D-сканер для цифровых 3D-карт: 5 шагов
Базовый 3D-сканер для цифровых 3D-карт: 5 шагов

Видео: Базовый 3D-сканер для цифровых 3D-карт: 5 шагов

Видео: Базовый 3D-сканер для цифровых 3D-карт: 5 шагов
Видео: Рейтинг 3D сканеров 2023 | Лучшие 3Д сканеры для работы и бизнеса | Выбираем 3Д сканер ! 2024, Ноябрь
Anonim
Базовый 3D-сканер для цифровых 3D-карт
Базовый 3D-сканер для цифровых 3D-карт

В этом проекте я опишу и объясню основные основы 3D-сканирования и реконструкции, применяемые в первую очередь для сканирования небольших полуплоскостных объектов, и чьи действия могут быть расширены до систем сканирования и реконструкции, которые могут быть установлены на самолетах с дистанционным управлением для получения 3D модель. мест, где пролетает установленный ими самолет

Конечная идея - получить 3D-сканирование некоторого места или области, снаружи или внутри, чтобы использовать их в качестве цифровой карты (как в фильме Прометея).

Шаг 1:

Изображение
Изображение

Идея состоит в том, чтобы установить всю систему 3D-сканирования на дистанционно управляемой плоскости, чтобы оцифровать виртуальную карту любой области, над которой он летит, в 3D, но для этого мы начали с самого начала работы лазерной триангуляции. Сканирование или 3D-реконструкция с помощью лазерной триангуляции в основном состоит из прохождения лазерного луча через призму, которая генерирует лазерную полосу для получения всей лазерной полосы, которая будет проецироваться на сканируемый объект, и как только эта лазерная проекция будет получена на поверхность поверхность От места сканирования изображение должно быть захвачено камерой определенного типа и, желательно, зная угол, который образуется по отношению к углу проекции излучаемой лазерной полосы, поскольку каждое из этих изображений захватывает проецируемые лазерные полосы. На поверхности объекта они будут предварительно обработаны для извлечения размерных характеристик объекта, подлежащего сканированию, и просто сканировать полоску за полосой над объектом, чтобы получить профиль его поверхности в этом поперечном сегменте объекта, а затем зафиксировать проецируемая полоса следующего поперечного сечения объекта, чтобы сложить все проецируемые полосы вместе. Перед всеми поперечными сечениями объекта мы получаем трехмерное сканирование его поверхности

Шаг 2:

Изображение
Изображение

Поскольку мы определили нашу цель, следующий шаг, зная, что для взлета вы должны сначала твердо стоять на земле, поэтому мы начали работу на земле с экспериментального прототипа линейного 3D-сканера, чтобы проверить правильность работы основного 3D-сканер, и, как вы можете видеть на изображении выше, я использовал ПК, OpenCV, Glut of OpenGL, веб-камеру, лазер, лазерный генератор фермы (в данном случае через вращающееся зеркало), электронную систему линейного смещения (сделанную с помощью рельса). и система, извлеченная из старого принтера) с базы, на которую я помещаю объекты для сканирования, дерево и пластилин, и, как вы можете видеть на фотографии, на компьютере: мне удалось сгенерировать и отобразить с помощью Glut из OpenGL трехкратный размерная модель воспроизводится на основе отсканированного реального объекта (в данном случае игрушечного паука)

Таким образом, более чем очевидно, что принцип действия является функциональным, и что с его соответствующими настройками и адаптациями к летающей системе он сможет сканировать и воспроизводить трехмерную карту области, в которой он летит.

Но эта система будет служить только для получения трехмерных карт внешней поверхности мест, над которыми она пролетает ???…

Шаг 3:

Изображение
Изображение

картирование интерьера пещер и каналов (как в фильме «Прометей»). Эта система трехмерного сканирования также служит для реконструкции трехмерных моделей интерьера больших и полых объектов, таких как пещеры, здания, туннели и т. д., принцип ее работы заключается в следующем. точно так же, как уже было описано, и в основном состоит из следующего:

  1. сделайте снимок каждой проекции лазерной полосы на сканируемой поверхности
  2. фильтровать и удалять цвет с изображения
  3. преобразовать цвет в двоичную форму с помощью порога динамического изображения
  4. применить детектор края для распознавания захваченного профиля каждого поперечного сечения лазерной проекции
  5. и с помощью сегментации выберите подходящую границу для трехмерного представления этого поперечного сечения объекта, который нужно сканировать и реконструировать на виртуальной трехмерной карте.
  6. затем эти шаги просто повторяются для каждой фотографии, сделанной в виде лазерных полос, непрерывно проецируемых каждым подразделом в подразделе.
  7. слой за слоем представления поперечных сечений добавляются последовательно до тех пор, пока не будет получено облако точек, образованное множеством представлений поперечных сечений объекта, подлежащего отображению

Шаг 4:

Изображение
Изображение

Затем прохожу программы обработки изображений проекций поверхностных лазерных полосок. и виртуальной трехмерной реконструкции этих субъективных поперечных представлений в разработанной трехмерной модели карты:

обработка изображений:

п

#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; ФАЙЛ * NuPu;

void Writepoints () {char bufferx [33], buffery [33]; itoa (x, bufferx, 10); итоа (у, буферизация, 10); fprintf (NuPu, bufferx); fprintf (NuPu, "\ т"); fprintf (NuPu, буферизация); fprintf (NuPu, "\ п"); }

void noteblockInit () {NuPu = fopen ("NuPu.txt", "w"); fseek (NuPu, 0, 0); fprintf (NuPu, «НП:»); fprintf (NuPu, "\ п"); }

int main () {char argstr [128]; noteblockInit (); cout << "Теклея!…:" f; имя [0] = f; cout <

IplImage * img0 = cvLoadImage ("00.jpg", 0); if (f == '0') {для (y = 1; yheight-2; y ++) {для (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, буфер, 10); fprintf (NuPu, «Фин:»); fprintf (NuPu, буфер); fprintf (NuPu, "\ п"); fclose (NuPu);

cvWaitKey (0); //_execlp("calc.exe "," calc.exe ", argstr, NULL); cvDestroyAllWindows (); cvReleaseImage (& изображение); cvReleaseImage (& img); cvReleaseImage (& img0); cvReleaseImage (& img1); cvReleaseImage (& img2); возврат 0; }

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; float mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5.0; const int Avance = 1; струнная линия, Aux; char Caracter = 'H'; ФАЙЛ * 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; метка статического символа [100]; char buffer [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 width, int height) {glViewport (0, 0, ширина, высота); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (hazPerspectiva) gluPerspective (23.0f, (GLfloat) width / (GLfloat) height, 1.0f, 20.0f); иначе glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); анчо = ширина; alto = высота; } void Kolorear (int K) {float Hip; х = (сх [с] -320) / 480; y = (cy [s] -240) / 640; Бедро = sqrt (pow (x, 2) + pow (y, 2)); if ((Hip> = 0) && (Hip =.07) && (Hip =.14) && (Hip =.21) && (Hip =.28) && (Hip =.35) && (Hip =.42) && (бедро <=. 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 (); Рохо; 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_TIMES;; 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 '(GL_ANT_24ES_APP_GL_ANT_BITM_); * / / * glColor3f (1. 0f, 1.0f, 1.0f); setOrthographicProjection (); glPushMatrix (); glLoadIdentity (); renderBitmapString (30, 15, (void *) font, «Учебное пособие по GLUT ---_ ------ _ @ 3D Tech»); * / glFlush (); glutSwapBuffers (); anguloCuboX + = 0,1f; anguloCuboY + = 0,1f; англоэсфера + = 0,2f; } void init () {glClearColor (0, 0, 0, 0); glEnable (GL_DEPTH_TEST); анчо = 500; альт = 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"); если (myfile.is_open ()) {s = 0; while (getline (myfile, line)) {if ((line [0]! = 'N') && (line [0]! = 'F')) {Aux = line; строка [0] = 48; строка [1] = 48; строка [2] = 48; строка [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 (); } else cout <1780) NP = 1700; cout <void idle () {display (); } void keyboard (беззнаковая клавиша char, int x, int y) {переключатель (клавиша) {case 'p': case 'P': hazPerspectiva = 1; изменить форму (анчо, альт); перерыв; case 'o': case 'O': hazPerspectiva = 0; изменить форму (анчо, альт); перерыв; case 27: // escape exit (0); перерыв; }} 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 = button; Pulbut = состояние; // mx = y; отображать(); } void ratmov (int x, int y) {если ((Boton == 0) & (Pulbut == 0)) {mx = y; мой = х; } если ((Boton == 2) & (Pulbut == 0)) {mtx = (y / 200) -1; mty = (x / 200) -1; } если ((Boton == 1) & (Pulbut == 0)) {mtz = - (y / 40) -5; } отображать(); } int main (int argc, char ** argv) {/ * glutAddMenuEntry () glutAddSubMenu () glutAttachMenu () glutCreateMenu () glutSetMenu () glutStrokeCharacter () пикселей glutStrokeLength () * / * пикселей из блока чтения () * / * буфер кадра glGetPixelMapfv () возвращает указанную карту пикселей glGetPixelMapuiv () возвращает указанную карту пикселей glGetPointerv () Возвращает адрес указанного указателя. * / Init (); ухмылка (); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (привязка, альт); glutCreateWindow ("Кубо 1"); в этом(); glutDisplayFunc (дисплей); glutReshapeFunc (изменить форму); glutIdleFunc (простаивает); glutMouseFunc (raton); glutMotionFunc (ратмов); glutKeyboardFunc (клавиатура); glutMainLoop (); возврат 0; }

Шаг 5:

Изображение
Изображение

на данный момент я должен остановиться! … но в следующей главе я обещаю вам, что я реализую это на моей raspberry pi 3 или моей наноплате jetson, уже установленной на каком-то дистанционно управляемом самолете, или на каком-то роботе-пауке для сканирования пещер.

Рекомендуемые: