DAFTAR PUSTAKA Angel, E., & Shreiner, D. (2012). Interactive Computer Graphics. A Top-Down Approach with Shader-Based OpenGL (6th ed.). England: Pearson Education, Inc. Blinn, J. F., & Newell, M. E. (1976). Texture and Reflection in Computer Generated Images. Communications of the ACM, 19, 542-547. Bradski, G., & Kaehler, A. (2008). Learning OpenCV. Computer Vision with the OpenCV Library (1st ed.). Sebastopol: O'Reilly Media, Inc. Connolly, T., & Begg, C. (2010). Database Systems. A Practical Approach to Design, Implementation, and Management (5th ed.). Boston: Pearson Education, Inc. Deitel, P. J., & Deitel, H. M. (2010). C How to Program (6th ed.). Boston: Pearson Education, Inc. EdrawSoft. (2004). Standard Flowchart Symbols and Their Usage. Retrieved Januari 12, 2014, from http://www.edrawsoft.com/flowchart-symbols.php Fairhurst, M. C. (1988). Computer Vision for Robotic Systems. An Introduction. Hertfordshire: Prentice Hall, Inc. Fussell, D. (2010). Texture Mapping. 1-22. Gonzalez, R. C., & Woods, R. E. (2008). Digital Image Processing (3rd ed.). New Jersey: Prentice Hall. Jiang, J., Ma, J., & Jin, Y. (2012). Computer Music Controller Based on Hand Gestures Recognition Through Web-cam. EE368 - Digital Image Processing, Stanford University. Licsár, A., & Szirányi, T. (2004). Dynamic Training of Hand Gesture Recognition System. 17th International Conference on Pattern Recognition, 4, 1-4. Park, H. (2010). A Method for Controlling Mouse Movement using a Real-Time Camera. 1-10. Ramadijanti, N., Setiawardhana, & Alhaqqi, R. M. (2013). Tracking Jari dengan Haar Cascade dan Filter Kalman pada Virtual Keyboard. Inovtek, 3, 1-9. Rich, E., & Knight, K. (1991). Artificial Intelligence (2nd ed.). New York: McGrawHill, Inc.
177
178 Satzinger, J. W., Jackson, R. B., & Burd, S. D. (2009). System Analysis and Design in a Changing World (5th ed.). Boston: Course Technology. Shneiderman, B., & Plaisant, C. (2010). Designing the User Interface: Strategies for Effective Human-Computer Interaction (5th ed.). Boston: Pearson Education, Inc. Sommerville, I. (2011). Software Engineering (9th ed.). Boston: Pearson Education, Inc. Sugiyono. (2009). Metode Penelitian Kuantitatif, Kualitatif dan R&D. Bandung: Alfabeta. Turban, E., & Frenzel, L. E. (1992). Expert Systems and Applied Artificial Intelligence. New York: Macmillan, Inc.
LAMPIRAN Kuesioner Sebelum Implementasi Berikut ini merupakan kuesioner yang disebarkan untuk mengetahui kebutuhan pengguna: Yth. Bapak/Ibu/Sdr Ditempat, Dalam rangka penelitian untuk penyusunan tugas akhir (skripsi), bersama ini kami mohon bantuan Bapak/Ibu/Sdr bersedia menjadi responden dalam penelitian yang kami lakukan. Angket ini ditujukan untuk diisi oleh Bapak/Ibu/Sdr dengan menjawab seluruh pertanyaan yang telah disediakan. Kami mengharapkan jawaban yang Bapak/Ibu/Sdr berikan nantinya adalah jawaban obyektif agar diperoleh hasil maksimal. Penelitian ini dilakukan dengan tujuan membuat aplikasi yang dapat mempermudah proses presentasi ataupun mengajar. Dengan bantuan kamera (webcam) pada aplikasi ini, pengguna dapat mengoperasikan computer dengan bantuan pergerakan tangan, seperti menggerakkan mouse, mouse click, next/prev slide presentasi. Adapun judul penelitian ini adalah “Aplikasi Remote Cursor Menggunakan Web Camera dengan Library OpenCV dan OpenGL”. Atas perhatian serta partisipasi yang diberikan, kami ucapkan terima kasih. 1.
Apakah pekerjaan Anda saat ini? * (boleh diisi lebih dari satu)
☐Dosen/Pengajar ☐Mahasiswa ☐Karyawan ☐Lainnya, ________________________________ 2.
Apakah Anda mengalami kesulitan saat mengajar/membawakan presentasi dengan fasilitas yang telah disediakan oleh Bina Nusantara? * (fasilitas tidak melingkupi suara/speaker/kualitas proyektor)
☐Ya ☐Tidak (lanjut ke pertanyaan 4)
179
180 3.
Jika Ya, apa saja kesulitan yang Anda hadapi dan bagaimana Anda mengatasi kesulitan tersebut? * Solusi Kesulitan
(jika belum memiliki solusi, silahkan dikosongkan)
4.
Apakah Anda memiliki alat bantu dalam mengajar/membawakan presentasi? * (alat bantu yang dimaksudkan, seperti: mouse wireless, pointer, dll)
☐Ya ☐Tidak (lanjut ke pertanyaan 6) 5.
Jika Ya, alat bantu apa yang Anda gunakan dan apakah alat bantu tersebut sangat mempengaruhi proses mengajar/membawakan presentasi? * (alat bantu boleh diisi lebih dari satu)
6.
Apakah Anda tertarik apabila terdapat fasilitas mengajar/membawakan presentasi hanya dengan menggunakan tangan Anda sebagai alat bantu? * (misalnya, untuk menggerakan pointer, mouse click, memilih menu, next/prev slide, dll)
☐Ya ☐Tidak (selesai)
181 7.
Jika Ya, menurut Anda manakah bentuk tangan yang cocok untuk menunjukkan angka 1? *
☐ 8.
☐
☐
Jika Ya, menurut Anda manakah bentuk tangan yang cocok untuk menunjukkan angka 2? *
☐ 9.
☐
☐
Jika Ya, menurut Anda manakah bentuk tangan yang cocok untuk menunjukkan angka 3? *
☐
☐
☐
10. Jika Ya, menurut Anda manakah bentuk tangan yang cocok untuk menunjukkan angka 4? *
☐
☐
☐
182 No. 11 s/d 15 tidak boleh ada yang diisi sama! 11. Berdasarkan bentuk tangan yang Anda pilih, jari yang menunjukan angka berapakah yang paling cocok untuk menggerakan mouse?* a. Angka 1 b. Angka 2 c. Angka 3 d. Angka 4 e. Angka 5 12. Berdasarkan bentuk tangan yang Anda pilih, jari yang menunjukan angka berapakah yang paling cocok untuk melakukan event click dan next slide? * a. Angka 1 b. Angka 2 c. Angka 3 d. Angka 4 e. Angka 5 13. Berdasarkan bentuk tangan yang Anda pilih, jari yang menunjukan angka berapakah yang paling cocok untuk melakukan event double click? a. Angka 1 b. Angka 2 c. Angka 3 d. Angka 4 e. Angka 5 14. Berdasarkan bentuk tangan yang Anda pilih, jari yang menunjukan angka berapakah yang paling cocok untuk menjalankan slide show pada power point? a. Angka 1 b. Angka 2 c. Angka 3 d. Angka 4 e. Angka 5
183 15. Berdasarkan bentuk tangan yang Anda pilih, jari yang menunjukan angka berapakah yang paling cocok untuk melakukan event prev slide? a. Angka 1 b. Angka 2 c. Angka 3 d. Angka 4 e. Angka 5 16. Menurut Anda, fitur presentasi apakah yang dibutuhkan dalam mendukung proses presentasi, selain fitur slide show, next slide, dan prev slide?
184 Kuesioner Setelah Implementasi (Evaluasi) Berikut ini merupakan kuesioner yang disebarkan untuk mendapatkan data evaluasi user: 1.
Apakah aplikasi ini mudah untuk digunakan? * a. Sangat Mudah b. Mudah c. Cukup Mudah d. Sangat Sulit
2.
Bagaimana keakuratan aplikasi ini dalam menangkap instruksi yang diberikan? * a. Sangat Akurat b. Akurat c. Cukup Akurat d. Sangat Tidak Akurat
3.
Apakah aplikasi ini membantu Anda dalam proses presentasi? * a. Sangat Membantu b. Membantu c. Cukup Membantu d. Sangat Tidak Membantu
4.
Apakah help yang ada dapat membantu Anda dalam menggunakan aplikasi ini?* a. Sangat Membantu b. Membantu c. Cukup Membantu d. Sangat Tidak Membantu
5.
Apakah ada kritik dan saran untuk aplikasi ini?
185 Wawancara Berikut hasil wawancara dengan narasumber Bapak Indra Dwi Rianto, S.Si, S.Kom, M.TI sebagai Operational Support Section Head di Software Laboratory Center Universitas Bina Nusantara dan Ibu Lusiana Citra Dewi, S.Kom, M.M sebagai Manager Software Laboratory Center kampus Alam Sutra Universitas Bina Nusantara: 1. Apakah aplikasi Linda mudah dalam digunakan? Berikan pendapat Anda sebagai user/dosen maupun sebagai implementator? Bapak Indra: Jika dilihat dari sisi dosen maka aplikasi ini mudah digunakan sebab tidak memerlukan alat seperti mouse dan keyboard untuk mengganti-ganti slide, cukup dengan menggunakan tangan serta web camera. Jika dilihat dari sisi implementator, menurut saya akan ada gangguan namun seandainya gangguan konfigurasi awal tersebut dapat diatasi semisal dengan mendistibusikan secara umum cara pemakaiannya sehingga dapat mempermudah pengguna. Ibu Lusiana: Jika dilihat dari sisi dosen, yang berlatar belakang TI dengan mengetahui posisi yang tepat dalam penggunaan masih tergolong gampang dalam pemakaian, namun perlu diperbanyak sampel data agar posisi tersebut dapat juga disesuaikan dengan dosen-dosen yang sudah lanjut usia. Sependapat dengan Indra, jika menggunakan aplikasi ini tidak perlu menggunakan alat bantu lainnya jadi cukup menggunakan tangan saja sudah dapat membantu proses mengajar. Jika dari sisi implementator, jika dikembangkan lebih lagi dapat mempunyai prospek yang baik sehingga dapat digunakan pada ruang teori maupun praktikum. Dapat juga menggantikan peran wireless pointer yang sekarang ini relatif mahal harganya, cukup menggunakan kamera yang resolusi minimal VGA tanpa harus beresolusi tinggi. Sehingga dari sisi investasi dan operasional harusnya baik. Saran saja untuk implementasinya harus dipermudah lagi untuk pengaturannya. 2. Saran dan kritik anda mengenai aplikasi ini secara mendetail dari sisi user ataupun implementator-nya? Bapak Indra: Secara umum implementasi siap namun masih ada kendala, dari segi biaya proyek ini merupakan investasi awal yang mudah dan murah jika diimplementasikan. Namun kendala terbesarnya, aplikasi yang belum terlalu umum pengaturannya ini hanya sebatas developer yang mengerti cara pengaturannya. Jadi kekurangan yang perlu diiatasi agar dapat mudah dalam implementasinya bagi pengguna maupun pengelola fasilitasnya. Dari fungsi, jika
186 diperluas lagi dapat digunakan juga untuk merekam proses yang sedang berjalan/ajar-mengajar, gesture tertentu dapat digunakan juga sebagai pengendali komputer (stop merekam) sehingga saat distribusi tidak hanya punya 1 fungi untuk control slide namun banyak fasilitas lainnya seperti video pengajaran. Ibu Lusiana: Dilihat dari segi interface-nya tidak ada masalah, simpel dan fitur kalibrasinya mudah. Namun saat pengaturan di Option-advance bagian thresholdnya tidak ada penjelasan dan kalibrasinya pun kurang penjelasan. Saat testing, pendeteksian objek tangan sudah optimal namun perlu diperhatikan mengenai cahaya proyektor saat menyala, karena pengaturannya akan berbeda lagi. Sarannya mungkin dapat dibantu dari suara sebagai pengontrol jadi tidak hanya menggunakan pola tangan(gambaran saja). Jika dari sisi user, user memang mempunyai banyak kemauan secara ide memang menarik. 3. Menurut anda apakah prospek kedepannya dapat dipakai? Bapak Indra: Bisa saja digunakan, ide yang menarik untuk diimplementasikan, hanya saja kekurangan pada pengaturan awal. Ibu Lusiana: Bisa digunakan, bukan hanya itu namun juga dapat dijual. Kantor, hotel yang punya kegiatan seminar mereka juga membutuhkan aplikasi semacam itu dibandingkan membeli laser pointer yang dapat hilang alatnya (baik connector ataupun remote), hal yang kecil namun butuh dana besar.
Jakarta, 28 Januari 2014 Mengetahui,
(Indra Dwi Rianto, S.Si, S.Kom, M.TI)
(Lusiana Citra Dewi, S.Kom, M.M)
187 Kode Aplikasi Linda (Potongan) 1. Fungsi pendeteksian tangan void detectHand() { image = new Mat(img); for(int i=0;i
rows;i++) { for(int j=0;jcols;j++) { for(int c=0;c<3;c++) image->at(i,j)[c] = saturate_cast((float)(option_2[1])*(image>at(i,j)[c])+option_2[2]); } } cvtColor(*image, edit,CV_RGB2GRAY); hand_cascade.detectMultiScale( edit, hand, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, cvSize(30, 30), cvSize(150, 150)); for(size_t i = 0; i < hand.size(); i++) { handX = hand[i].x + hand[i].width/2; // set pointer x -- rumus handY = hand[i].y + hand[i].height/2; // set pointer y -- rumus Point center(handX,handY); centerPointX = ((float)((scaleX[0]+(float)(VIEWPORT_WIDTHscaleX[1]))/2)+ (float)((scaleX[3]+(float)(VIEWPORT_WIDTHscaleX[2]))/2))/2; //center -- rumus centerPointY = ((float)((scaleY[0]+(float)(VIEWPORT_HEIGHTscaleY[3]))/2)+(float)((scaleY[1]+(float)(VIEWPORT_HEIG HT-scaleY[2]))/2))/2; //center -- rumus Point center2(centerPointX,centerPointY); if(handX<=centerPointX) //rumus { if(handY<=centerPointY) idxScale = 0; else idxScale = 3; } else { if(handY<=centerPointY) idxScale = 1;
188 else idxScale = 2; } disX = ((GetSystemMetrics(SM_CXSCREEN)VIEWPORT_WIDTH)/2); // rumus disY = ((GetSystemMetrics(SM_CYSCREEN)VIEWPORT_HEIGHT)/2); // rumus handX1 = (double)((double)(((float)GetSystemMetrics(SM_CXSCREEN) /VIEWPORT_WIDTH)*(handX+scaleX[idxScale]))-disX); handY1 = (double)((double)(((float)GetSystemMetrics(SM_CYSCREEN) /VIEWPORT_HEIGHT)*(handY+scaleY[idxScale]))-disY);
roi = cvRect(handX-hand[i].width/2, handYhand[i].height/2, hand[i].width, hand[i].height); cvResetImageROI( img ); cvSetImageROI( img, roi); cropped = cvCreateImage( cvSize(roi.width,roi.height), img->depth, img>nChannels ); cvCopy( img, cropped ); cvResetImageROI( img ); ellipse(*image, center, Size(hand[i].width/2, hand[i].height/2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0); image2 = edit(hand[i]); n++; new_image = new Mat(cropped); cvtColor(*new_image,*new_image,CV_RGB2GRAY); threshold_output = new Mat(new_image->size(), new_image->type()); threshold(*new_image, *threshold_output,option_2[0], 255, THRESH_BINARY_INV ); handX1 = (GetSystemMetrics(SM_CXSCREEN) * center.x) / 600; handY1 = (GetSystemMetrics(SM_CYSCREEN) * center.y) / 600; makeContours(threshold_output, handX1, handY1); getFingerNumber(threshold_output); } }
189 void detect() { frameCount++; currentTime = glutGet(GLUT_ELAPSED_TIME); timeInterval = currentTime - previousTime; if(timeInterval > 500) { detectHand(); previousTime = currentTime; frameCount = 0; } }
2. Fungsi event handler void mouse() { INPUT zero = {INPUT_MOUSE, 0}; INPUT in = zero; int i = option_1[c-1]; if(i==1) { //single click in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN; SendInput(1, &in, sizeof in); in = zero; in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP; SendInput(1, &in, sizeof in); } else if (i==2) { //double click in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN; SendInput(1, &in, sizeof in); in = zero; in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP; SendInput(1, &in, sizeof in); in = zero; in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN; SendInput(1, &in, sizeof in); in = zero; in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP;
190 SendInput(1, &in, sizeof in); } b1=12; } void controlPowerPoint() { hwnd = GetForegroundWindow(); GetWindowTextA(hwnd,title,sizeof(title)); int i = option_1[c-1]; if(strstr(title,"PowerPoint")) { if(i==4) { //slide show SetForegroundWindow(hwnd); keybd_event(VK_F5, 0, 0, 0); } else if (i==5) { //prev slide SetForegroundWindow(hwnd); keybd_event(VK_LEFT, 0, 0, 0); } else if (i == 11) { SetForegroundWindow(hwnd); keybd_event(VK_ESCAPE, 0, 0, 0); } b1=12; } }
3. Fungsi menghitung contur tangan void initVectors(){ hullI=vector>(contours.size()); hullP=vector>(contours.size()); defects=vector> (contours.size()); } void analyzeContours(){ bRect_height=bRect.height; bRect_width=bRect.width; } float distanceP2P(Point a, Point b){ return sqrt(fabs((double)(((a.x-b.x)*(a.x-b.x)) + ((a.y-b.y)*(a.y-b.y)))));
191 } void removeRedundantFingerTips(){ for(int i=0;ihighestFreq){ frequentNr=fingerNumbers[i-1]; highestFreq=thisNumberFreq; } thisNumberFreq=0; } thisNumberFreq++; } if(thisNumberFreq>highestFreq){ frequentNr=fingerNumbers[fingerNumbers.size()1]; } mostFrequentFingerNumber=frequentNr; } void addFingerNumberToVector(){ fingerNumbers.push_back(fingerTips.size()); } void getFingerNumber(Mat* m){ removeRedundantFingerTips(); if(bRect.height > m->rows/2 && nrNoFinger>12){ numberColor=Scalar(0,200,0); addFingerNumberToVector(); if(frameNumber>12){ nrNoFinger=0; frameNumber=0; computeFingerNumber();
192 numbers2Display.push_back(mostFrequentFingerNumber); fingerNumbers.clear(); }else{ frameNumber++; } }else{ nrNoFinger++; numberColor=Scalar(200,200,200); } } float getAngle(Point s, Point f, Point e){ l1 = distanceP2P(f,s); l2 = distanceP2P(f,e); dot1 = (s.x-f.x)*(e.x-f.x) + (s.y-f.y)*(e.y-f.y); angle = acos(dot1/(l1*l2)); angle = angle*180/PI; return angle; } void removeRedundantEndPoints(vector newDefects, Mat* m){ tolerance=bRect_width/6; for(int i=0;ipenyebab error ptStart= new Point (contours[cIdx][startidx] ); endidx=newDefects[i][1]; ptEnd= new Point (contours[cIdx][endidx] ); startidx2=newDefects[j][0]; ptStart2= new Point (contours[cIdx][startidx2] ); endidx2=newDefects[j][1]; ptEnd2= new Point (contours[cIdx][endidx2] ); if(distanceP2P(*ptStart,*ptEnd2) < tolerance ){ contours[cIdx][startidx]=*ptEnd2; break; }if(distanceP2P(*ptEnd,*ptStart2) < tolerance ){ contours[cIdx][startidx2]=*ptEnd; } } } }
193 void eleminateDefects(Mat* m){ vector newDefects; tolerance = bRect_height/5; angleTol=95; int startidx, endidx, faridx; d=defects[cIdx].begin(); while( d!=defects[cIdx].end() ) { v=(*d); startidx=v[0]; ptStart = new Point (contours[cIdx][startidx] ); endidx=v[1]; ptEnd = new Point (contours[cIdx][endidx] ); faridx=v[2]; ptFar = new Point (contours[cIdx][faridx] ); if(distanceP2P(*ptStart, *ptFar) > tolerance && distanceP2P(*ptEnd, *ptFar) > tolerance && getAngle(*ptStart, *ptFar, *ptEnd ) < angleTol ){ if( ptEnd->y > (bRect.y + bRect.height bRect.height/4 ) ){ }else if( ptStart->y > (bRect.y + bRect.height -bRect.height/4 ) ){ }else { newDefects.push_back(v); } } d++; } nrOfDefects=newDefects.size(); defects[cIdx].swap(newDefects); removeRedundantEndPoints(defects[cIdx], m);//-> jdi ngebreak } void checkForOneFinger(Mat* m){ yTol=bRect.height/6; highestP.y=m->rows; d1=contours[cIdx].begin(); while( d1!=contours[cIdx].end() ) { Point v=(*d1); if(v.y
194 n2++; } d1++; }if(n2==0){ fingerTips.push_back(highestP); } } void drawFingerTips(Mat* m){ k=0; for(int i=0;i
195 int findBiggestContour(vector > contours){ indexOfBiggestContour = -1; sizeOfBiggestContour = 0; for (int i = 0; i < contours.size(); i++){ if(contours[i].size() > sizeOfBiggestContour){ sizeOfBiggestContour = contours[i].size(); indexOfBiggestContour = i; } } return indexOfBiggestContour; } void myDrawContours(Mat* m){ m->copyTo(aBw1); drawContours(aBw1,hullP,cIdx,cv::Scalar(200,0,0),1, 8, vector(), 0, Point()); rectangle(aBw1,bRect.tl(),bRect.br(),Scalar(0,0,200) ,1,8,0); d=defects[cIdx].begin(); for(int i=0;i<3;i++) channels.push_back(aBw1); result = new Mat(aBw1.size(), aBw1.type()); merge(channels,*result); drawContours(*result,hullP,cIdx,cv::Scalar(0,0,250), 10, 8, vector(), 0, Point()); while( d!=defects[cIdx].end() ) { v=(*d); startidx=v[0]; ptStart = new Point(contours[cIdx][startidx] ); endidx=v[1]; ptEnd = new Point(contours[cIdx][endidx] ); faridx=v[2]; ptFar = new Point(contours[cIdx][faridx] ); depth = v[3] / 256; circle( *result, *ptFar, 2, Scalar(0,205,0), 1 ); d++; } } void makeContours(Mat *m, int handX, int handY){ printf("%d,,,,,%d\n",handX,handY); pyrUp(*m,*m); m->copyTo(aBw); findContours(aBw,contours,CV_RETR_EXTERNAL,CV_CHAIN_ APPROX_NONE);
196 initVectors(); cIdx=findBiggestContour(contours); if(cIdx!=-1){ bRect=boundingRect(Mat(contours[cIdx]));
convexHull(Mat(contours[cIdx]),hullP[cIdx],false,tru e); convexHull(Mat(contours[cIdx]),hullI[cIdx],false,fal se); approxPolyDP( Mat(hullP[cIdx]), hullP[cIdx], 18, true ); printf("a: %d\n",contours[cIdx].size()); if(contours[cIdx].size()>3 ){ convexityDefects(contours[cIdx],hullI[cIdx],defects[ cIdx]); eleminateDefects(m); } c=getFingerTips(m); if(b1 ==0 && option_1[c-1]==3) { glutWarpPointer(handX, handY); mouse(); } else if(b1==0 && (option_1[c-1]==1||option_1[c1]==2)) { mouse(); } else if(b1==0 && (option_1[c-1]==4||option_1[c1]==5 ||option_1[c-1]==11 )) { controlPowerPoint(); } } }
197 XML yang Digunakan pada Aplikasi (Potongan) <size> 30 30 <stages> <_> <_> <_> <_> 0 7 28 4 -1. <_> 0 9 28 2 2. 0 -2.1621789783239365e-003 0.8576400279998779 -0.9588099718093872 <_> <_> <_> 0 5 4 13 -1. <_> 2 5 2 13 2. 0 -2.4858219549059868e-003 0.9218298792839050 -0.8868970274925232 <stage_threshold>-0.0369801484048367 <parent>-1 -1 … … <stage_threshold>0.0835630297660828 <parent>27 -1
198 Isi File yang Digunakan pada Aplikasi 1. Struktur file untuk menyimpan titik koordinat ketika selesai calibration
2. Struktur file untuk menyimpan pengaturan options advanced
3. Struktur file untuk menyimpan pengaturan options basic
199 Timeline Penelitian