通過kinect實現3d掃描建立打印模型(processing、skanect、ReconstructMe)

http://www.sigvc.org/bbs/thread-722-1-1.html


在本文中將詳細梳理使用Kinect進行3d掃描的過程,一共包含3種實現方法:processing編程實現、skanect軟件實現、ReconstructMe軟件實現。RecontructMe只能基於32位系統的驅動與kinect連接,而skanect與processing不論是32位還是64位都可以較好的兼容。

Comparison of ReconstructMe, KinectFusion and Skanect:



我們首先來看ReconstructMe:
ReconstructMe是基於32位系統的,但是在64位操作系統下仍舊使用32位的kinect驅動以及ReconstructMe。
ReconstructMe官方網址:http://reconstructme.net/
官網中針對不同的用戶,有免費版以及收費版兩種軟件,具體下載地址爲:http://reconstructme.net/projects/reconstructme-console/
下載完成以後,先不要安裝,在安裝ReconstructMe之前我們首先需要安裝Kinect的驅動,具體步驟如下:


  • 下載32位openni驅動包,下載地址:
Dropbox下載地址:
https://www.dropbox.com/s/n55mr8q1j0nzyru/Sensor%20Driver%20Package%
20×86%201.5.2.zip
堅果雲下載地址:
https://jianguoyun.com/c/pubfile/uGqA8e_Y18lRqUluPrFMdXnCzq3o0ko9_Eh_5yDu-3U
2.解壓驅動包,首先安裝OpenNI,再然後是SensorKinect,然後是SensorPrimesense。(在安裝之前,一定要把原來kinect的驅動卸載掉)
3.全部安裝完成以後,重啓
4.將你的Kinect連接上電腦,可以通過查看控制面板中的設備管理器,檢查你的電腦是否已 經識別Kinect.
8351452160_ed770105d7_z.jpg 
5.確認Kinect已經能和電腦通信之後,安裝下載好的ReconstructMe,安裝完以後運行目錄中的Start ReconstructMe Scan OpenNI.bat,注意不是ReconstructMe.exe。然後根據提示進行操作即可
附圖:
8350394557_08557b1c61_z.jpg 


接下來是通過skanect進行3d掃描

Skanect官方網址:http://skanect.manctl.com
下載地址:http://manctl.com/products.html(頁面中含有詳細的安裝步驟,但是一些鏈接已經失效,在後面的安裝步驟中含有其他下載鏈接)
詳細安裝步驟:

  • 下載skanect
  • 下載kinect驅動包:
Dropbox下載地址:
https://www.dropbox.com/s/734160v5imqyd5d/kinect%20driver%20package%20for%2064bit.zip
堅果雲下載地址:
https://jianguoyun.com/c/pubfile/sm_vNwOtndapU8ya3p46l6BXj-ujPkDmnt7JrTnhjoc
3. 下載完驅動包以後,首先安裝OpenNI,然後是NITE,再然後是sensor(此文件也就是Primesense),最後是SensorKinect.
4.把kinect通過USB連接到電腦,檢查控制面板中的設備管理器,判斷是否已經連接成功。
5.安裝skanect並運行skanect.exe
(備註
1. 若基於32位操作系統,當使用skanect應下載之前ReconstructMe的所需的驅動,並附加NITE(具體安裝順序如上所示):
dropbox下載:https://www.dropbox.com/s/alvz98xzchlhlqj/NITE-Win32-1.5.2.21-Dev.zip
堅果雲下載:
https://jianguoyun.com/c/pubfile/pw4suN5cAEsSIyTDyMGLaoAIw3Dfc6baECBR_1udBkY
2. 若運行skanect時,提示未查找到openni.dll則需根據你安裝的目錄找到openni.dll並複製到system32中!)
附圖:
8350401023_e880009539_z.jpg 


最後一種方法是通過processing編程實現
,對於使用過Processing或者java的人比較適用。雖然自己之前沒有接觸過java,但還是嘗試了一下,歡迎大家一起折騰,具體步驟:

  • 首先還是需要安裝Kinect的驅動(本人親測爲安裝64位的驅動,如果你使用的操作系統是32位的還需安裝NITE,因爲後面調用processing庫是需使用到)
  • Processing的simple-openni庫下載及安裝:
http://code.google.com/p/simple-openni/downloads/list
(木有接觸過processing的,百度一下即可找到,下載該軟件並根據官網指示瞭解如何安裝庫文件)
3.Coding!
Processing代碼:

普通瀏覽複製代碼
  1. import processing.opengl.*;
  2. import SimpleOpenNI.*;
  3. import kinectOrbit.*;
  4. KinectOrbit myOrbit;
  5. SimpleOpenNI kinect;
  6. String turnTableAngle = "0";
  7. ArrayList scanPoints = new ArrayList(); // PointCloud
  8. ArrayList scanColors = new ArrayList(); // Object Colors
  9. ArrayList objectPoints = new ArrayList(); // PointCloud
  10. ArrayList objectColors = new ArrayList(); // Object Colors
  11. float baseHeight =   ; // Height of the Model's base//1
  12. float modelWidth =    ;//2
  13. float modelHeight =    ;//3
  14. PVector axis = new PVector(0, baseHeight,   );//4
  15. int scanLines = 200;
  16. int scanRes = 1;
  17. float[] shotNumber = new float[3];
  18. int currentShot = 0;
  19. public void setup()
  20. {
  21.   size(800600, OPENGL);
  22.   // Orbit
  23.   myOrbit = new KinectOrbit(this0"kinect");
  24.   myOrbit.drawCS(true);
  25.   myOrbit.drawGizmo(true);
  26.   myOrbit.setCSScale(  );//5
  27.   myOrbit.drawGround(true);
  28.   // Simple-openni
  29.   kinect = new SimpleOpenNI(this);
  30.   kinect.setMirror(false);
  31.   kinect.enableDepth();
  32.   kinect.enableRGB();
  33.   kinect.alternativeViewPointDepthToImage();
  34.   for (int i = 0; i < shotNumber.length; i++) 
  35.   {
  36.     shotNumber<i> = i * (2 * PI) / shotNumber.length;
  37.   }
  38. }
  39. public void draw() 
  40. {
  41.   kinect.update(); // Update Kinect data
  42.   background(0);
  43.   myOrbit.pushOrbit(this); // Start Orbiting
  44.   drawPointCloud(5);
  45.   updateObject(scanLines, scanRes);
  46.   if(currentShot>0&¤tShot<4)
  47.   {
  48.     scan();
  49.   }
  50.   drawObjects();
  51.   drawBoundingBox(); // Draw Box Around Scanned Objects
  52.   kinect.drawCamFrustum(); // Draw the Kinect cam
  53.   myOrbit.popOrbit(this); // Stop Orbiting
  54. }
  55. void drawPointCloud(int steps)
  56. {
  57.   // draw the 3D point depth map
  58.   int index;
  59.   PVector realWorldPoint;
  60.   stroke(255);
  61.   for (int y = 0; y < kinect.depthHeight(); y += steps)
  62.   {
  63.     for (int x = 0; x < kinect.depthWidth(); x += steps)
  64.     {
  65.       index = x + y * kinect.depthWidth();
  66.       realWorldPoint = kinect.depthMapRealWorld()[index];
  67.       stroke(150);
  68.       point(realWorldPoint.x, realWorldPoint.y, realWorldPoint.z);
  69.     }
  70.   }
  71. }
  72. void drawObjects()
  73. {
  74.   pushStyle();
  75.   strokeWeight(4);
  76.   for (int i = 1; i < objectPoints.size(); i++)
  77.   {
  78.     stroke(objectColors.get(i).x, objectColors.get(i).y, objectColors.get(i).z);
  79.     point(objectPoints.get(i).x, objectPoints.get(i).y, objectPoints.get(i).z + axis.z);
  80.   }
  81.   for (int i = 1; i < scanPoints.size(); i++)
  82.   {
  83.     stroke(scanColors.get(i).x, scanColors.get(i).y, scanColors.get(i).z);
  84.     point(scanPoints.get(i).x, scanPoints.get(i).y, scanPoints.get(i).z + axis.z);
  85.   }
  86.   popStyle();
  87. }
  88. void drawBoundingBox()
  89. {
  90.   stroke(25500);
  91.   line(axis.x, axis.y, axis.z, axis.x, axis.y + 100, axis.z);
  92.   noFill();
  93.   pushMatrix();
  94.   translate(axis.x, axis.x + baseHeight + modelHeight / 2, axis.z);
  95.   box(modelWidth, modelHeight, modelWidth);
  96.   popMatrix();
  97. }
  98. void scan()
  99. {
  100.   for (PVector v : scanPoints)
  101.   {
  102.     boolean newPoint = true;
  103.     for (PVector w : objectPoints)
  104.     {
  105.       if (v.dist(w) < 1)
  106.       newPoint = false;
  107.     }
  108.     if (newPoint)
  109.     {
  110.       objectPoints.add(v.get());
  111.       int index = scanPoints.indexOf(v);
  112.       objectColors.add(scanColors.get(index).get());
  113.     }
  114.   }
  115. }
  116. void updateObject(int scanWidth, int step)
  117. {
  118.   int index;
  119.   PVector realWorldPoint;
  120.   scanPoints.clear();
  121.   scanColors.clear();
  122.   float angle=(currentShot-1)*2*PI/3;
  123.   rotateY(angle);
  124.   line(0,0,100,0);//draw a line at the base of the bounding box to indicate the rotation
  125.   int xMin = (int) (kinect.depthWidth() / 2 - scanWidth / 2);
  126.   int xMax = (int) (kinect.depthWidth() / 2 + scanWidth / 2);
  127.   for (int y = 0; y < kinect.depthHeight(); y += step)
  128.   {
  129.     for (int x = xMin; x < xMax; x += step)
  130.     {
  131.       index = x + (y * kinect.depthWidth());
  132.       realWorldPoint = kinect.depthMapRealWorld()[index];
  133.       color pointCol = kinect.rgbImage().pixels[index];
  134.       if (realWorldPoint.y < modelHeight + baseHeight && realWorldPoint.y > baseHeight)
  135.       {
  136.         if (abs(realWorldPoint.x - axis.x) < modelWidth / 2)
  137.         { // Check x
  138.           if (realWorldPoint.z < axis.z + modelWidth / 2 && realWorldPoint.z > axis.z -modelWidth / 2)
  139.           { // Check z
  140.             PVector rotatedPoint;
  141.             realWorldPoint.z -= axis.z;
  142.             realWorldPoint.x -= axis.x;
  143.             rotatedPoint = vecRotY(realWorldPoint, angle);
  144.             scanPoints.add(rotatedPoint.get());
  145.             scanColors.add(new PVector(red(pointCol), green(pointCol), blue(pointCol)));
  146.           }
  147.         }
  148.       }
  149.     }
  150.   }
  151. }
  152. PVector vecRotY(PVector vecIn, float phi)
  153. {
  154.   // Rotate the vector around the y-axis
  155.   PVector rotatedVec = new PVector();
  156.   rotatedVec.x = vecIn.x * cos(phi) - vecIn.z * sin(phi);
  157.   rotatedVec.z = vecIn.x * sin(phi) + vecIn.z * cos(phi);
  158.   rotatedVec.y = vecIn.y;
  159.   return rotatedVec;
  160. }
  161. public void keyPressed() {
  162.   switch(key)
  163.   {
  164.     case 's':
  165.     currentShot++;
  166.     break;
  167.     case 'c'// Clear the object points
  168.     objectPoints.clear();
  169.     objectColors.clear();
  170.     currentshot=0;
  171.     break;
  172.     case 'e'// Export the object points
  173.     exportPly('0');
  174.     break;
  175.     case '+'// Increment the number of scanned lines
  176.     scanLines++;
  177.     println(scanLines);
  178.     break;
  179.     case '-'// Decrease the number of scanned lines
  180.     scanLines--;
  181.     println(scanLines);
  182.     break;
  183.   }
  184. }



代碼下載地址:
Dropbox下載:https://www.dropbox.com/s/90fttmvheag2k2r/scan.pde
堅果雲下載:https://jianguoyun.com/c/pubfile/GHAf-ZzTMjgr1KNNinHgpWf7QKdTmBu2Z-2SIU_YbE8
收工!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章