преобразовать pcl::pointcloud в бинарное изображение. С++

Я пытаюсь преобразовать плоскую часть pcl::pointcloud в двоичное изображение. Я нашел класс savePNGFile, но он плохо работает с моей программой.

До сих пор я использовал селектор 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 — это то облако точек, которое мне нужно для работы с моими данными). Я знаю, что, возможно, фрагмент кода, который я там показываю, неактуален, но он может показать вам более или менее типы, которые я использую.

Кто-нибудь знает, как экспортировать это облако точек в двоичное изображение? После этого шага я буду работать с OpenCV.

Спасибо


person Alejandro Trigo Rosón    schedule 06.09.2017    source источник
comment
структурировано или неструктурировано облако точек   -  person Sneaky Polar Bear    schedule 06.09.2017
comment
Я предполагаю, что это данные Dicom? в этом случае он должен быть структурирован   -  person Sneaky Polar Bear    schedule 06.09.2017
comment
Что вы подразумеваете под бинарным изображением? видел ли пиксель проецируемой камеры точку? или вам нужно изображение глубины с отфильтрованными точками? В любом случае, смотрели ли вы изображение диапазона из облака точек или облако точек на изображение? Кроме того, вы должны проверить сквозной фильтр   -  person apalomer    schedule 06.09.2017
comment
Извините, что пропустил так много информации, я начну с самого начала: Сначала я получаю облако точек из файла pcd. Я применяю фильтры и получаю меньшее облако точек со всеми точками белого цвета, где глубина почти равна 0. Теперь я хочу применить глубокое обучение, чтобы узнать, где на изображении есть объекты, но мне нужно изображение (бинарное изображение, массив из 0 и 1), чтобы передать его через алгоритм DL   -  person Alejandro Trigo Rosón    schedule 06.09.2017
comment
Правильно, я понимаю, что вы пытаетесь сделать, хотя мой вопрос касается структуры. Если он у вас есть, вам нужно его использовать, а если у вас его нет, вам нужно искусственно создать его, чтобы сделать образ.   -  person Sneaky Polar Bear    schedule 06.09.2017
comment
Я не знаю, что вы имеете в виду под структурированным ... Я использую облака точек несколько дней назад, поэтому я еще не очень экспериментировал ...   -  person Alejandro Trigo Rosón    schedule 06.09.2017
comment
могут быть организованы в виде массива xyz. что сгенерировало данные облака точек?   -  person Sneaky Polar Bear    schedule 06.09.2017
comment
Да, это организовано   -  person Alejandro Trigo Rosón    schedule 06.09.2017


Ответы (1)


Этот метод должен работать как для организованных, так и для неорганизованных данных. Однако вам может потребоваться повернуть плоскость входного облака точек так, чтобы она была параллельна двум ортогональным измерениям, и вы знали, какое измерение вы хотите удалить. 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;
}
person brad    schedule 07.09.2017
comment
pcl::passThroughFilter1D не существует! разве это не должно быть pcl::PassThrough вместо этого? - person Färid Alijani; 12.08.2019
comment
Это пользовательский метод, который я создал и определяется в нижней части фрагмента кода. - person brad; 12.08.2019