2017-09-06 25 views
0

pcl :: pointcloud의 평면 섹션을 이진 이미지로 변환하려고합니다. savePNGFile이라는 클래스를 찾았지만 내 프로그램과 잘 작동하지 않습니다.은 pcl :: pointcloud를 2 진 이미지로 변환합니다. C++

지금까지 ROI 선택기와 강도 필터를 사용하여 원하는 포인트를 얻었습니다.

void regionOfInterest(VPointCloud::Ptr cloud_in, double x1, double x2, 
double y1, double y2, double z) 
{ 
    for (VPoint& point: cloud_in->points) 
    if ((z > point.z) && (y1 > point.y) && (y2 < point.y) && (x1 > point.x) 
    &&(x2 < point.x)) 
     cloud_out->points.push_back(point); 
} 

내가 관련 내가 보여 코드 조각이없는 어쩌면 알고 (VPointCloud은 내 데이터로 작업해야하는 점 구름의 종류), 그러나 당신이 더 많거나 적은 종류 나 '표시 할 수 있습니다 사용하고 있습니다.

이 pointcloud를 이진 이미지로 내보내는 방법을 아는 사람이 있습니까? 이 단계가 끝나면 OpenCV와 함께 작업 할 것입니다.

감사합니다.

+0

은 pointcloud 구조 또는 비정형 구조입니다. –

+0

이것이 dicom 데이터라고 가정합니다. 이 경우 구조화해야합니다 –

+0

이진 이미지 란 무엇입니까? 투영 된 카메라의 픽셀이 점을 보았는지 여부 또는 필터링 된 점으로 심도있는 이미지를 원하십니까? 어쨌든 [포인트 클라우드에서 레인지 이미지] (http://pointclouds.org/documentation/tutorials/range_image_creation.php) 또는 [포인트 클라우드에서 이미지] (http://wiki.ros.org/)를 보았습니까? pcl_ros/Tutorials/CloudToImage)? 또한, [패스 스루 필터] (http://pointclouds.org/documentation/tutorials/passthrough.php)를 확인해야합니다 – apalomer

답변

0

이 방법은 정리 된 데이터 또는 정리되지 않은 데이터에 대해 작동합니다. 그러나 입력 점 구름면이 직교 치수 중 두 개에 평행하고 제거 할 치수를 알고 있도록 회전해야 할 수 있습니다. stepSize1과 stepSize2는 포인트 클라우드의 크기가 새 이미지의 픽셀이되는 크기를 설정하는 매개 변수입니다. 점 밀도를 기준으로 회색 음영 이미지를 계산하지만 깊이 또는 기타 정보를 표시하도록 쉽게 수정할 수 있습니다. 간단한 임계 값을 사용하여 이미지를 바이너리화할 수도 있습니다.

cv::Mat makeImageFromPointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, std::string dimensionToRemove, float stepSize1, float stepSize2) 
{ 
    pcl::PointXYZI cloudMin, cloudMax; 
    pcl::getMinMax3D(*cloud, cloudMin, cloudMax); 

    std::string dimen1, dimen2; 
    float dimen1Max, dimen1Min, dimen2Min, dimen2Max; 
    if (dimensionToRemove == "x") 
    { 
     dimen1 = "y"; 
     dimen2 = "z"; 
     dimen1Min = cloudMin.y; 
     dimen1Max = cloudMax.y; 
     dimen2Min = cloudMin.z; 
     dimen2Max = cloudMax.z; 
    } 
    else if (dimensionToRemove == "y") 
    { 
     dimen1 = "x"; 
     dimen2 = "z"; 
     dimen1Min = cloudMin.x; 
     dimen1Max = cloudMax.x; 
     dimen2Min = cloudMin.z; 
     dimen2Max = cloudMax.z; 
    } 
    else if (dimensionToRemove == "z") 
    { 
     dimen1 = "x"; 
     dimen2 = "y"; 
     dimen1Min = cloudMin.x; 
     dimen1Max = cloudMax.x; 
     dimen2Min = cloudMin.y; 
     dimen2Max = cloudMax.y; 
    } 

    std::vector<std::vector<int>> pointCountGrid; 
    int maxPoints = 0; 

    std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> grid; 

    for (float i = dimen1Min; i < dimen1Max; i += stepSize1) 
    { 
     pcl::PointCloud<pcl::PointXYZ>::Ptr slice = passThroughFilter1D(cloud, dimen1, i, i + stepSize1); 
     grid.push_back(slice); 

     std::vector<int> slicePointCount; 

     for (float j = dimen2Min; j < dimen2Max; j += stepSize2) 
     { 
      pcl::PointCloud<pcl::PointXYZ>::Ptr grid_cell = passThroughFilter1D(slice, dimen2, j, j + stepSize2); 

      int gridSize = grid_cell->size(); 
      slicePointCount.push_back(gridSize); 

      if (gridSize > maxPoints) 
      { 
       maxPoints = gridSize; 
      } 
     } 
     pointCountGrid.push_back(slicePointCount); 
    } 

    cv::Mat mat(static_cast<int>(pointCountGrid.size()), static_cast<int>(pointCountGrid.at(0).size()), CV_8UC1); 
    mat = cv::Scalar(0); 

    for (int i = 0; i < mat.rows; ++i) 
    { 
     for (int j = 0; j < mat.cols; ++j) 
     { 
      int pointCount = pointCountGrid.at(i).at(j); 
      float percentOfMax = (pointCount + 0.0)/(maxPoints + 0.0); 
      int intensity = percentOfMax * 255; 

      mat.at<uchar>(i, j) = intensity; 
     } 
    } 

    return mat; 
} 


pcl::PointCloud<pcl::PointXYZ>::Ptr passThroughFilter1D(const pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, const std::string field, const double low, const double high, const bool remove_inside) 
{ 
    if (low > high) 
    { 
     std::cout << "Warning! Min is greater than max!\n"; 
    } 

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>); 
    pcl::PassThrough<pcl::PointXYZI> pass; 

    pass.setInputCloud(cloud); 
    pass.setFilterFieldName(field); 
    pass.setFilterLimits(low, high); 
    pass.setFilterLimitsNegative(remove_inside); 
    pass.filter(*cloud_filtered); 
    return cloud_filtered; 
}