Ubuntu下安裝配置OpenNI, OpenCV


費了老大半天工夫,總算在Linux下把OpenNI和OPenCV配置好了,網上對Linux下OpenNI的配置方法講的很少,而尋找使用OpenNI進行開發的方法更是像大海撈針……連手冊里都只字不提,翻了好的資料才算搞定。閑話少說,總結在這和大家一起分享。

一、OPenNI篇

1.軟件下載:

(1)OpenNI:http://www.openni.org/Downloads/OpenNIModules.aspx

  選擇“OpenNI Binaries”->“Unstable”->“...for ubuntu...”,點擊“Download”。

  下載完成后解壓,cd進入解壓后的路徑:$ ./install.sh(不記得要不要加sudo了,試一試吧)

(2)SensorKinect:

  命令:$git clone https://github.com/avin2/SensorKinect.git

  如果沒有安裝git,則sudo apt-get install之~

  過程比較慢,結束后會在當前路徑出現一個文件夾SensorKinect,cd進SensorKinect/Platform/Linux/CreateRedist,之后$ ./RedistMaker,這時在上層目錄Linux下出現Redist文件夾。此時網上說進該目錄$ ./install.sh,但實際上還要進一層目錄才有instal.sh文件。但是貌似執行這個需要root權限,我不知道怎么弄,$sudo su后也不行,最后發現還是Redist文件夾里面有一個Final文件夾,里面有一個壓縮包Sensor-Bin-Linux-x86-v5.0.5.1.tar.bz2,我索性把它拷出來,解壓縮后進去 (…/SensorKinect/Platform/Linux/CreateRedist/Sensor-Bin-Linux-x86-v5.0.5.1/),在里面$./install.sh,竟然就可以了。順便說一下,可能在這些過程中輸入$ ./install.sh 會提示沒有命令之類的,可以在install.sh文件上右擊->屬性->權限,選中“允許以程序執行文件”,就可以了。

  這時可以到在OpenNI-Bin-XXXX/Samples/Bin/x86-Release目錄中測試:$ ./NiViewer,有可能提示沒有什么庫之類的,試着裝一下:$sudo apt-get install libusb-1.0-0-dev freeglut3-dev,之后應該就可以運行了,就可以看到期待已久的畫面嘍。如果這時候提示說Failed to set USB interface!或者Open failed: The network connection has been closed!,在命令行里運行:

  $sudo rmmod gspca_kinect
  這是因為Ubuntu可能自帶了kinect驅動gspca_kinect,二者有沖突。貌似每次重啟電腦后都需要執行一下這句才行。如果不想這么麻煩,可以把這個驅動加入系統黑名單:

  $sudo gedit /etc/modprobe.d/blacklist.conf

  在打開的文件底部加入一行:

  blacklist gspca_kinect

  這部分主要參考了https://github.com/avin2/SensorKinect里面講的可能和實際不太一樣,嘗試着來吧。

(2)NITE:http://www.openni.org/Downloads/OpenNIModules.aspx

  選擇“OpenNI Compliant Middleware Binaries”->“Unstable”->“...Ubuntu...”,下載就好了。

  下載完成后解壓,進入目錄$ ./install.sh即可。

2.開發環境配置

  我選用的是eclipse-cdt進行開發,網上僅有的可憐的一點資料講的是用codeblocks進行開發,其實都是差不多的。這里以eclipse為例介紹一下吧。

  新建一個空的或helloworld工程,如kinectOpenNI,在左側的project exploer中右擊kinectOpenNI,點properties,在對話框中選擇C/C++ Build->settings->GCC C++ Compiler(如果用C寫就選GCC C Compiler)->Directories,在右側Include paths(-l)里點右邊綠色加號,添加兩個路徑/usr/include/ni和/usr/include/nite,然后再選擇GCC C++ Linker->Libraries,在Libraries (-l)中添加OpenNI,glut,XnVNite,注意XnVNite可能有版本號,要到你的/usr/lib目錄下看一看,有個文件叫libXnVNite_XXXX.so之類的,我的是libXnVNite_1_5_0.so,所以我填的是XnVNite_1_5_0,反正就是隨機應變吧,填不對的話它會報錯說找不到庫。由於這幾個庫都是在系統/usr/lib/目錄下的,因此不用添加Library search path (-L)。

  到此為止你的工程應該可以編譯了。試試這段樣例:(注意該一下里面xml文件的路徑。樣例是直接從安裝包里找到的。當然,記得連上你的Kinect)

View Code
/****************************************************************************
* *
* OpenNI 1.x Alpha *
* Copyright (C) 2011 PrimeSense Ltd. *
* *
* This file is part of OpenNI. *
* *
* OpenNI is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* OpenNI is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with OpenNI. If not, see <
http://www.gnu.org/licenses/>. *
* *
***************************************************************************
*/
//---------------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------------
#include <XnOS.h>
#if (XN_PLATFORM == XN_PLATFORM_MACOSX)
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <math.h>

#include <XnCppWrapper.h>
using namespace xn;

//---------------------------------------------------------------------------
// Defines
//---------------------------------------------------------------------------
#define SAMPLE_XML_PATH "/home/iotuyrfviloh/Softwares/OpenNI-Bin-Dev-Linux-x86-v1.4.0.2/Samples/Config/SamplesConfig.xml"

#define GL_WIN_SIZE_X 1280
#define GL_WIN_SIZE_Y 1024

#define DISPLAY_MODE_OVERLAY 1
#define DISPLAY_MODE_DEPTH 2
#define DISPLAY_MODE_IMAGE 3
#define DEFAULT_DISPLAY_MODE DISPLAY_MODE_DEPTH

#define MAX_DEPTH 10000

//---------------------------------------------------------------------------
// Globals
//---------------------------------------------------------------------------
float g_pDepthHist[MAX_DEPTH];
XnRGB24Pixel* g_pTexMap = NULL;
unsigned int g_nTexMapX = 0;
unsigned int g_nTexMapY = 0;

unsigned int g_nViewState = DEFAULT_DISPLAY_MODE;

Context g_context;
ScriptNode g_scriptNode;
DepthGenerator g_depth;
ImageGenerator g_image;
DepthMetaData g_depthMD;
ImageMetaData g_imageMD;

//---------------------------------------------------------------------------
// Code
//---------------------------------------------------------------------------

void glutIdle (void)
{
// Display the frame
glutPostRedisplay();
}

void glutDisplay (void)
{
XnStatus rc = XN_STATUS_OK;

// Read a new frame
rc = g_context.WaitAnyUpdateAll();
if (rc != XN_STATUS_OK)
{
printf("Read failed: %s\n", xnGetStatusString(rc));
return;
}

g_depth.GetMetaData(g_depthMD);
g_image.GetMetaData(g_imageMD);

const XnDepthPixel* pDepth = g_depthMD.Data();
const XnUInt8* pImage = g_imageMD.Data();

unsigned int nImageScale = GL_WIN_SIZE_X / g_depthMD.FullXRes();

// Copied from SimpleViewer
// Clear the OpenGL buffers
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Setup the OpenGL viewpoint
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, GL_WIN_SIZE_X, GL_WIN_SIZE_Y, 0, -1.0, 1.0);

// Calculate the accumulative histogram (the yellow display...)
xnOSMemSet(g_pDepthHist, 0, MAX_DEPTH*sizeof(float));

unsigned int nNumberOfPoints = 0;
for (XnUInt y = 0; y < g_depthMD.YRes(); ++y)
{
for (XnUInt x = 0; x < g_depthMD.XRes(); ++x, ++pDepth)
{
if (*pDepth != 0)
{
g_pDepthHist[*pDepth]++;
nNumberOfPoints++;
}
}
}
for (int nIndex=1; nIndex<MAX_DEPTH; nIndex++)
{
g_pDepthHist[nIndex] += g_pDepthHist[nIndex-1];
}
if (nNumberOfPoints)
{
for (int nIndex=1; nIndex<MAX_DEPTH; nIndex++)
{
g_pDepthHist[nIndex] = (unsigned int)(256 * (1.0f - (g_pDepthHist[nIndex] / nNumberOfPoints)));
}
}

xnOSMemSet(g_pTexMap, 0, g_nTexMapX*g_nTexMapY*sizeof(XnRGB24Pixel));

// check if we need to draw image frame to texture
if (g_nViewState == DISPLAY_MODE_OVERLAY ||
g_nViewState == DISPLAY_MODE_IMAGE)
{
const XnRGB24Pixel* pImageRow = g_imageMD.RGB24Data();
XnRGB24Pixel* pTexRow = g_pTexMap + g_imageMD.YOffset() * g_nTexMapX;

for (XnUInt y = 0; y < g_imageMD.YRes(); ++y)
{
const XnRGB24Pixel* pImage = pImageRow;
XnRGB24Pixel* pTex = pTexRow + g_imageMD.XOffset();

for (XnUInt x = 0; x < g_imageMD.XRes(); ++x, ++pImage, ++pTex)
{
*pTex = *pImage;
}

pImageRow += g_imageMD.XRes();
pTexRow += g_nTexMapX;
}
}

// check if we need to draw depth frame to texture
if (g_nViewState == DISPLAY_MODE_OVERLAY ||
g_nViewState == DISPLAY_MODE_DEPTH)
{
const XnDepthPixel* pDepthRow = g_depthMD.Data();
XnRGB24Pixel* pTexRow = g_pTexMap + g_depthMD.YOffset() * g_nTexMapX;

for (XnUInt y = 0; y < g_depthMD.YRes(); ++y)
{
const XnDepthPixel* pDepth = pDepthRow;
XnRGB24Pixel* pTex = pTexRow + g_depthMD.XOffset();

for (XnUInt x = 0; x < g_depthMD.XRes(); ++x, ++pDepth, ++pTex)
{
if (*pDepth != 0)
{
int nHistValue = g_pDepthHist[*pDepth];
pTex->nRed = nHistValue;
pTex->nGreen = nHistValue;
pTex->nBlue = 0;
}
}

pDepthRow += g_depthMD.XRes();
pTexRow += g_nTexMapX;
}
}

// Create the OpenGL texture map
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_nTexMapX, g_nTexMapY, 0, GL_RGB, GL_UNSIGNED_BYTE, g_pTexMap);

// Display the OpenGL texture map
glColor4f(1,1,1,1);

glBegin(GL_QUADS);

int nXRes = g_depthMD.FullXRes();
int nYRes = g_depthMD.FullYRes();

// upper left
glTexCoord2f(0, 0);
glVertex2f(0, 0);
// upper right
glTexCoord2f((float)nXRes/(float)g_nTexMapX, 0);
glVertex2f(GL_WIN_SIZE_X, 0);
// bottom right
glTexCoord2f((float)nXRes/(float)g_nTexMapX, (float)nYRes/(float)g_nTexMapY);
glVertex2f(GL_WIN_SIZE_X, GL_WIN_SIZE_Y);
// bottom left
glTexCoord2f(0, (float)nYRes/(float)g_nTexMapY);
glVertex2f(0, GL_WIN_SIZE_Y);

glEnd();

// Swap the OpenGL display buffers
glutSwapBuffers();
}

void glutKeyboard (unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit (1);
case '1':
g_nViewState = DISPLAY_MODE_OVERLAY;
g_depth.GetAlternativeViewPointCap().SetViewPoint(g_image);
break;
case '2':
g_nViewState = DISPLAY_MODE_DEPTH;
g_depth.GetAlternativeViewPointCap().ResetViewPoint();
break;
case '3':
g_nViewState = DISPLAY_MODE_IMAGE;
g_depth.GetAlternativeViewPointCap().ResetViewPoint();
break;
case 'm':
g_context.SetGlobalMirror(!g_context.GetGlobalMirror());
break;
}
}

int main(int argc, char* argv[])
{
XnStatus rc;

EnumerationErrors errors;
rc = g_context.InitFromXmlFile(SAMPLE_XML_PATH, g_scriptNode, &errors);
if (rc == XN_STATUS_NO_NODE_PRESENT)
{
XnChar strError[1024];
errors.ToString(strError, 1024);
printf("%s\n", strError);
return (rc);
}
else if (rc != XN_STATUS_OK)
{
printf("Open failed: %s\n", xnGetStatusString(rc));
return (rc);
}

rc = g_context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_depth);
if (rc != XN_STATUS_OK)
{
printf("No depth node exists! Check your XML.");
return 1;
}

rc = g_context.FindExistingNode(XN_NODE_TYPE_IMAGE, g_image);
if (rc != XN_STATUS_OK)
{
printf("No image node exists! Check your XML.");
return 1;
}

g_depth.GetMetaData(g_depthMD);
g_image.GetMetaData(g_imageMD);

// Hybrid mode isn't supported in this sample
if (g_imageMD.FullXRes() != g_depthMD.FullXRes() || g_imageMD.FullYRes() != g_depthMD.FullYRes())
{
printf ("The device depth and image resolution must be equal!\n");
return 1;
}

// RGB is the only image format supported.
if (g_imageMD.PixelFormat() != XN_PIXEL_FORMAT_RGB24)
{
printf("The device image format must be RGB24\n");
return 1;
}

// Texture map init
g_nTexMapX = (((unsigned short)(g_depthMD.FullXRes()-1) / 512) + 1) * 512;
g_nTexMapY = (((unsigned short)(g_depthMD.FullYRes()-1) / 512) + 1) * 512;
g_pTexMap = (XnRGB24Pixel*)malloc(g_nTexMapX * g_nTexMapY * sizeof(XnRGB24Pixel));

// OpenGL init
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(GL_WIN_SIZE_X, GL_WIN_SIZE_Y);
glutCreateWindow ("OpenNI Simple Viewer");
glutFullScreen();
glutSetCursor(GLUT_CURSOR_NONE);

glutKeyboardFunc(glutKeyboard);
glutDisplayFunc(glutDisplay);
glutIdleFunc(glutIdle);

glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

// Per frame code is in glutDisplay
glutMainLoop();

return 0;
}

二、OpenCV篇

  雖然已經可以用OpenGL了,但是OpenCV還是很不錯的,也配一下吧。

1.軟件下載

(1)裝一下這些吧:

apt-get install build-essential
apt-get install cmake cmake-gui
apt-get install pkg-config
apt-get install libgtk2.0-0 libgtk2.0-dev
apt-get install libpng12-0 libpng12-dev libpng++-dev libpng3
apt-get install libpnglite-dev libpngwriter0-dev libpngwriter0c2
apt-get install zlib1g-dbg zlib1g zlib1g-dev
apt-get install libjasper-dev libjasper-runtime libjasper1
apt-get install pngtools libtiff4-dev libtiff4 libtiffxx0c2 libtiff-tools
apt-get install libjpeg8 libjpeg8-dev libjpeg8-dbg libjpeg-prog
apt-get install ffmpeg libavcodec-dev libavcodec53 libavformat53 libavformat-dev libswscale-dev
apt-get install libgstreamer0.10-0-dbg libgstreamer0.10-0 libgstreamer0.10-dev
apt-get install libxine1-ffmpeg libxine-dev libxine1-bin
apt-get install libunicap2 libunicap2-dev
apt-get install libdc1394-22-dev libdc1394-22 libdc1394-utils
apt-get install swig
apt-get install libv4l-0 libv4l-dev
apt-get install python-numpy
apt-get install libpython2.7 python-dev python2.7-dev

有些可能你用不到,但是貌似build-essential,cmake,pkg-config都是必須的,其他的都不確定啦,保險起見都裝一下吧~另外有些軟件包可能已經過時或者版本發生變化,在安裝時如果提示找不到軟件包,最好更新一下版本號。附帶說明一下,如果要使用opencv做視頻開發,一定要把ffmpeg相關到軟件包安裝好,不然可能讀取不了視頻。

(2)下載最新版本OpenCV:http://sourceforge.net/projects/opencvlibrary/files/

  解壓,生成目錄如OpenCV-2.3.1,在它旁邊新建一個目錄,如OpenCV-2.3.1-build。這時打開cmake-gui圖形界面,應該可以在主菜單的“編程”項中找到。在上面的Source和Build欄中分別填上OpenCV-2.3.1和OpenCV-2.3.1-build的完整路徑。點下面的Config,如果窗口內容變紅,再點一次,直到不紅為止,這時點Generate即可。命令行cd進OpenCV-2.3.1-build,$make然后$sudo make install,此時OpenCV應該就被安裝在/usr/local/下面了。

2.建立工程

  使用eclipse建立新工程,如testOpenCV在左側的project exploer中右擊testOpenCV,點properties,在對話框中選擇C/C++ Build->settings->GCC C++ Compiler(如果用C寫就選GCC C Compiler)->Directories,在右側Include paths(-l)里點右邊綠色加號,添加路徑/usr/local/include/opencv,然后再選擇GCC C++ Linker->Libraries,在Libraries (-l)中添加opencv_core,opencv_highgui,如果需要其他庫也依次添加。庫的路徑是/usr/local/lib,因此要添加Library search path (-L):/usr/local/lib。

  也附帶講一下codeblocks下的工程配置:

  在codeblocks中建立工程后,點擊主菜單project-->build options,點上左上角的工程名,然后進入右側的Linker settings選項卡,可以在左側Link libraries中添加鏈接庫名稱(與eclipse中一樣,opencv_core等),也可以更簡單地在右側Other linker options中填寫 `pkg-config opencv --libs`(注意兩邊的 ` 號,在鍵盤上!/1 鍵左側);然后進入Search directories選項卡,在Compiler子選項卡中添加路徑 /usr/local/include/opencv。如果上一步你用的是第一種方法,這里你可能還需要在Linker子選項卡中添加庫路徑:/usr/local/lib。

  還要給系統添加一下環境變量。我是試了好幾種方法,也不知道最后是那個生效了:

  命令行里依次輸入(就是新建個文件,添上一行/usr/local/lib,也可以用gedit來做):

sudo vi /etc/ld.so.conf.d/opencv.conf
G
o
/usr/local/lib
<Esc>
:wq!

類似地,打開文件/etc/bash.bashrc,在最后添加兩行:

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH

然后在命令行輸入:

sudo ldconfig -v
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

重啟,然后應該就可以編譯運行了,如果配置不好的話可能會報錯說沒有libopencv_core.so文件之類的。如果還是不行,就在看看其他帖子吧,不同人情況不一yang,我是深深地感受到了。
  好了,看看能不能運行吧:

圖像讀取測試程序:

#include <iostream>
#include "cv.h"
#include <cxcore.h>
#include <highgui.h>
using namespace std;

int main() {
IplImage *img = cvLoadImage("a.jpg");
cvNamedWindow("Image:",1);
cvShowImage("Image:",img);
cvWaitKey();
cvDestroyWindow("Image:");
cvReleaseImage(&img);
return 0;
}

視頻讀取示例程序:

#include "cv.h"
#include
<cxcore.h>
#include
<highgui.h>

int main() {
cvNamedWindow(
"顯示視頻", CV_WINDOW_AUTOSIZE );
CvCapture
* capture = cvCreateFileCapture("aa.MPG");
IplImage
* frame;
while(1)
{
frame
= cvQueryFrame( capture );
if( !frame ) break;
cvShowImage(
"顯示視頻", frame );
char c = cvWaitKey(33);
if( c == 27 ) break;
}
cvReleaseCapture(
&capture );
cvDestroyWindow(
"顯示視頻");
return 0;
}

 

其中圖片路徑在與工程中該cpp文件一致,或者取個絕對路徑吧。
如果一切安好,那就恭喜啦。

  有了OpenNI和OpenCV,就安心開發你有意思的Kinect應用吧~


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com