लिनक्स पर Kinect को हराएं

यह सी ++ अनुप्रयोगों के विकास के बारे में एक श्रृंखला का दूसरा लेख है जो Microsoft Kinect के साथ काम करता है। इस भाग में, हम इस बारे में बात करेंगे कि डिवाइस को लिनक्स पर कैसे काम करना है और इसका उपयोग आपके अनुप्रयोगों में कैसे किया जा सकता है।

Kinect के लिए पहला विकास लेख यहां पढ़ा जा सकता है । मैं दृढ़ता से पहले भाग को पढ़ने की सलाह देता हूं क्योंकि इसके बिना, दूसरे का प्रभाव अधूरा होगा।


परिचय


जैसा कि पहले लेख में पहले ही उल्लेख किया गया है, Microsoft से आधिकारिक एसडीके के अलावा, तीसरे पक्ष के निर्माताओं से कई पुस्तकालय हैं:

वैकल्पिक एसडीके, आधिकारिक लोगों के विपरीत, लिनक्स और मैक ओएस के तहत विकास के लिए इस्तेमाल किया जा सकता है।
उपयोग करने के लिए सबसे आसान है libfreenect (OpenNI, संकलित और आधिकारिक दस्तावेज के अनुसार स्थापित। उदाहरण के लिए, मैं नवीनतम उबंटू में काम नहीं करना चाहता था, यह काफी संभव है कि इस तथ्य के कारण कि Kinect के लिए ड्राइवर को OpenNI प्लेटफॉर्म के अस्थिर संस्करण की आवश्यकता है, और अस्थिर इतना अस्थिर है) । आधिकारिक दस्तावेज में जो कुछ भी कहा गया है वह सच है और हां, यह काम करता है।

Libfreenect स्थापित करें


यह संतुष्टिदायक है कि उबंटू के लिए 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

उबंटू x64 के लिए, /usr/local/lib64/ लाइन /usr/local/lib64/
उसके बाद, आप बिल्ड / बिन फ़ोल्डर में उदाहरण चला सकते हैं - वे बहुत अच्छी तरह से पुस्तकालय की क्षमताओं का वर्णन करते हैं।

लिनक्स पर wxWidgets स्थापित करें


Ubuntu में wxWidgets के लिए बाइनरी पैकेज भी उपलब्ध हैं (लेकिन केवल स्थिर 2.8.x शाखा के लिए, जो, हालांकि, काम के लिए काफी पर्याप्त है)। पैकेज libwxgtk2.8-dev स्थापित करें और समस्या हल हो गई है।

एक काम दो बार कैसे नहीं


एक समय में, क्यूटी का एक अच्छा मकसद था - राइट वन्स, रन एनीव्हेयर । इसे व्यवस्थित करना अच्छा होगा, लेकिन wxWidgets के साथ। लेकिन स्थिति यह है कि, स्रोत कोड के अलावा, हमारे पास अभी भी परियोजना फाइलें हैं (पहले भाग के बाद हमें विजुअल स्टूडियो से परियोजनाएं मिलीं, लेकिन लिनक्स उनके लिए बहुत कम उपयोग है) और अब, नए ओएस के लिए कोड के प्लेटफ़ॉर्म-निर्भर हिस्से को लिखने से पहले, यह अच्छा होगा कि कैसे प्रोजेक्ट फ़ाइलों के निर्माण और कॉन्फ़िगरेशन को स्वचालित करने के लिए। CMake उपयोगिता हमें इसमें मदद करेगी।
CMake क्यों अच्छा है? सबसे पहले, लिनक्स सभी अलग हैं। यदि आपकी मशीन पर कुछ थर्डपार्टी लाइब्रेरी एक पथ पर स्थित है, तो यह एक तथ्य नहीं है कि आपके सभी सहकर्मियों या उपयोगकर्ताओं के पास वहां होगा। यहां तक ​​कि कुछ बिल्ड मापदंडों को बदलने के मामले में आउटपुट pkg-config का उपयोग करते समय, मैन्युअल रूप से लिखी गई परियोजनाओं में बहुत सारे स्थान होंगे जहां आपको हाथ से नए पैरामीटर लिखना होगा। सीएमके के माध्यम से इस सभी छोटे काम को स्वचालित करके, जो परियोजना फ़ाइलों को बनाता है जो पहले से ही एक विशिष्ट कार्य मशीन के लिए कॉन्फ़िगर किया गया है, हम बहुत समय बचा सकते हैं।
विंडोज के साथ, कहानी एक ही है - क्यों सभी मापदंडों को अपने हाथों से पंजीकृत करें यदि सीएमके खुद ही बड़ी संख्या में विभिन्न पुस्तकालयों की खोज कर सकते हैं यदि वे सिस्टम में स्थापित हैं, और फिर पहले से कॉन्फ़िगर किए गए मापदंडों के साथ प्रोजेक्ट उत्पन्न करते हैं।
वास्तव में परियोजनाओं को उत्पन्न करने के अलावा, सीएमके के लिए स्क्रिप्ट में आप प्रत्येक प्लेटफॉर्म के लिए सशर्त मापदंडों को निर्दिष्ट कर सकते हैं, उदाहरण के लिए, किसी विशेष ओएस के लिए प्रोजेक्ट में कुछ फ़ाइलों को शामिल करना / बाहर करना, किसी विशेष ओएस के लिए विशिष्ट तीसरे पक्ष के पुस्तकालयों से निर्भरता जोड़ना या निकालना, आदि।
किसी भी मामले में, सीएमके का उपयोग करने का विषय एक अलग लेख के योग्य है। हमारे मामले में, सीएमके लिपियों की लिस्टिंग के साथ पाठ को अधिभार नहीं देने के लिए, मैं उन्हें रिपॉजिटरी में लिंक प्रदान करूंगा:

आइए संक्षेप में बताएं कि पिछली बार हमें क्या मिला था:

महान, सभी को याद है, अब हम लिनक्स के तहत कामेच्छा की विजय के लिए आगे बढ़ सकते हैं।

कोडिंग



लाइब्रेरी का प्रारंभिककरण और विचलन


इससे पहले कि आप freenect_init() उपकरणों का उपयोग करने के लिए एपीआई का उपयोग करना शुरू करें, आपको 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

उपकरणों की एक सूची प्राप्त करना


Libfreenect में उपलब्ध उपकरणों की संख्या प्राप्त करने के लिए, freenect_num_devices() फ़ंक्शन का उपयोग करें:
FREENECTAPI int freenect_num_devices(freenect_context *ctx);

दुर्भाग्य से, libfreenect में एक व्यक्तिगत डिवाइस के लिए एक अद्वितीय नाम प्राप्त करने के लिए एक एपीआई नहीं है, इसलिए किसी भी तरह से हमारे आवेदन में उपकरणों की पहचान करने के लिए, आपको वर्कअराउंड के साथ आना होगा, उदाहरण के लिए, डिवाइस इंडेक्स वाले कुछ स्ट्रिंग मान लौटाएं, उदाहरण के लिए:
wxString KinectHelperImplFreenect::GetDeviceName(size_t index)
{
wxString name = wxT( "Unknown Kinect Sensor" );
if (m_Context)
{
name = wxString::Format(wxT( "Kinect %u" ), index);
}
return name;
}


काइनेक्ट इमेज कैप्चर


किफ़ेक्ट लाइब्रेरी में किनेक्ट से छवियों को पकड़ने के दो तरीके हैं - एपीआई के एक तुल्यकालिक या अतुल्यकालिक संस्करण का उपयोग करना। एसिंक्रोनस विकल्प के मामले में, जब एक नया फ्रेम आता है, तो एक कॉलबैक फ़ंक्शन कहा जाएगा, जिसमें आने वाले बफर को संसाधित करना संभव है। बफर के लिए मेमोरी को स्वतंत्र रूप से आवंटित किया जा सकता है या पुस्तकालय खुद एक आंतरिक बफर बनाने और काम पूरा होने पर मेमोरी को साफ करने का ख्याल रख सकता है।

छवि पर कब्जा शुरू करने के लिए, आपको 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 "अतुल्यकालिक" है, फिर भी आप मैन्युअल रूप से नियंत्रण प्रवाह बनाए बिना नहीं कर सकते। समय-समय पर, आपको freenect_process_events() फ़ंक्शन को कॉल करने की आवश्यकता होती है, जो ईवेंट क्यू को 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 के विपरीत, केवल 11 बिट्स का उपयोग गहराई मान के लिए किया जाता है, और 12. खिलाड़ी सूचकांक प्राप्त करने का कोई तरीका नहीं है।

एक रंग छवि प्राप्त करना


सिद्धांत रूप में, एक रंगीन छवि प्राप्त करने के लिए एक उपकरण स्थापित करने के लिए एल्गोरिथ्म एक गहराई बफर प्राप्त करने के लिए एल्गोरिथ्म के समान है, केवल फ़ंक्शन 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;
}

सभी वर्णित कार्यों के परिणामस्वरूप, हड़पने का एक नया वर्ग बनाया गया था, जो लिनक्स में काफी अच्छी तरह से काम करता है। दुर्भाग्य से, libfreenect में खिलाड़ियों की स्थिति प्राप्त करने के लिए कोई एपीआई नहीं है, इन उद्देश्यों के लिए आपको ओपन-पार्टी के आधार पर तीसरे पक्ष (या अपने स्वयं के) विकास का उपयोग करना होगा। लेकिन जो मान्यता के लिए काफी है, उदाहरण के लिए, आंदोलन का।



निष्कर्ष में


मुझे लगता है कि अब हम सिद्धांत के साथ समाप्त होंगे। अगला भाग अभ्यास का होगा।
मैं एक बार फिर याद दिलाता हूं कि काइनेट के साथ काम करने के लिए उदाहरण और आवरण पुस्तकालयों के सभी स्रोत कोड यहां डाउनलोड किए जा सकते हैं
लिनक्स के लिए बिल्ड / cm.bat स्क्रिप्ट का उपयोग करके विंडोज के लिए प्रोजेक्ट फाइलें उत्पन्न की जा सकती हैं - बिल्ड / cmLinux.sh
इसके अलावा, मैं लिनक्स और मैक ओएस के लिए ओपनएनआई को नामित करने में मदद से इनकार नहीं करूंगा।

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


All Articles