Оглавление:
Видео: Базовый 3D-сканер для цифровых 3D-карт: 5 шагов
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:49
В этом проекте я опишу и объясню основные основы 3D-сканирования и реконструкции, применяемые в первую очередь для сканирования небольших полуплоскостных объектов, и чьи действия могут быть расширены до систем сканирования и реконструкции, которые могут быть установлены на самолетах с дистанционным управлением для получения 3D модель. мест, где пролетает установленный ими самолет
Конечная идея - получить 3D-сканирование некоторого места или области, снаружи или внутри, чтобы использовать их в качестве цифровой карты (как в фильме Прометея).
Шаг 1:
Идея состоит в том, чтобы установить всю систему 3D-сканирования на дистанционно управляемой плоскости, чтобы оцифровать виртуальную карту любой области, над которой он летит, в 3D, но для этого мы начали с самого начала работы лазерной триангуляции. Сканирование или 3D-реконструкция с помощью лазерной триангуляции в основном состоит из прохождения лазерного луча через призму, которая генерирует лазерную полосу для получения всей лазерной полосы, которая будет проецироваться на сканируемый объект, и как только эта лазерная проекция будет получена на поверхность поверхность От места сканирования изображение должно быть захвачено камерой определенного типа и, желательно, зная угол, который образуется по отношению к углу проекции излучаемой лазерной полосы, поскольку каждое из этих изображений захватывает проецируемые лазерные полосы. На поверхности объекта они будут предварительно обработаны для извлечения размерных характеристик объекта, подлежащего сканированию, и просто сканировать полоску за полосой над объектом, чтобы получить профиль его поверхности в этом поперечном сегменте объекта, а затем зафиксировать проецируемая полоса следующего поперечного сечения объекта, чтобы сложить все проецируемые полосы вместе. Перед всеми поперечными сечениями объекта мы получаем трехмерное сканирование его поверхности
Шаг 2:
Поскольку мы определили нашу цель, следующий шаг, зная, что для взлета вы должны сначала твердо стоять на земле, поэтому мы начали работу на земле с экспериментального прототипа линейного 3D-сканера, чтобы проверить правильность работы основного 3D-сканер, и, как вы можете видеть на изображении выше, я использовал ПК, OpenCV, Glut of OpenGL, веб-камеру, лазер, лазерный генератор фермы (в данном случае через вращающееся зеркало), электронную систему линейного смещения (сделанную с помощью рельса). и система, извлеченная из старого принтера) с базы, на которую я помещаю объекты для сканирования, дерево и пластилин, и, как вы можете видеть на фотографии, на компьютере: мне удалось сгенерировать и отобразить с помощью Glut из OpenGL трехкратный размерная модель воспроизводится на основе отсканированного реального объекта (в данном случае игрушечного паука)
Таким образом, более чем очевидно, что принцип действия является функциональным, и что с его соответствующими настройками и адаптациями к летающей системе он сможет сканировать и воспроизводить трехмерную карту области, в которой он летит.
Но эта система будет служить только для получения трехмерных карт внешней поверхности мест, над которыми она пролетает ???…
Шаг 3:
картирование интерьера пещер и каналов (как в фильме «Прометей»). Эта система трехмерного сканирования также служит для реконструкции трехмерных моделей интерьера больших и полых объектов, таких как пещеры, здания, туннели и т. д., принцип ее работы заключается в следующем. точно так же, как уже было описано, и в основном состоит из следующего:
- сделайте снимок каждой проекции лазерной полосы на сканируемой поверхности
- фильтровать и удалять цвет с изображения
- преобразовать цвет в двоичную форму с помощью порога динамического изображения
- применить детектор края для распознавания захваченного профиля каждого поперечного сечения лазерной проекции
- и с помощью сегментации выберите подходящую границу для трехмерного представления этого поперечного сечения объекта, который нужно сканировать и реконструировать на виртуальной трехмерной карте.
- затем эти шаги просто повторяются для каждой фотографии, сделанной в виде лазерных полос, непрерывно проецируемых каждым подразделом в подразделе.
слой за слоем представления поперечных сечений добавляются последовательно до тех пор, пока не будет получено облако точек, образованное множеством представлений поперечных сечений объекта, подлежащего отображению
Шаг 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, уже установленной на каком-то дистанционно управляемом самолете, или на каком-то роботе-пауке для сканирования пещер.
Рекомендуемые:
Magic Hercules - Драйвер для цифровых светодиодов: 10 шагов
Magic Hercules - драйвер для цифровых светодиодов: Краткий обзор: модуль Magic Hercules - это преобразователь между хорошо известным и простым SPI в протокол NZR. Входы модуля имеют допуск +3,3 В, поэтому вы можете безопасно подключать любые микроконтроллеры, работающие от напряжения +3,3 В. Использование
Внешний литий-ионный аккумулятор для цифровых фотоаппаратов: 12 шагов (с изображениями)
Внешняя литий-ионная батарея для цифровых фотоаппаратов. Внешняя батарея полезна для съемки дополнительных фотографий и видео, поскольку ее емкость выше, чем у литий-полимерных батарей, которые поставляются с камерой. Они также могут заменить труднодоступные батареи в ваших резервных камерах, которые вы иногда можете использовать
Автоматическая кормушка для домашних животных с использованием старых цифровых часов: 10 шагов (с изображениями)
Автоматическая кормушка для домашних животных с использованием старых цифровых часов: Здравствуйте, в этой инструкции я покажу вам, как я сделал автоматическую кормушку для домашних животных, используя старые цифровые часы. Я также вложил видео о том, как я сделал эту кормушку. Это руководство будет участвовать в конкурсе печатных плат, и в качестве одолжения я хотел бы
Подушечки для игр, чувствительные к давлению (для цифровых игровых площадок и не только): 11 шагов (с изображениями)
Игровые подушечки, чувствительные к давлению (для цифровых игровых площадок и др.): Это руководство, которое покажет вам, как сделать подушечки, чувствительные к давлению, которые можно использовать для создания цифровых игрушек или игр. Его можно использовать как крупномасштабный резистор, чувствительный к силе, и, хотя он и забавен, его можно использовать для более серьезных проектов
Модуль батарей для цифровых фотоаппаратов DXG 305V - больше нет изношенных батарей !: 5 шагов
DXG 305V Аккумуляторный модуль для цифровой камеры - больше нет изношенных аккумуляторов! Эта цифровая камера у меня была уже несколько лет, и я обнаружил, что она мгновенно высасывает энергию из аккумуляторных батарей! Я наконец придумал способ модифицировать его, чтобы сэкономить батареи на те времена, когда мне действительно понадобились