תוכן עניינים:

סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי: 5 שלבים
סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי: 5 שלבים

וִידֵאוֹ: סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי: 5 שלבים

וִידֵאוֹ: סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי: 5 שלבים
וִידֵאוֹ: סורק תלת ממדי דגם Sense 2024, נוֹבֶמבֶּר
Anonim
סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי
סורק תלת מימד בסיסי למיפוי תלת מימד דיגיטלי

בפרויקט זה, אתאר ואסביר את היסודות הבסיסיים של סריקה ושחזור תלת-ממד המיושמים בעיקר על סריקה של אובייקטים קטנים של מטוס למחצה, ואפשר להרחיב את פעולתם למערכות סריקה ושחזור שניתן להתקין במטוסים בשלט רחוק כדי להשיג דגם תלת מימד. מהמקומות שבהם המטוס שלוקח אותם טס

הרעיון הסופי הוא להשיג סריקה תלת מימדית של מקום או אזור כלשהו, החיצוניים או הפנימיים שלו, להשתמש בו כמפה דיגיטלית (כמו בסרט פרומאוס)

שלב 1:

תמונה
תמונה

הרעיון הוא להתקין את כל מערכת הסריקה התלת-ממדית על מטוס בשלט רחוק, על מנת להפוך את המפה הווירטואלית של כל אזור שעליו היא עפה בתלת-ממד דיגיטציה, אך לשם כך התחלנו מתחילת הפעולה של טריאנגולציית הלייזר השיטה של סריקה או שחזור תלת מימד על ידי טריאנגולציה בלייזר בעצם מורכב מהעברת קרן לייזר דרך פריזמה שיוצרת פס לייזר כדי להשיג פס לייזר שלם שיוקרן על אובייקט שייסרק, וברגע שהתקבלה הקרנת לייזר זו על פני השטח מהמקום לסריקה, יש לצלם את התמונה בעזרת מצלמה כלשהי ורצוי להכיר את הזווית שנוצרת ביחס לזווית ההקרנה של פס הלייזר הנפלט, שכן כל אחת מהתמונות הללו לוכדת את רצועות הלייזר המוקרנות. על פני השטח של האובייקט, הם יהיו מעובדים מראש כדי לחלץ את המאפיינים הממדיים של האובייקט שיש לסרוק, ופשוט לסרוק רצועה אחר רצועה מעל האובייקט כדי להשיג את פרופיל פני השטח שלו באותו קטע רוחבי של האובייקט, ולאחר מכן ללכוד הרצועה המוקרנת של החתך הבא של האובייקט, כדי להוסיף את כל הפסים המוקרנים יחדיו לפני כל חתכי האובטו נקבל סריקה תלת ממדית של פני השטח שלו

שלב 2:

תמונה
תמונה

מכיוון שזיהינו את המטרה שלנו, השלב הבא בידיעה שכדי להמריא עליך קודם כל להניח את הרגליים היטב על הקרקע, אז התחלנו על הקרקע עם אב טיפוס ניסיוני של סורק תלת מימד ליניארי, כדי לאמת את הפעולה הנכונה של הבסיסי. סורק תלת מימד וכפי שאתה יכול לראות בתמונה למעלה השתמשתי במחשב PC, OpenCV, Glut של OpenGL, מצלמת רשת, לייזר, מחולל לייזר (במקרה זה דרך מראה סיבובית) במערכת תזוזה לינארית אלקטרונית (עשויה מסילה ומערכת המופקת ממדפסת ישנה) מבסיס שעליו אני מניח את האובייקטים לסריקה, עץ ופלסטלינה וכפי שאתה יכול לראות בתמונה, במחשב: הצלחתי לייצר ולהציג עם גלוט מ- OpenGL שלשה- מודל ממדי משוכפל על סמך האובייקט האמיתי הסרוק (במקרה זה עכביש צעצוע)

כך שברור כי עקרון הפעולה הוא פונקציונלי, וכי בעזרת ההתאמות והתאמות שלו למערכת מעופפת הוא יוכל לסרוק ולשחזר מפה תלת מימדית של האזור בו הוא טס.

אבל מערכת זו תשמש רק להשגת מפות תלת מימד של המשטח החיצוני של המקומות עליה היא טסה ??? …

שלב 3:

תמונה
תמונה

מיפוי פנים המערות והתעלות (ממש כמו בסרט Prometeus) מערכת סריקה תלת מימדית זו משמשת גם לשחזור מודלים תלת מימדיים של פנים אובייקטים גדולים וחלולים כגון מערות, בניינים, מנהרות וכו 'עקרון הפעולה שלה הוא בדיוק אותו הדבר כפי שכבר תואר ואשר בעצם מורכב מהדברים הבאים:

  1. לצלם את התמונה של כל הקרנה של פס הלייזר על פני השטח שיש לסרוק
  2. לסנן ולהסיר צבע מהתמונה
  3. בינארי את הצבע עם סף תמונה דינאמי
  4. החלת גלאי קצה כדי לזהות את הפרופיל שצולם של כל חתך הקרנת לייזר
  5. ובאמצעות פילוח בחר את הגבול המתאים לייצוג תלת מימד של אותו חתך של האובייקט שיש לסרוק ולבנות מחדש על מפת התלת מימד הווירטואלית.
  6. אז השלבים האלה פשוט חוזרים על כל תמונה שצולמה בתת-משנה של פסי הלייזר שמוקרנים ברציפות על ידי כל תת-חלק בקטע משנה.
  7. שכבה אחר שכבה של הייצוג של חתכי הרוחב מתווספים ברצף עד לקבלת ענן נקודה שנוצר על ידי ייצוגים רבים של חתכים של האובייקט שיש למפות

שלב 4:

תמונה
תמונה

אחר כך אני מעביר את התוכניות לעיבוד תמונה של הקרנות רצועות הלייזר השטחיות. ושל שחזור תלת מימד וירטואלי של ייצוגים רוחביים אלה במודל המפה התלת ממדי המשוכלל:

עיבוד תמונה:

נ

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

char f = 0; שם char = {"0.jpg"}; int n = 0, s, x, y; CvScalar sp; קובץ *NuPu;

void Writepoints () {char bufferx [33], buffery [33]; itoa (x, bufferx, 10); itoa (y, buffery, 10); fprintf (NuPu, bufferx); fprintf (NuPu, "\ t"); fprintf (NuPu, buffery); 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; שם [0] = f; להתייחס <

IplImage* img0 = cvLoadImage ("00.jpg", 0); אם (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 {עבור (y = 1; yheight-2; y ++) {עבור (x = 1; xwidth-2; x ++) { sp = cvGet2D (img1, y, x); if (sp.val [0]> 50) {Writepoints (); n ++;}}}} מאגר צ'אר [33]; itoa (n, buffer, 10); fprintf (NuPu, "Fin:"); fprintf (NuPu, חיץ); fprintf (NuPu, "\ n"); fclose (NuPu);

cvWaitKey (0); //_execlp("calc.exe "," calc.exe ", argstr, NULL); cvDestroyAllWindows (); cvReleaseImage (& image); cvReleaseImage (& img); cvReleaseImage (& img0); cvReleaseImage (& img1); cvReleaseImage (& img2); החזר 0; }

שחזור תלת מימד:

#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) באמצעות מרחב שמות std; int s, Boton = 1, Pulbut = 1; צף mx = 0, my = 0, mtx = 0, mty = 0, mtz = -5.0; const int Avance = 1; קו מחרוזת, Aux; char Character = 'H'; קובץ *NuPu; int NP, h, w; לצוף G = 0, n = 0, cx [5000], cy [5000], x, y, ax, ay, az; int font = (int) GLUT_BITMAP_8_BY_13; תווית צ'ארטית סטטית [100]; חיץ חרוך [3]; GLfloat anguloCuboX = 0.0f; GLfloat anguloCuboY = 0.0f; GLfloat anguloEsfera = 0.0f; אנצ'ו גלינט = 500; אלט גלינט = 500; int hazPerspectiva = 0; עיצוב מחדש של חלל (רוחב int, גובה int) {glViewport (0, 0, רוחב, גובה); glMatrixMode (GL_PROJECTION); glLoadIdentity (); אם (hazPerspectiva) gluPerspective (23.0f, (GLfloat) רוחב/(GLfloat) גובה, 1.0f, 20.0f); אחרת glOrtho (-1, 1, -1, 1, -10, 10); glMatrixMode (GL_MODELVIEW); אנצ'ו = רוחב; alt=גובה; } void Kolorear (int K) {float Hip; x = (cx [s] -320)/480; y = (cy [s] -240)/640; ירך = sqrt (pow (x, 2)+pow (y, 2)); אם ((ירך> = 0) && (ירך =.07) && (ירך =.14) && (ירך =.21) && (ירך =.28) && (ירך =.35) && (ירך =.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 (); רוג'ו; 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); עבור (c = string; *c! = '\ 0'; c ++) {glutBitmapCharacter (פונט, *c);}} תצוגת חלל () {// 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_,; 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, "שלום טקסט"); glutBitmapCharacter (GLUT_BIT_BIT_BITM_);* / /*glColor3f (1. 0f, 1.0f, 1.0f); setOrthographicProjection (); glPushMatrix (); glLoadIdentity (); renderBitmapString (30, 15, (void *) גופן, "הדרכה GLUT ---_ ------ _@ 3D Tech"); */ glFlush (); glutSwapBuffers (); anguloCuboX+= 0.1f; anguloCuboY+= 0.1f; anguloEsfera+= 0.2f; } חלל init () {glClearColor (0, 0, 0, 0); glEnable (GL_DEPTH_TEST); אנצ'ו = 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"); אם (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 (); } מקלדת חלל (מפתח צ'אר לא חתום, int x, int y) {switch (מפתח) {case 'p': case 'P': hazPerspectiva = 1; צור מחדש (אנצ'ו, אלט); לשבור; מקרה 'o': מקרה 'O': hazPerspectiva = 0; צור מחדש (אנצ'ו, אלט); לשבור; מקרה 27: // יציאת בריחה (0); לשבור; }} void raton (כפתור int, int int, int x, int y) { / * GLUT_LEFT_BUTTON 0 GLUT_MIDDLE_BUTTON 1 GLUT_RIGHT_BUTTON 2 GLUT_DOWN 0 GLUT_UP 1 * / Boton = כפתור; Pulbut = מדינה; // mx = y; לְהַצִיג(); } void ratmov (int x, int y) {if ((Boton == 0) & (Pulbut == 0)) {mx = y; שלי = x; } אם ((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 ()* / /*glReadPixels () מסגרת מאגר glGetPixelMapfv () מחזירה את מפת הפיקסלים שצוין glGetPixelMapuiv () מחזירה את מפת הפיקסלים שצוין glGetPointerv () מחזירה את כתובת המצביע שצוין.*/ Init (); leer (); glutInit (& argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition (50, 50); glutInitWindowSize (אנצ'ו, אלטו); glutCreateWindow ("קובו 1"); init (); glutDisplayFunc (תצוגה); glutReshapeFunc (עיצוב מחדש); glutIdleFunc (סרק); glutMouseFunc (raton); glutMotionFunc (ratmov); glutKeyboardFunc (מקלדת); glutMainLoop (); החזר 0; }

שלב 5:

תמונה
תמונה

כרגע אני חייב לעצור! … אבל בפרק הבא אני מבטיח לך שאיישם אותו על פטל pi 3 שלי או על ננובארד ג'טסון שלי, שכבר מותקן על כמה מטוסים בשלט רחוק, או על רובוט עכביש לסרוק את פנים המערות

מוּמלָץ: