Je lis 2,2 millions de points à partir d'un fichier pcd, et loadPCDFile utilise ca 13 sek à la fois en mode Release et Debug. Étant donné que les programmes de visualisation comme CloudCompare peuvent lire le fichier en ce qui semble être des millisecondes, je pense que je fais quelque chose de plus difficile que nécessaire.

Qu'est-ce que je fais mal?

Le haut de mon fichier pcd:

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS rgb x y z _
SIZE 4 4 4 4 1
TYPE F F F F U
COUNT 1 1 1 1 4
WIDTH 2206753
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 2206753
DATA binary
    ¥•ÃöèÝÃájfD        ®§”ÃÍÌÝÃá:fD        H”ø¾ÝÃH!fD   .....

Depuis mon code, lecture du fichier:

#include <iostream>
#include <vector>

#include <pcl/common/common.h>
#include <pcl/common/common_headers.h>
#include <pcl/common/angles.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include <boost/thread/thread.hpp>

int main() {
    (...)
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr largeCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    largeCloud->points.resize(3000000); //Tried to force resizing only once. Did not help much.

    if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("MY_POINTS.pcd", *largeCloud) == -1) {
        PCL_ERROR("Couldn't read file MY_POINTS.pcd\n");
        return(-1);
    }

    (...)
    return 0;
}

(Utilisation de PCL 1.8, Visual studio 2015)

1
emilal 20 avril 2017 à 17:00

3 réponses

Meilleure réponse

Résumé de ci-dessous ...

-PCL est légèrement plus lent au chargement des fichiers pcd formatés dans le cloud. En regardant les en-têtes, CC semble ajouter une variable supplémentaire à chaque point "_" que pcl n'aime pas et doit formater. Mais ce n'est qu'une différence de 30% à 40% du temps de chargement.

-Sur la base du résultat qu'avec le même nuage de points de taille (3 m), mon ordinateur a mis 13 secondes pour le charger à partir du cloud comparez alors que le programme était compilé en mode débogage et seulement 0,25 s pour charger le même cloud en mode version, je pense que vous exécutez en mode débogage. Selon la manière dont vous avez compilé / installé pcl, vous devrez peut-être reconstruire pcl pour générer la bibliothèque de version appropriée. Je suppose que tout ce que vous pensez faire pour passer du débogage à la publication n'engage pas en fait la bibliothèque de versions de pcl.

En PCL, dans presque toutes les fonctions, passer du débogage à la publication vous donnera souvent un traitement plus rapide d'un à deux ordres de grandeur (en raison de l'utilisation intensive par pcl d'objets de grand tableau qui doivent être gérés différemment en mode débogage pour la visibilité)



Test de pcl avec des fichiers de comparaison cloud

Voici le code que j'ai exécuté pour produire les sorties suivantes:

std::cout << "Press enter to load cloud compare sample" << std::endl;
    std::cin.get();

    TimeStamp stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColor.pcd", *tempCloud2);

    stopWatch.fullStamp(true);
    std::cout <<"Points loaded: "<< tempCloud2->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud2->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cout << "Press enter to save cloud in pcl format " << std::endl;
    std::cin.get();
    pcl::io::savePCDFileBinary("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud2);

    std::cout << "Press enter to load formatted cloud" << std::endl;
    std::cin.get();

    stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud3);
    stopWatch.fullStamp(true);
    std::cout << "Points loaded: " << tempCloud3->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud3->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cin.get();

Nuage comparer le nuage coloré généré (3 m points avec la couleur) cloud compare le nuage coloré généré (3 m points avec la couleur)

En cours de débogage, reproduit votre temps de chargement approximatif avec un nuage de 3 m pt L'exécution du débogage a reproduit votre temps de chargement approximatif avec un nuage de 3 mégapixels

Exécution en version

Running in release

1
Sneaky Polar Bear 11 mai 2017 à 17:13

Je me heurtais exactement à cette situation. Cela se résume simplement au style de stockage des fichiers. Votre fichier (qui prend autant de temps à charger) est presque certainement un fichier de nuage de points de style ascii. Si vous voulez pouvoir le charger beaucoup plus rapidement (x100), convertissez-le au format binaire. Pour référence, je charge un nuage de 1 m pt en environ un quart de seconde (mais cela dépend du système)

pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);

L'appel de charge est le même:

pcl::io::loadPCDFile(fp, *tempCloud);

Mais pour enregistrer en tant que binaire, utilisez ceci:

pcl::io::savePCDFileBinary(fp, *tempCloud);

Juste au cas où cela aiderait, voici un extrait du code que j'utilise pour charger et enregistrer les nuages (je les structure un peu, mais cela est probablement basé sur un exemple, alors voyez à quel point c'est important, mais vous voudrez peut-être jouer avec si vous passez au binaire et que vous constatez toujours de longs temps de chargement).

//save pt cloud
        std::string filePath = getUserInput("Enter file name here");
        int fileType = stoi(getUserInput("0: binary, 1:ascii"));
        if (filePath.size() == 0)
            printf("failed file save!\n");
        else
        {
            pcl::PointCloud<pcl::PointXYZ> tempCloud;
            copyPointCloud(*currentWorkingCloud, tempCloud);
            tempCloud.width = currentWorkingCloud->points.size();
            tempCloud.height = 1;
            tempCloud.is_dense = false;

            filePath = "../PointCloudFiles/" + filePath;
            std::cout << "Cloud saved to:_" << filePath << std::endl;
            if (fileType == 0){pcl::io::savePCDFileBinary(filePath, tempCloud);}
            else
            {pcl::io::savePCDFileASCII(filePath, tempCloud);}

        }

//load pt cloud
        std::string filePath = getUserInput("Enter file name here");
        if (filePath.size() == 0)
            printf("failed user input!\n");
        else
        {
            filePath = "../PointCloudFiles/" + filePath;
            pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);

            if (pcl::io::loadPCDFile(filePath, *tempCloud) == -1) //* load the file
            {
                printf("failed file load!\n");
            }
            else
            {
                copyPointCloud(*tempCloud, *currentWorkingCloud); std::cout << "Cloud loaded from:_" << filePath << std::endl;
            }
        }
  • Élément de liste
1
Sneaky Polar Bear 3 mai 2017 à 14:13

Cela semble correct, en comparant avec un exemple pcl. Je pense que le travail principal de loadPCDFile se fait dans la fonction pcl::PCDReader::read, qui se trouve dans le fichier pcd_io.cpp. Lors de la vérification du code pour les données binaires, comme c'est le cas dans votre cas, il y a 3 boucles for imbriquées qui vérifient si les données numériques de chaque champ sont valides. Le commentaire de code exact est

// Once copied, we need to go over each field and check if it has NaN/Inf values and assign cloud

Cela peut prendre du temps. Cependant, je spécule.

0
Adrian Schneider 2 mai 2017 à 08:56