Kinect+OpenNI学习笔记之3(获取kinect的数据并在Qt中显示的类的设计)

本文介绍了一种利用OpenNI库和Kinect传感器进行图像和深度数据采集的方法。通过面向对象的设计,实现了图像数据和深度数据的实时更新,并在Qt环境中进行可视化展示。

本文改编自http://www.cnblogs.com/tornadomeet/archive/2012/09/29/2708029.html

对原文的程序架构进行了改编,符合面向对象的思想

头文件:ckinectreader.h  copenni.h

源文件:ckinectreader.cpp  copenni.cpp  main.cpp

代码贴在下面

copenni.h

#ifndef COPENNI_H
#define COPENNI_H
#include <ni/XnCppWrapper.h>
#include <QtGui>
#include <QApplication>
#include <qmessagebox.h>
#include <iostream>
using namespace std;
using namespace xn;

class COpenNI
{
public:
    COpenNI();
    ~COpenNI();
    bool Initial();
    bool Start();
    bool UpdateData();

    DepthMetaData depth_metadata;
    ImageMetaData image_metadata;
private:
    //return true if wrong,else return false
    bool CheckError(const char* error);
    XnStatus status;
    Context context;
    DepthGenerator depth_generator;
    ImageGenerator image_generator;
};

#endif // COPENNI_H


ckinectreader.h

#ifndef CKINECTREADER_H
#define CKINECTREADER_H

#include "copenni.h"
#include <QObject>
#include <QtGui>
#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <ni/XnCppWrapper.h>
#include <iostream>

using namespace std;

class CKinectReader : public QObject
{
    //to do things from here
public:
    CKinectReader(COpenNI &openni,QGraphicsScene &scene):openni(openni),scene(scene){
        test=0.0;
    }
    ~CKinectReader();
    bool Start(int interval=33);
    float test;
private:
    void timerEvent(QTimerEvent *);

    COpenNI &openni;
    QGraphicsScene &scene;
    QGraphicsPixmapItem *image_item;
    QGraphicsPixmapItem *depth_item;
    uchar *p_depth_argb;
};

#endif // CKINECTREADER_H


copenni.cpp

#include "copenni.h"

COpenNI::COpenNI()
{
}
COpenNI::~COpenNI()
{
    context.Release();
}
bool COpenNI::Initial()
{
    //initialize
    status=context.Init();
    if(CheckError("Context initial failed!")){
        return false;
    }
    context.SetGlobalMirror(true);//设置镜像
    //产生图片node
    status = image_generator.Create(context);
    if(CheckError("Create image generator  error!")) {
        return false;
    }
    //产生深度node
    status = depth_generator.Create(context);
    if(CheckError("Create depth generator  error!")) {
        return false;
    }
    //视角校正
    status = depth_generator.GetAlternativeViewPointCap().SetViewPoint(image_generator);
    if(CheckError("Can't set the alternative view point on depth generator")) {
        return false;
    }
    return true;
}

bool COpenNI::Start() {
    status = context.StartGeneratingAll();
    if(CheckError("Start generating error!")) {
        return false;
    }
    return true;
}

bool COpenNI::UpdateData() {
    status = context.WaitNoneUpdateAll();
    if(CheckError("Update date error!")) {
        return false;
    }
    //获取数据
    image_generator.GetMetaData(image_metadata);
    depth_generator.GetMetaData(depth_metadata);

    return true;
}

bool COpenNI::CheckError(const char* error) {
    if(status != XN_STATUS_OK ) {
        QMessageBox::critical(NULL, error, xnGetStatusString(status));
        cerr << error << ": " << xnGetStatusString( status ) << endl;
        return true;
    }
    return false;
}


ckinectreader.cpp

#include "ckinectreader.h"

CKinectReader::~CKinectReader(){
    scene.removeItem(image_item);
    scene.removeItem(depth_item);
    delete[] p_depth_argb;
}

bool CKinectReader::Start(int interval) {
    openni.Start();//因为在调用CKinectReader这个类的之前会初始化好的,所以这里直接调用Start了
    image_item = scene.addPixmap(QPixmap());
    image_item->setZValue(1);
    depth_item = scene.addPixmap(QPixmap());
    depth_item->setZValue(2);
    openni.UpdateData();
    p_depth_argb = new uchar[4*openni.depth_metadata.XRes()*openni.depth_metadata.YRes()];
    startTimer(interval);//这里是继承QObject类,因此可以调用该函数
    return true;
}

void CKinectReader::timerEvent(QTimerEvent *) {

    openni.UpdateData();
    //这里使用const,是因为右边的函数返回的值就是const类型的
    const XnDepthPixel *p_depth_pixpel = openni.depth_metadata.Data();
    unsigned int size = openni.depth_metadata.XRes()*openni.depth_metadata.YRes();

    //找深度最大值点
    XnDepthPixel max_depth = *p_depth_pixpel;
    for(unsigned int i = 1; i < size; ++i)
        if(p_depth_pixpel[i] > max_depth )
            max_depth = p_depth_pixpel[i];
    test = max_depth;

    //将深度图像格式归一化到0~255
    int idx = 0;
    for(unsigned int i = 1; i < size; ++i) {
        //一定要使用1.0f相乘,转换成float类型,否则该工程的结果会有错误,因为这个要么是0,要么是1,0的概率要大很多
        float fscale = 1.0f*(*p_depth_pixpel)/max_depth;
        if((*p_depth_pixpel) != 0) {
            p_depth_argb[idx++] = 255*(1-fscale);    //蓝色分量
            p_depth_argb[idx++] = 0; //绿色分量
            p_depth_argb[idx++] = 255*fscale;   //红色分量,越远越红
            p_depth_argb[idx++] = 255*(1-fscale); //距离越近,越不透明
        }
        else {
            p_depth_argb[idx++] = 0;
            p_depth_argb[idx++] = 0;
            p_depth_argb[idx++] = 0;
            p_depth_argb[idx++] = 255;
        }
        ++p_depth_pixpel;//此处的++p_depth_pixpel和p_depth_pixpel++是一样的
    }
    //往item中设置图像色彩数据
    image_item->setPixmap(QPixmap::fromImage(
                          QImage(openni.image_metadata.Data(), openni.image_metadata.XRes(), openni.image_metadata.YRes(),
                          QImage::Format_RGB888)));
    //往item中设置深度数据
    depth_item->setPixmap(QPixmap::fromImage(
                          QImage(p_depth_argb, openni.depth_metadata.XRes(), openni.depth_metadata.YRes()
                          , QImage::Format_ARGB32)));
}


main.cpp

#include <QtGui/QtGui>
#include <QDebug>
#include <QGraphicsView>
#include "ckinectreader.h"

int main(int argc, char **argv)
{
    COpenNI openni;
    if(!openni.Initial())//初始化返回1表示初始化成功
        return 1;

    QApplication app(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view;
    view.setScene(&scene);
    view.resize(650, 540);
    view.show();

    CKinectReader kinect_reader(openni, scene);
    kinect_reader.Start();//启动,读取数据
    qDebug() << kinect_reader.test;
    return app.exec();
}

程序逻辑,跟原文相同!

可以直接运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值