市场上各种深度摄像头测试之OPT8241

来源:互联网 发布:打条码软件 编辑:程序博客网 时间:2024/06/06 02:56

简要介绍

  • ToF,即time of flight,不同于二维图像来推算三维信息,而是通过红外光在空气中的飞行时间,计算出目标体的距离。
  • 相关文档:http://www.ti.com.cn/product/cn/OPT8241/technicaldocuments
  • 系统要求: Win7/Ubuntu 14.04 64 bit PC 2GB RAM Minimum of 500MB free
    space

资源下载

官方资源下载:http://www.ti.com/tool/opt8241-cdk-evm
使用官方软件就能使用该摄像头,若想下载SDK源码进行编译,参考以下资源:
cmake:http://www.cmake.org/download/
git:http://git-scm.com/download/win
CySuiteUSB:http://www.cypress.com/?rID=34870
QT:http://download.qt.io/official_releases/qt/5.4/5.4.2/qt-opensource-windows-x86-msvc2013_64-5.4.2.exe.mirrorlist
PCL:https://github.com/3dtof/pcl/releases/tag/1.7.2

  • 说明:
    1、PCL官网不提供1.7之后的版本下载,这仅提供了1.7.2的链接,若需要其他版本可自行Google或百度下载大牛编译好的pcl
    2、PCL和QT是必须支持你的编译环境的,另外源码仅支持64位编译,若环境不是64位将会报错,故下载请注意

源码编译过程

  1. 默认安装完上述软件后(记得提示加环境变量的就加),下载源码:https://github.com/3dtof/voxelsdk
    GitHub里也有教程,单个人不认为是用来编译源码的,自行斟酌
  2. 在源码目录中,Voxel文件夹下新建文件夹CyAPI,将安装后的CySuiteUSB文件夹中的CyAPI.lib和CyAPI.h拷贝到该目录
  3. 打开命令行,进入到源码目录下

    cd voxel-sdk mkdir build cd build set
    CMAKE_PREFIX_PATH=%CWD%;%CMAKE_PREFIX_PATH% cmake-gui ..

  4. 看到cmake图形界面,点击Configure,选择相应的编译环境,等待完成,若报错,请在图形界面中对应项手动选择路径,具体如下:
    如果它找不到PCL, 将PCL_DIR设为PCL的安装目录下版本号文件夹的一个cmake目录。 再点一下configure
    如果找不到VTK,设置CMAKE_PREFIX_PATH为vtk-6.1。
    如果找不到QT,设置Qt5Widgets_DIR为Qt5Widgets文件夹所在绝对路径

    说明:一般来说,cmake会自动寻找相应路径,保证PCL和QT的全能找到就可以,什么openNI之类貌似没影响

  5. 最后点击Generate,就能在build目录下看到项目文件
    编译完成后需要在环境变量中添加VOXEL_SDK_PATH这个环境变量为build文件夹所在路径,否则编译运行后会提示找不到设备。
  6. 之后在PATH当中添加%VOXEL_SDK_PATH%\bin和%VOXEL_SDK_PATH%\lib即可。如果没有添加这两个环境变量,会出现找不到dll文件而无法运行程序
  7. 最后一步,打开项目文件,重新生成解决方案,确保x64的Release配置无误,生成ALL_BUILD即可。
    说明:本人试过debug和release两种模式下的环境配置,然而debug始终会中断,无法调试,最终只能选择release下进行之后的操作

深度数据分析

  • opt8241的图像有以下种类:

    raw/phase/ambient/amplitude/flags/depth/pointcloud/vxl
    depth:深度
    pointcloud:点云
    其他:不知道

  • 图像格式:

    320 * 240 每个像素4个字节32bit 【12bit相位数据 12bit振幅数据 4bit环境数据
    4bit标记数据(某一个官网文档看到的,不知道翻译的对不对,也不知道是不是如此)】

深度图获取

  1. 源码sdk自带命令控制(一堆,说几个个人需要用到的): help 可看见所有命令及其作用 profilelist
    列举所有模式,短距,中距,长距。。。 profileselect id 选择对应id模式 filterlist
    列举所有滤波器(这样翻译不知对不对) 。 。 。 save type num filename
    :存储num帧type类型的图像数据到文件中,文件名为filename
  2. 这里只说深度图的存储:

    _saveFile.write((char *)f->depth.data(),
    sizeof(float)*f->size.width*f->size.height); _saveFile.write((char
    *)f->amplitude.data(), sizeof(float)*f->size.width*f->size.height);
    代码中是将深度数据和另一种数据都存到文件,一帧大小为320 * 240 * 4 * 2
    取出深度图就只需要文件中每一帧数据的前一半

  3. opencv取深度图:
    opencv配置:http://blog.csdn.net/wzw_ice/article/details/77159741
  4. 个人处理【未成功】: 在源码中的存储深度文件函数中加入以下代码
    里面包含了各种尝试,得出的结果始终不对。猜测原因:源图像数据是float类型32位存储,使用Mat存了数据之后放入png格式时,数据丢失导致结果错误
  float * depthData = (float*)f->depth.data();  cv::Mat depth(f->size.height, f->size.width, CV_32FC1, depthData);  //short int * depthtmp;  //cvConvertScale(depthData, depthtmp,255,0);  //cv::Mat depthf(f->size.height, f->size.width, CV_8UC1, depthtmp);  //IplImage iplimg = depth;  //IplImage* outimg = cvCreateImage(cvSize(iplimg.width,iplimg.height),32,1);  //cvConvertScale(&iplimg, outimg,1.0/(256*256-1));  //cv::Mat outmat=cv::cvarrToMat(outimg);  //cv::imwrite("./b.bmp", outmat);  //cvReleaseImage(&outimg);  cv::Mat depthImage = depth * 1000;  depth.convertTo(depthImage, CV_16UC1);  cv::imwrite("./depth.png",depth);  cv::imwrite("./depthtmp.png", depthImage);  std::cout << f->id << "##" << f->amplitude.data() << "##" << f->depth.data() << "##" << f->timestamp << "##" <<  std::endl;

5、 最终方案:直接读取sdk存储的文件,对文件进行读处理,对读到的每个像素的数据进行处理之后再用opencv存为png

void depthAmp2png(const std::string & filePath, const std::string & depthPath){    FILE * pFile;    long lSize;    char * buffer;    size_t result;    cout << filePath << " " << depthPath;    /* 若要一个byte不漏地读入整个文件,只能采用二进制方式打开 */    pFile = fopen(filePath.c_str(), "rb");    if (pFile == NULL)    {        fputs("File error", stderr);        exit(1);    }    /* 获取文件大小 */    fseek(pFile, 0, SEEK_END);    lSize = ftell(pFile);    cout << endl << lSize;    rewind(pFile);    /* 分配内存存储整个文件 */    buffer = (char*)malloc(sizeof(char)*lSize);    if (buffer == NULL)    {        fputs("Memory error", stderr);        exit(2);    }    /* 将文件拷贝到buffer中 */    result = fread(buffer, 1, lSize, pFile);    if (result != lSize)    {        fputs("Reading error", stderr);        exit(3);    }    fclose(pFile);    //to png file    float * bufferFloat = (float *)buffer;    int vertexSize = 320 * 240;    int imageSize = lSize / vertexSize / 4 / 2;    int strideOfImageChar = 320 * 240 * 4;    for (int index = 0; index < imageSize; index++)    {        cv::Mat depthMat = cv::Mat::zeros(240, 320, CV_32FC1);        //cv::Mat amplitude = cv::Mat::zeros(320, 240, CV_32FC1);        memcpy(depthMat.data, buffer + (index * 2) *strideOfImageChar, strideOfImageChar);        //memcpy(amplitude.data, buffer + (index * 2 + 1) *strideOfImageChar, strideOfImageChar);        std::string depthFilePath = depthPath + std::to_string(index) + ".png";        //std::string colorFilePath = depthPath + std::to_string(index) + "_visual.png";        //std::string amplitudePath = depthPath + std::to_string(index) + ".png";        ////2)visual depth image        //cv::Mat recolorDepth;        //cv::Mat grayImage;        //float max = 2.4;        //float min = 1.7;        //double alpha = 225.0 / (max - min);        //depthMat.convertTo(grayImage, CV_8UC1, alpha, -alpha *min);// expand your range to 0..255. Similar to histEq();        ////grayImage = restrictDepthImg(grayImage);        //cv::applyColorMap(grayImage, recolorDepth, cv::COLORMAP_JET);// this is great. It converts your grayscale image into a tone-mapped one, much more pleasing for the eye function is found in contrib module, so include contrib.hpp  and link accordingly        depthMat = depthMat * 1000;         depthMat.convertTo(depthMat, CV_16UC1);        if (!cv::imwrite(depthFilePath, depthMat))        {            cout << "error:" << depthFilePath << " raw data is shorter than header specify!";        }        //if (!cv::imwrite(colorFilePath, recolorDepth))        //{        //  LOG_ERROR << colorFilePath << " raw data is shorter than header specify!";        //}        //if (!cv::imwrite(amplitudePath, amplitude))        //{        //  LOG_ERROR << amplitudePath << " raw data is shorter than header specify!";        //}    }}
原创粉丝点击