cx_3d_snap_point_cloud+20201014

1、发现设备

std::string uri = cx::discoverAndChooseDevice()->deviceURI;
std::cout << "Open Device:" << uri.c_str() << endl;

连接相机

auto cam = cx::DeviceFactory::openDevice(uri);

可视化框架

cx::viz::Viz3d viz("Point Cloud");
cx::Variant val;
cam->getParam("DeviceScanType")
if(std::string(val)!="Linescan3D")
{
    cerr << "Current sensor devicemode is not 'Linescan3D',we activate it.." << endl;
    cam->setParam("DeviceScanType","Linescan")
    if (std::string(val) != "Linescan3D")
    {
        cerr << "Current sensor devicemode is not 'Linescan3D',we activate it..." 
        << endl;
        //向某个输出器输出
        cam->setParam("DeviceScanType","Linescan3D");
        //setParam是cam这个结构体中的成员变量,这是对这个变量进行赋值
      /*void setParam(const std::string& prm,const cx::Variant& val)
      {
           cx::checkOk("cx_setParam",cx_setParam(m_hDevice,prm.c_str(),val));
      }
      */   
    }
}

typedef cv::viz::Color Color;

2、从相机或文件加载3D校准

cx::c3d::Calib calib;

从给定文件加载校准

if (argc > 1)
{
    calib.load(argv[1]);
}

从传感器加载校准,可能的来源是“用户数据”、“校准”、“校准用户”

else 
{
    cx::downloadCalib(cam->getHandle(),calib);
}

3、在校准中设置相关采集参数,我们假设只有一个aoi激活

cx::updateCalib(cam->getHandle(),calib,1);

设置轮廓步长缩放

calib.get(CX_3D_PARAM_SY,val);
std::out << "enter profile distance,current value=" << (double)val << ",new value:";
std::string userInput;
cin >> userInput;
if (!=userInput.empty())
{
    double dy = std::stod(userInput);
    calib.set(CX_3D_PARAM_SY,dy);
    //CX_3D_PARAM_SY:从一个外形到下一个外形的距离乘以给定的y坐标
}

打印用于计算点云的更新校准

cx::printInfo(calib.getHandle());

为所有为0的范围图值设置将在点云中使用的无效值
可以是任何数字,例如-10.0f,如果使用NAN,则在showPointCloud中自动抑制点

float ivd = NAN;
calib.set(CX_3D_PARAM_METRIC_IDV,ivd)
//CX_3D_PARAM_METRIC_IDV:用于标记无效数据点的数据值无效,只有Z坐标用此值标记。如果pixel_格式为整数,则必须舍入为整数。

触发缓存更新,当使用参数>0调用时,内部缓存将更新。
这将防止在第一次调用度量函数cx_3d_range2calibratedABC

calib.set(CX_3D_PARAM_METRIC_CACHE_MODE,int(1));
/*
set的函数定义
void set(cx_3d_calib_param_t,param, const cx::Variant& val)
{
    cx::checkOk("cx_3d_calib_set",cx_3d_calib_set(m_hCalib, param, &val));
}

checkOk的函数定义
@overload
@param func    name of function that returned the status s.
@param s       status,see \ref CX_STATUS_ENUM for possible values.
inline cx_status_t checkOk(const char* func, cx_status_t s)
{
    if (s != CX_STATUS_OK)
    {
        throw(RuntimeError)
    }
}
*/

int(1):强制转换成整数,int型

4、分配和排队内部采集缓冲区
allocate and queue internal acquisition buffers

cam->allocAndQueueBuffers();
/*
void allocAndQueueBuffers(int numBuffers=3)
{
 cx::checkOk("cx_allocAndQueueBuffers",cx_allocAndQueueBuffers(m_hDevice,numBuffers));
}
*/

5、启动图像采集

cam->startAcquisition();

6、抓取采集缓冲区,等待具有可选超时的有效缓冲区,超时以毫秒为单位。
grab acquisition buffer,wait for valid buffer with optional timeout.Timeout is given in ms.

cx::DeviceBuffer buffer = cam->waitForBuffer(10000);

7、从缓冲区获取图像数据并对图像数据进行一些处理(或获取一个副本供以后使用)
注意img保存了对DeviceBuffer中的图像数据的引用,如果您需要cx_queueBuffer之后的图像数据,则需要克隆映像!

auto rangeImg = buffer.getImage();

可选地将范围图像保存到文件

if (argc > 2)
    rangeImg->save(argv[2]);
cout << "rangeImg height" << rangeImg->height() << endl; //100
cout << "rangeImg width" << rangeImg->width() << endl;//1280

8、计算点云

cx::c3d::PointCloud pc(rangeImg->height(),rangeImg->width());
cx::c3d::calculatePointCloud(calib,*rangeImg,pc);

获取 xyz 坐标

clock_t start_time = clock();
vector<cx::Point3f> tpour;    //图像坐标轮廓
vector<cv::Point2i>CenterlaserPoint;    //扫描点轮廓
cv::Point2i point;
for(unsigned x = 0; x < pc.points.width();x++)
//cx::Image points 仅在计算或从文件加载后有效。注:为了使用vtk(WCloud)可视化,必须使用//CX_PF_COORD3D_ABC32f(CV_32FC3)类型。
{
    cx::Point3f dx = pc.points.at<cx::Point3f>(4,x);    //(x,y,z相机坐标系下坐标) 
    if(dx.z < 200 && dx.z > -200)    //去除无效点
    point.x = x;
    point.y = (int)(10 * (dx.z));    //扩大z值,便于图像显示
    tpour.push_back(dx);    //相机坐标系坐标
    CenterlaserPoint.push_back(point);    //深度坐标,求特征点
    //在末端插入元件,提供强有力的保证
/*
void push_back(const _Ty& _val)
{
    emplace_back(_val);
}
//push_back是vector的一个方法,表示将一个元素存储到容器的末尾。
*/
}
cv::Mat midimage(1024, 1280,CV_8UC1, cv::Scalar::all(0));
//CV_8UC1 8表示8位,UC表示unsigned char,1表示1个通道, Scalar表示向量长度,要与通道数目一致
int size_num = CenterlaserPoint.size();    //扫描点轮廓的尺寸?
if (size_num < 1)
{
    return 0;
}
for (int i = 0;i < size_num; i++)
{
    midimage.at<uchar>(CenterlaserPoint[i].y + 512,CenterlaserPoint[i].x) = 255;
}
//求左边轮廓点位置
int Laserleft = 0;
for (int i = 20;i < size_num - 20; i++)
{
    if ((abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 1].y) > 3) &&
        (abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 2].y) > 5) &&
        (abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 3].y) > 10))
    {
        Laserleft = i-2;
        break;
    }  
}
if (Laserleft == 0)
{
    cout << "find point error" << endl;
    return 0;
}
cv::Point2f Leftpoint;
Leftpoint.x = CenterlaserPoint[Laserleft].x;
Leftpoint.y = CenterlaserPoint[Laserleft].y + 512;
cv::circle(midimage,Leftpoint,8,cv::Scalar(180,0,0),-1);
//求右边特征点位置
int Laserright = 0;
for (int i = 20;i < size_num - 20; i--)
{
    if ((abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 1].y) > 3) &&
        (abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 2].y) > 5) &&
        (abs(CenterlaserPoint[i].y - CenterlaserPoint[i + 3].y) > 10))
    {
        Laserleft = i+2;
        break;
    }  
}
if (Laserleft == 0)
{
    cout << "find point error" << endl;
    return 0;
}
cv::Point2f Rightpoint;
Rightpoint.x = CenterlaserPoint[Laserright].x;
Rightpoint.y = CenterlaserPoint[Laserright].y + 512;
cv::circle(midimage,Leftpoint,8,cv::Scalar(180,0,0),-1);
//求底部特征点位置
int Laserbottom = 0;
int point_bottom = CenterlaserPoint[Laserleft].y;
for (int i = Laserleft + 1;i < Laserright; i++)
{
    int point_bottom_new = CenterlaserPoint[i].y;
    if (point_bottom_new < point_bottom)
    {
        point_bottom = point_bottom_new;
        Laserbottom = i;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值