初次使用Kinect体感,并用OpenCV显示彩色景深骨骼图

1.     安装Kinect驱动

安装驱动前,看下右侧的Installation instructions,这里简单翻译下:

  1. 体感不要连在电脑上
  2. 如果以前装了Kinect SDK要卸载它
  3. 关闭Visual Studio2010

http://www.kinectforwindows.org/download/

根据硬件平台选择要装的驱动(64bit安装64bit驱动,32bit安装32bit驱动)

(1)KinectSDK-v1.0-beta2-x86.msi    OR   KinectSDK-v1.0-beta2-x64.msi

(2)看看自己硬件是否符合要求,使用的是VS2010和Win7系统(恰好这二个我已经熟悉了,很多人依旧不用VS2010)

(3)为了能运行他给出的SkeletalViewer程序我们还要安装Microsoft DirectX® SDK - June 2010 or later version 和Runtime for Microsoft DirectX® 9

(4)如果你要使用语音功能,使用SpeechSamples那么继续安装,把他给的后面三个驱动都装了。注意安装和硬件平台对应的驱动。

2.体感(Kinect)

       买体感前确保它可以使用220V电源(我买的是台版,电压接受范围很大- -),一般买的是盒装的,他专门用于开发(但里面附增了一个正版游戏光碟,让我郁闷了)

先给体感连上电源,再把体感另一头USB接口连上电脑(那个附带的数据转换线是用来连接老式Xbox主机的,无视掉吧。)

如果你安装了驱动以及的USB没有问题(我第一次插入时USB失灵了),会看到右下角图标处有反应,双击出来看看。

正在安装驱动中

经过几分钟的等待,都安装上了!

设备管理器中也可以看到,这里说明安装成功了。我们可以看到体感摄像头中间的绿灯闪烁。

如果你第二次安装(这一次很快),那显示下图:

2.运行示例程序

程序在类似如下的目录,根据你安装的SDK目录了,如果默认这是c盘下。

Program Files\Microsoft SDKs\Kinect\v1.0Beta2\Samples\bin

你可以选择SkeletalViewer等运行试试效果。(注意骨骼图只有大于1.2米能会有效果)

3.最后再给出一个OpenCV打开摄像头的程序

首先要说明,本人虽然用64bit计算机但所有有关软件的配置都是按照32bit程序配置的,至今使用64bit电脑还么有写出过一个32bit的程序。囧。

配置问题:

打开项目属性页-à配置属性àVC++目录 中的”包含目录”,添加$(KINECTSDK_DIR)\inc,

库目录添加$(KINECTSDK_DIR)\lib\x86。

连接器—>输入à附加依赖项,添加MSRKinectNUI.lib

 

// kongzhitai.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace std;

using namespace cv;

//KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK

#include "windows.h"

#include "MSR_NuiApi.h"

//KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK

int main(int argc,char * argv[])

{

    //初始化NUI

    HRESULT hr = NuiInitialize( 

       NUI_INITIALIZE_FLAG_USES_COLOR);

    if( hr != S_OK )

    {

       cout<<"NuiInitializefailed"<<endl;

       return hr;

    }

    //打开KINECT设备的彩色图信息通道

    HANDLE h1 = CreateEvent( NULL,TRUE, FALSE, NULL );

    HANDLE h2 = NULL;

    hr = NuiImageStreamOpen(

       NUI_IMAGE_TYPE_COLOR,

       NUI_IMAGE_RESOLUTION_640x480,

       0,

       4,

       h1,

       &h2);

    if( FAILED( hr ) )

    {

       cout<<"Could notopen image stream video"<<endl;

       return hr;

    }

    //开始读取彩色图数据

    Matimg;img.create(480,640,CV_8UC3);

    uchar *pData;

    while(1)

    {

       WaitForSingleObject(h1,INFINITE);

       const NUI_IMAGE_FRAME *pImageFrame = NULL;

       

       hr = NuiImageStreamGetNextFrame(

           h2,

           0,

           &pImageFrame );

       if( FAILED( hr ) )

       {

           cout<<"GetImage Frame Failed"<<endl;

           continue;

       }

 

       INuiFrameTexture * pTexture =pImageFrame->pFrameTexture;

       NUI_LOCKED_RECT LockedRect;

       pTexture->LockRect( 0,&LockedRect, NULL, 0 );

       if( LockedRect.Pitch != 0 )

       {

       BYTE * pBuffer = (BYTE*)LockedRect.pBits;

       for(int i=0;i<480;i++)

       {

           pData=img.ptr<uchar>(i);

           for(int j=0;j<640;j++)

           {

              for(int k=0;k<3;k++)

              *(pData+j*3+k)=*(pBuffer+i*4*640+j*4+k);

           }

       }

       imshow("rgb",img);

       waitKey(36);

       imwrite("H:\\out.jpg",img);

       }

       if( LockedRect.Pitch != 0 )

       {

           BYTE * pBuffer = (BYTE*)LockedRect.pBits;

           //显示x200y400位置上的像素信息

           pBuffer +=(200+399*640)*4;

           printf("x:200 y:400坐标处的像素颜色:r:%d g:%d b:%d\n",pBuffer[2],pBuffer[1],pBuffer[0]);

       }

       else

       {

           cout<<"Bufferlength of received texture is bogus\r\n"<<endl;

       }

       //释放本帧数据,准备迎接下一帧

       NuiImageStreamReleaseFrame(h2, pImageFrame );

    }

    //关闭NUI链接

    NuiShutdown();

    return 0;

}

     不过此程序占用CPU比较大,本人i7机器上,占用了20%,有时会飙到30%,十分郁闷。通过方法改进也没有改进出来。而微软给的例子的效果特别好,只占用5%的CPU。我以为是DirectX的问题,这二天用MFC改写了下,效果依旧很差,发现也不是DirectX的问题。而微软使用底层API函数写的,效率却很高,弄了半天也没弄明白。接下来如果有空,我将分享一下在MFC下开发Kinect的经验(就是把图像显示出来,不影响按钮的操作)。目前有些问题还没有很好的解决,所以不能把不够成熟的东西拿出来。先说下,我在MFC下的框架用了多线程(工作者线程),工作者线程中通过SendMessage向主线程发送消息处理。暂时没有考虑到线程同步啊,锁啊之类东西。如果有人知道更好的方法,欢迎留言。

附录

1.     参考网站,http://www.cnkinect.com/

2.     百度文库: Kinect(幻象)sdk编程指南

3.     百度文库: skeletalviewer中文文档

 

安装过程的问题

安装MicrosoftDirectX SDK(June 2010)发生错误。(不过我发现,他是最后才发生错误的,对程序实际运行目前发现没有任何影响。下面是有些人的解决方法,如果你无法运行SkeletalViewer,可能需要参考下)

http://www.docin.com/p-60410380.html#

regedit.打开HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectX

里面有2个选项要修改,一个是Version,一个也许是ManagedDirectXVersion或者其他Version,把这2个值都改小,改成能正常安装为止,可以参考”C:\Windows\DirectX.log”内容

<think>好的,我现在需要解决用户关于使用C++在Arduino Mega和Kinect V2上,结合Visual Studio 2017、OpenCV 3.4.1以及组态王实现智能送风控制系统的问题。首先,我需要理清整个系统的各个组件和它们之间的交互方式。 首先,用户提到的硬件包括Arduino Mega和Kinect V2。Arduino Mega负责控制送风方向,可能通过舵机或步进电机来实现。Kinect V2用于捕捉人员的位置信息,这里需要用到深度摄像头和骨骼追踪功能。软件方面,Visual Studio 2017是开发环境,OpenCV 3.4.1处理像数据,组态王可能用于上位机的监控界面或控制系统。 接下来,我需要考虑各个部分的连接和通信。Kinect V2通常通过USB连接到PC,运行在Windows系统上,所以可能需要使用Kinect SDK或libfreenect2库来获取数据。OpenCV用于处理Kinect捕捉到的像,识别人体位置。然后,PC端需要将处理后的位置数据发送给Arduino Mega,可能通过串口通信。Arduino接收到数据后,根据位置调整舵机角度,改变送风方向。组态王可能作为上位机软件,用于监控系统状态或发送控制命令。 然后,我需要检查各个组件的兼容性和库的支持情况。Kinect V2在Windows上需要特定的驱动,而OpenCV 3.4.1可能已经支持Kinect的数据读取,或者需要额外的配置。Arduino Mega的串口通信在C++中可以使用Serial库,但在Visual Studio中可能需要安装插件,如Visual Micro,以便在VS中编写和上传代码到Arduino。用户提到的引用[4]提到了Visual Micro插件,可能需要指导用户安装配置。 接下来是代码部分。首先,Kinect的数据采集和处理。使用OpenCV可能需要初始化Kinect,捕获深度或彩色像,进行人体检测或骨骼追踪。这里可能需要使用OpenCV的背景减除、轮廓检测或者集成其他库如OpenNI。然后,计算人员的位置坐标,将其转换为舵机需要转动的角度。例如,检测到人在左侧,舵机转向左,反之亦然。 然后,串口通信部分。PC端需要将角度数据通过串口发送到Arduino Mega。在C++中,可以使用Windows API或第三方库如Boost.Asio来处理串口通信。Arduino端则需要监听串口,接收数据并控制舵机转动。引用[3]中的舵机控制代码可以作为参考,使用Servo库来控制舵机角度。 组态王的集成可能涉及到与C++程序的通信,比如通过OPC协议或TCP/IP。组态王可能需要接收来自主程序的数据,显示当前人员位置和送风状态,或者发送控制指令。这部分可能需要编写组态王的脚本或配置通信接口。 在整合所有部分时,需要注意各环节的数据格式和通信协议。例如,OpenCV处理后的坐标如何转换为角度,如何确保串口通信的稳定性和实时性,以及组态王如何与主程序交互。此外,还需要考虑系统的实时性,确保从人员位置检测到舵机响应的延迟足够低。 可能遇到的问题包括Kinect驱动安装、OpenCVKinect的兼容性、串口通信的配置、Visual Studio插件的使用,以及组态王与C++程序的通信设置。需要逐一排查这些环节,并提供相应的解决方案或示例代码。 最后,根据用户提供的引用,引用[1]和[2]涉及Arduino与传感器的连接和通信,引用[3]是舵机控制的代码示例,引用[4]是Visual Studio的Arduino插件,这些都可以作为参考资料整合到教程中。因此,整个系统的搭建步骤大致分为硬件连接、Kinect数据采集、OpenCV处理、串口通信、Arduino控制以及组态王集成这几个部分,需要分步骤详细说明,并提供代码示例和配置方法。</think>### 分步解决方案 #### **1. 硬件搭建与通信配置** - **Arduino Mega与执行机构连接** 使用舵机/步进电机控制送风方向,接线参考引用[1]的传感器连接逻辑: ``` 舵机信号线 → 数字引脚9 电源 → +5V/GND ``` 示例代码参考引用[3]的舵机控制逻辑: ```cpp #include <Servo.h> Servo fanServo; void setup() { fanServo.attach(9); } void loop() { // 接收串口角度值并转动 if (Serial.available() > 0) { int angle = Serial.parseInt(); fanServo.write(angle); } } ``` - **Kinect V2与PC通信** 安装Kinect SDK 2.0或开源库(如`libfreenect2`),确保通过USB 3.0连接PC。 #### **2. Visual Studio 2017环境配置** - **安装Visual Micro插件** 参考引用[4],在VS2017中安装Visual Micro插件以支持Arduino开发[^4]。 - **配置OpenCV 3.4.1** 在VS项目中设置OpenCV库路径,包含头文件及链接库。 #### **3. Kinect数据采集与人员定位** - **C++代码框架(VS2017)** 使用Kinect API获取骨骼数据,结合OpenCV处理像: ```cpp #include <Kinect.h> #include <opencv2/opencv.hpp> using namespace cv; int main() { IKinectSensor* pSensor; GetDefaultKinectSensor(&pSensor); pSensor->Open(); // 获取骨骼数据流 IBodyFrameSource* pBodySource; pSensor->get_BodyFrameSource(&pBodySource); // 循环检测人员坐标 while (true) { IBodyFrame* pBodyFrame; pBodySource->OpenReader(&pBodyReader); pBodyReader->AcquireLatestFrame(&pBodyFrame); // 解析骨骼坐标并计算中心点 // 发送角度至Arduino } return 0; } ``` #### **4. 串口通信实现** - **PC端C++代码(Windows API)** 通过串口发送角度数据至Arduino: ```cpp #include <Windows.h> HANDLE hSerial = CreateFile("COM3", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); DCB dcbSerialParams = {0}; dcbSerialParams.BaudRate = CBR_9600; SetCommState(hSerial, &dcbSerialParams); // 发送角度值 char angleStr[10]; sprintf(angleStr, "%d\n", targetAngle); WriteFile(hSerial, angleStr, strlen(angleStr), NULL, NULL); ``` #### **5. 组态王集成** - **数据监控界面设计** 在组态王中配置以下元素: - 实时显示人员位置坐标 - 舵机角度状态指示 - 手动控制模式切换按钮 - **OPC通信配置** 通过OPC服务器与C++程序交换数据,读取坐标并发送控制指令。 #### **6. 系统联调** - **验证流程** 1. Kinect检测到人员位置 → 计算目标角度 2. PC通过串口发送角度至Arduino 3. 舵机转动至指定方向 4. 组态王同步更新状态 --- ### 示例代码整合 **Arduino端(舵机控制)** ```cpp #include <Servo.h> Servo fanServo; void setup() { Serial.begin(9600); fanServo.attach(9); } void loop() { if (Serial.available() > 0) { int angle = Serial.parseInt(); fanServo.write(angle); Serial.print("Set to: "); Serial.println(angle); } } ``` **PC端(C++/OpenCV/Kinect)** ```cpp // 简化的坐标转换逻辑 Point3f getPersonPosition() { // 使用Kinect API获取骨骼坐标 // 返回三维空间中的中心点 } void sendAngleToArduino(int angle) { // 使用Windows API发送串口数据 } ``` --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值