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驱动包,下载地址:
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.

5.确认Kinect已经能和电脑通信之后,安装下载好的ReconstructMe,安装完以后运行目录中的Start ReconstructMe Scan OpenNI.bat,注意不是ReconstructMe.exe。然后根据提示进行操作即可
附图:

接下来是通过skanect进行3d扫描 :
Skanect官方网址: http://skanect.manctl.com
下载地址: http://manctl.com/products.html (页面中含有详细的安装步骤,但是一些链接已经失效,在后面的安装步骤中含有其他下载链接)
详细安装步骤:
- 下载skanect
- 下载kinect驱动包:
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中!)
附图:

最后一种方法是通过processing编程实现 ,对于使用过Processing或者java的人比较适用。虽然自己之前没有接触过java,但还是尝试了一下,欢迎大家一起折腾,具体步骤:
- 首先还是需要安装Kinect的驱动(本人亲测为安装64位的驱动,如果你使用的操作系统是32位的还需安装NITE,因为后面调用processing库是需使用到)
- Processing的simple-openni库下载及安装:
(木有接触过processing的,百度一下即可找到,下载该软件并根据官网指示了解如何安装库文件)
3.Coding!
Processing代码:
普通浏览
复制代码
-
import processing.opengl.* ;
-
import SimpleOpenNI.* ;
-
import kinectOrbit.* ;
-
KinectOrbit myOrbit ;
-
SimpleOpenNI kinect ;
-
String turnTableAngle = "0" ;
-
ArrayList scanPoints = new ArrayList ( ) ; // PointCloud
-
ArrayList scanColors = new ArrayList ( ) ; // Object Colors
-
ArrayList objectPoints = new ArrayList ( ) ; // PointCloud
-
ArrayList objectColors = new ArrayList ( ) ; // Object Colors
-
float baseHeight = ; // Height of the Model's base//1
-
-
float modelWidth = ; //2
-
-
float modelHeight = ; //3
-
-
PVector axis = new PVector ( 0, baseHeight, ) ; //4
-
-
int scanLines = 200 ;
-
int scanRes = 1 ;
-
float [ ] shotNumber = new float [ 3 ] ;
-
int currentShot = 0 ;
-
-
public void setup ( )
-
{
-
size ( 800, 600, OPENGL ) ;
-
// Orbit
-
myOrbit = new KinectOrbit ( this, 0, "kinect" ) ;
-
myOrbit.drawCS ( true ) ;
-
myOrbit.drawGizmo ( true ) ;
-
myOrbit.setCSScale ( ) ; //5
-
-
myOrbit.drawGround ( true ) ;
-
// Simple-openni
-
kinect = new SimpleOpenNI ( this ) ;
-
kinect.setMirror ( false ) ;
-
kinect.enableDepth ( ) ;
-
kinect.enableRGB ( ) ;
-
kinect.alternativeViewPointDepthToImage ( ) ;
-
for ( int i = 0 ; i < shotNumber.length ; i++ )
-
{
-
shotNumber<i> = i * ( 2 * PI ) / shotNumber.length ;
-
}
-
}
-
-
public void draw ( )
-
{
-
kinect.update ( ) ; // Update Kinect data
-
background ( 0 ) ;
-
myOrbit.pushOrbit ( this ) ; // Start Orbiting
-
drawPointCloud ( 5 ) ;
-
updateObject (scanLines, scanRes ) ;
-
if (currentShot> 0&¤tShot< 4 )
-
{
-
scan ( ) ;
-
}
-
drawObjects ( ) ;
-
drawBoundingBox ( ) ; // Draw Box Around Scanned Objects
-
kinect.drawCamFrustum ( ) ; // Draw the Kinect cam
-
myOrbit.popOrbit ( this ) ; // Stop Orbiting
-
}
-
-
void drawPointCloud ( int steps )
-
{
-
// draw the 3D point depth map
-
int index ;
-
PVector realWorldPoint ;
-
stroke ( 255 ) ;
-
for ( int y = 0 ; y < kinect.depthHeight ( ) ; y + = steps )
-
{
-
for ( int x = 0 ; x < kinect.depthWidth ( ) ; x + = steps )
-
{
-
index = x + y * kinect.depthWidth ( ) ;
-
realWorldPoint = kinect.depthMapRealWorld ( ) [index ] ;
-
stroke ( 150 ) ;
-
point (realWorldPoint.x, realWorldPoint.y, realWorldPoint.z ) ;
-
}
-
}
-
}
-
-
void drawObjects ( )
-
{
-
pushStyle ( ) ;
-
strokeWeight ( 4 ) ;
-
for ( int i = 1 ; i < objectPoints.size ( ) ; i++ )
-
{
-
stroke (objectColors.get (i ).x, objectColors.get (i ).y, objectColors.get (i ).z ) ;
-
point (objectPoints.get (i ).x, objectPoints.get (i ).y, objectPoints.get (i ).z + axis.z ) ;
-
}
-
for ( int i = 1 ; i < scanPoints.size ( ) ; i++ )
-
{
-
stroke (scanColors.get (i ).x, scanColors.get (i ).y, scanColors.get (i ).z ) ;
-
point (scanPoints.get (i ).x, scanPoints.get (i ).y, scanPoints.get (i ).z + axis.z ) ;
-
}
-
popStyle ( ) ;
-
}
-
-
void drawBoundingBox ( )
-
{
-
stroke ( 255, 0, 0 ) ;
-
line (axis.x, axis.y, axis.z, axis.x, axis.y + 100, axis.z ) ;
-
noFill ( ) ;
-
pushMatrix ( ) ;
-
translate (axis.x, axis.x + baseHeight + modelHeight / 2, axis.z ) ;
-
box (modelWidth, modelHeight, modelWidth ) ;
-
popMatrix ( ) ;
-
}
-
-
void scan ( )
-
{
-
for (PVector v : scanPoints )
-
{
-
boolean newPoint = true ;
-
for (PVector w : objectPoints )
-
{
-
if (v.dist (w ) < 1 )
-
newPoint = false ;
-
}
-
if (newPoint )
-
{
-
objectPoints.add (v.get ( ) ) ;
-
int index = scanPoints.indexOf (v ) ;
-
objectColors.add (scanColors.get (index ).get ( ) ) ;
-
}
-
}
-
}
-
-
void updateObject ( int scanWidth, int step )
-
{
-
int index ;
-
PVector realWorldPoint ;
-
scanPoints.clear ( ) ;
-
scanColors.clear ( ) ;
-
float angle = (currentShot-1 )*2*PI/ 3 ;
-
rotateY (angle ) ;
-
line ( 0, 0, 100, 0 ) ; //draw a line at the base of the bounding box to indicate the rotation
-
int xMin = ( int ) (kinect.depthWidth ( ) / 2 - scanWidth / 2 ) ;
-
int xMax = ( int ) (kinect.depthWidth ( ) / 2 + scanWidth / 2 ) ;
-
for ( int y = 0 ; y < kinect.depthHeight ( ) ; y + = step )
-
{
-
for ( int x = xMin ; x < xMax ; x + = step )
-
{
-
index = x + (y * kinect.depthWidth ( ) ) ;
-
realWorldPoint = kinect.depthMapRealWorld ( ) [index ] ;
-
color pointCol = kinect.rgbImage ( ).pixels [index ] ;
-
if (realWorldPoint.y < modelHeight + baseHeight && realWorldPoint.y > baseHeight )
-
{
-
if ( abs (realWorldPoint.x - axis.x ) < modelWidth / 2 )
-
{ // Check x
-
if (realWorldPoint.z < axis.z + modelWidth / 2 && realWorldPoint.z > axis.z -modelWidth / 2 )
-
{ // Check z
-
PVector rotatedPoint ;
-
realWorldPoint.z - = axis.z ;
-
realWorldPoint.x - = axis.x ;
-
rotatedPoint = vecRotY (realWorldPoint, angle ) ;
-
scanPoints.add (rotatedPoint.get ( ) ) ;
-
scanColors.add ( new PVector (red (pointCol ), green (pointCol ), blue (pointCol ) ) ) ;
-
}
-
}
-
}
-
}
-
}
-
}
-
-
PVector vecRotY (PVector vecIn, float phi )
-
{
-
// Rotate the vector around the y-axis
-
PVector rotatedVec = new PVector ( ) ;
-
rotatedVec.x = vecIn.x * cos (phi ) - vecIn.z * sin (phi ) ;
-
rotatedVec.z = vecIn.x * sin (phi ) + vecIn.z * cos (phi ) ;
-
rotatedVec.y = vecIn.y ;
-
return rotatedVec ;
-
}
-
-
public void keyPressed ( ) {
-
switch (key )
-
{
-
case 's':
-
currentShot++ ;
-
break ;
-
case 'c': // Clear the object points
-
objectPoints.clear ( ) ;
-
objectColors.clear ( ) ;
-
currentshot = 0 ;
-
break ;
-
case 'e': // Export the object points
-
exportPly ( '0' ) ;
-
break ;
-
case '+': // Increment the number of scanned lines
-
scanLines++ ;
-
println (scanLines ) ;
-
break ;
-
case '-': // Decrease the number of scanned lines
-
scanLines-- ;
-
println (scanLines ) ;
-
break ;
-
}
-
}
代码下载地址:
Dropbox下载:https://www.dropbox.com/s/90fttmvheag2k2r/scan.pde
坚果云下载:https://jianguoyun.com/c/pubfile/GHAf-ZzTMjgr1KNNinHgpWf7QKdTmBu2Z-2SIU_YbE8
收工!