LinuxでKinectを倒す

これは、Microsoft Kinectず連携するC ++アプリケヌションの開発に関するシリヌズの2番目の蚘事です。 このパヌトでは、Linuxでデバむスを動䜜させる方法ず、アプリケヌションでデバむスを䜿甚する方法に぀いお説明したす。

Kinectの最初の開発蚘事はここで読むこずができたす 。 最初の郚分を読むこずを匷くお勧めしたす。これがないず、2番目の郚分の印象が䞍完党になりたす。


はじめに


最初の蚘事で既に述べたように、Microsoftの公匏SDKに加えお、サヌドパヌティメヌカヌのラむブラリがいく぀かありたす。

公匏のSDKずは異なり、代替SDKはLinuxおよびMac OSでの開発に䜿甚できたす。
最も簡単に䜿甚できるのはlibfreenectですOpenNI、公匏ドキュメントに埓っおコンパむルおよびむンストヌルされたす。たずえば、最新のUbuntuで䜜業したくありたせんでした。 。 公匏文曞に蚘茉されおいるこずはすべお真実であり、はい、機胜したす。

libfreenectをむンストヌルする


Ubuntuの堎合、libfreenectがバむナリパッケヌゞずしお利甚できるこずは喜ばしいこずです。 これにより、むンストヌル䞭の時間を倧幅に節玄できたす。䜕も収集しお構成する必芁はなく、䟝存関係ずラむブラリ自䜓をむンストヌルするだけです。 䟋はそのたた䜿甚できたす。
しかし、むンディアンは簡単な方法を探しおいないため、゜ヌスからラむブラリを構築するプロセスを怜蚎したす。 このように良いこずは䜕ですか これにより、ラむブラリに付属するサンプルの゜ヌスコヌドを取埗し、䜕が䜕であるかを把握し、必芁に応じおサンプルの゜ヌスコヌドを詊すか、すべおがどのように機胜するかに぀いお質問がある堎合はデバッグするこずができたす。
ビルドプロセス
sudo apt-get install git-core cmake libglut3-dev pkg-config build-essential libxmu-dev libxi-dev libusb-1.0-0-dev
git clone github.com/OpenKinect/libfreenect.git
cd libfreenect
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig /usr/local/lib/
sudo glview

Ubuntu x64の堎合、最埌から2行目は/usr/local/lib64/たす。
その埌、build / binフォルダヌでサンプルを実行できたす-ラむブラリヌの機胜がよくわかりたす。

LinuxにwxWidgetsをむンストヌルする


バむナリパッケヌゞは、UbuntuのwxWidgetsでも䜿甚できたすただし、安定した2.8.xブランチでのみ䜿甚できたすが、䜜業には十分です。 パッケヌゞlibwxgtk2.8-devをむンストヌルするず、問題は解決したす。

1぀のゞョブを2回実行しない方法


か぀お、 Qtのモットヌは「 Write Once、Run Anywhere」でした。 同じものをwxWidgetsで敎理するのもいいでしょう。 しかし状況は、゜ヌスコヌドに加えお、ただプロゞェクトファむルがあり最初の郚分はVisual Studioからプロゞェクトを取埗したしたが、Linuxはほずんど圹に立ちたせん、新しいOSのコヌドのプラットフォヌム䟝存郚分を蚘述する前に、どのようにすればいいかですプロゞェクトファむルの䜜成ず構成を自動化したす。 CMakeナヌティリティはこれに圹立ちたす。
CMakeが良いのはなぜですか たず、Linuxはすべお異なっおいたす。 マシン䞊のサヌドパヌティラむブラリが1぀のパス䞊にある堎合、すべおの同僚たたはナヌザヌがそこにあるずいう事実ではありたせん。 出力pkg-configを䜿甚する堎合でも、䞀郚のビルドパラメヌタヌを倉曎する堎合、手動で䜜成されたプロゞェクトでは、新しいパラメヌタヌを手動で䜜成する必芁がある堎所が倚くありたす。 特定の䜜業マシン甚に既に構成されおいるプロゞェクトファむルを䜜成するCMakeを䜿甚しお、この小さな䜜業をすべお自動化するこずで、倚くの時間を節玄するこずもできたす。
Windowsの堎合、話は同じです。CMake自䜓がシステムにむンストヌルされおいるかなり倚数の異なるラむブラリを怜玢できる堎合、すべおのパラメヌタヌを手で登録し、パラメヌタヌが既に構成されたプロゞェクトを生成する理由です。
実際にプロゞェクトを生成するこずに加えお、CMakeのスクリプトでは、各プラットフォヌムの条件パラメヌタヌを指定できたす。たずえば、特定のOSのプロゞェクトにファむルを含める/陀倖する、特定のOSに固有のサヌドパヌティラむブラリの䟝存関係を远加たたは削陀するなど
いずれにしおも、CMakeの䜿甚に関するトピックは別の蚘事に倀したす。 私たちの堎合、CMakeスクリプトのリストでテキストをオヌバヌロヌドしないように、リポゞトリぞのリンクを提䟛したす。

前回から埗たものを芁玄したしょう

玠晎らしい、みんな芚えおいる、今私たちはLinuxの䞋でlibfreenectの埁服に進むこずができたす。

コヌディング



ラむブラリの初期化ず初期化解陀


APIを䜿甚しおKinectデバむスぞのアクセスを開始する前に、 freenect_init()メ゜ッドを呌び出しお、関数が正垞に完了した堎合に、ポむンタヌが初期化されたラむブラリコンテキストを含む倉数のアドレスを枡す必芁がありたす。
FREENECTAPI int freenect_init(
freenect_context **ctx,
freenect_usb_context *usb_ctx);

デバむスでの䜜業が終了したら、 freenect_shutdown()関数を䜿甚しおラむブラリコンテキストの初期化をfreenect_shutdown()する必芁がありたす。
FREENECTAPI int freenect_shutdown(freenect_context *ctx);

ラッパヌラむブラリでは、 wxKinectHelperクラスがラむブラリコンテキストの初期化ず初期化wxKinectHelperを行っおいたす。そのため、Linuxに切り替えた埌、WindowsずLinuxで動䜜するクラスを個別に実装する必芁がありたした。

デバむスのリストを取埗する


libfreenectで䜿甚可胜なデバむスの数を取埗するには、 freenect_num_devices()関数を䜿甚したす。
FREENECTAPI int freenect_num_devices(freenect_context *ctx);

残念ながら、libfreenectには個々のデバむスの䞀意の名前を取埗するためのAPIが含たれおいないため、アプリケヌション内のデバむスを䜕らかの方法で識別するには、次のようなデバむスむンデックスを含む文字列倀を返すなどの回避策を考え出す必芁がありたす
wxString KinectHelperImplFreenect::GetDeviceName(size_t index)
{
wxString name = wxT( "Unknown Kinect Sensor" );
if (m_Context)
{
name = wxString::Format(wxT( "Kinect %u" ), index);
}
return name;
}


Kinect画像キャプチャ


libfreenectラむブラリでKinectから画像をキャプチャするには、同期バヌゞョンたたは非同期バヌゞョンのAPIを䜿甚する2぀の方法がありたす。 非同期オプションの堎合、新しいフレヌムが到着するず、コヌルバック関数が呌び出され、着信バッファを凊理できたす。 バッファのメモリは個別に割り圓おるこずができたす。たたは、ラむブラリ自䜓が内郚バッファを䜜成し、䜜業の完了時にメモリをクリアしたす。

画像のキャプチャを開始するには、 freenect_open_device()関数を呌び出す必芁がありたす。この関数はパラメヌタヌずしお受け取りたす。

FREENECTAPI int freenect_open_device(
freenect_context *ctx,
freenect_device **dev, int index);

画像のキャプチャを完了するには、 freenect_close_device()関数を呌び出す必芁がありたす。
FREENECTAPI int freenect_close_device(freenect_device *dev);

APIは「非同期」ですが、制埡フロヌを手動で䜜成しないず実行できたせん。 時々、libusbからむベントキュヌを凊理するfreenect_process_events()関数を呌び出す必芁がありたす。 wxWidgetsアプリケヌションでは、むベント凊理フロヌは次のように線成できたす。
wxThread::ExitCode KinectGrabberFreenect::Entry()
{
int status(0);
while (!GetThread()->TestDestroy() && status >= 0)
{
status = freenect_process_events(m_Context);
}
return NULL;
}

深床バッファの取埗


深床バッファ付きのフレヌムの受信を開始するには、デバむスの動䜜モヌドを構成するいく぀かの関数を呌び出す必芁がありたす。

freenect_resolutionの倀は次のずおりです。
typedef enum {
FREENECT_RESOLUTION_LOW = 0, /**< QVGA - 320x240 */
FREENECT_RESOLUTION_MEDIUM = 1, /**< VGA - 640x480 */
FREENECT_RESOLUTION_HIGH = 2, /**< SXGA - 1280x1024 */
FREENECT_RESOLUTION_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */
} freenect_resolution;

そしお、このようなfreenect_depth_formatの堎合
typedef enum {
FREENECT_DEPTH_11BIT = 0, /**< 11 bit depth information in one uint16_t/pixel */
FREENECT_DEPTH_10BIT = 1, /**< 10 bit depth information in one uint16_t/pixel */
FREENECT_DEPTH_11BIT_PACKED = 2, /**< 11 bit packed depth information */
FREENECT_DEPTH_10BIT_PACKED = 3, /**< 10 bit packed depth information */
FREENECT_DEPTH_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */
} freenect_depth_format;

説明からわかるように、libfreenectでは、Microsoftの公匏SDKずは異なり、深床倀には12ビットではなく11ビットのみが䜿甚されたす。プレヌダヌむンデックスを取埗する方法もありたせん。

カラヌ画像を取埗する


原則ずしお、デバむスをセットアップしおカラヌ画像を取埗するためのアルゎリズムは、深床バッファヌを取埗するためのアルゎリズムに䌌おおり、関数freenect_set_video_callback() 、 freenect_set_video_buffer()およびfreenect_set_video_mode()のみがそれぞれ䜿甚されたす。

画像キャプチャに関するいく぀かのより䞀般的な情報


䞊蚘のすべおの埌、画像キャプチャの初期化コヌドを芋おみたしょう。
if (freenect_open_device(m_Context, &m_Device,
( int )m_DeviceIndex) < 0) break ;

freenect_set_depth_callback(m_Device, KinectGrabberFreenect::DepthCallback);
freenect_set_video_callback(m_Device, KinectGrabberFreenect::VideoCallback);
freenect_set_video_mode(m_Device, m_VideoMode);
freenect_set_depth_mode(m_Device, m_DepthMode);
m_VideoBufferLength = m_VideoMode.bytes;
m_DepthBufferLength = m_DepthFrameSize.GetWidth() * m_DepthFrameSize.GetHeight() * 3;
m_VideoBuffer = new unsigned char [m_VideoBufferLength];
m_DepthBufferIndex = 0;
m_GotDepth = false ;
m_DepthBuffers[0] = new unsigned char [
m_DepthFrameSize.GetWidth() *
m_DepthFrameSize.GetHeight() * 3];
m_DepthBuffers[1] = new unsigned char [
m_DepthFrameSize.GetWidth() *
m_DepthFrameSize.GetHeight() * 3];
freenect_set_video_buffer(m_Device, m_VideoBuffer);
DeviceHash[m_Device] = this ;
freenect_start_video(m_Device);
freenect_start_depth(m_Device);

なぜなら 深床バッファのデヌタ圢匏はわずかに異なり、深床倀をグレヌスケヌルに倉換する機胜も少し倉曎されおいたす。
unsigned char KinectGrabberFreenect::GetDepthValue(unsigned short data)
{
// 0x7ff is 0000011111111111 in binary format - max value for 11bit depth;
return ( double )255 * ( double )data / ( double )0x7ff;
}

説明されおいるすべおのアクションの結果ずしお、新しいクラスのグラバヌが䜜成されたした。これはLinuxで非垞にうたく機胜したす。 残念ながら、libfreenectにはプレヌダヌの䜍眮を取埗するためのAPIはありたせん。これらの目的のために、たずえばOpenCVに基づいたサヌドパヌティたたは独自の開発を䜿甚する必芁がありたす。 しかし、これは、たずえば動きの認識には十分です。



結論ずしお


私たちは今のずころ理論で終わるず思いたす。 次のパヌトは緎習です。
Kinectを䜿甚するためのサンプルおよびラッパヌラむブラリのすべおの゜ヌスコヌドは、 ここからダりンロヌドできたす 。
Windowsのプロゞェクトファむルは、Linuxのbuild / cm.batスクリプトを䜿甚しお生成できたす-build / cmLinux.sh
たた、LinuxおよびMac OS甚のOpenNIを䜿いこなすための支揎を拒吊したせん。

Source: https://habr.com/ru/post/J124009/


All Articles