Wie konvertieren von cv::Mat zu pcl::Punktewolke mit Farbe

Ich versuche zu konvertieren, die eine Punktewolke mit rgb-Informationen aus pcl-format auf cv::Mat und zurück nach pcl. Ich habe festgestellt konvertieren Matte Punktewolke auf stackoverflow.

– Code Aktualisiert

Habe ich deshalb verwendet, die code von stackoverflow als Ausgangspunkt. Und habe nun das folgende:

//input pcl::PointCloud<pcl::PointXYZRGB> point_cloud_ptr
cv::Mat OpenCVPointCloud(3, point_cloud_ptr.points.size(), CV_64FC1);
OpenCVPointCloudColor = cv::Mat(480, 640, CV_8UC3);
for(int y=0;y<OpenCVPointCloudColor.rows;y++)
{
    for(int x=0;x<OpenCVPointCloudColor.cols;x++)
    {
        OpenCVPointCloud.at<double>(0,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).x;
        OpenCVPointCloud.at<double>(1,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).y;
        OpenCVPointCloud.at<double>(2,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).z;

        cv::Vec3b color = cv::Vec3b(point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).b,point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).g,point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).r);

        OpenCVPointCloudColor.at<cv::Vec3b>(cv::Point(x,y)) = color;
    }
}

cv::imshow("view 2", OpenCVPointCloudColor);
cv::waitKey(30);

Anzeige das Bild oben sichergestellt dass mir die Farben ordnungsgemäß extrahiert werden (das Bild ist im Vergleich mit dem Auge mit dem raw-Bild). Dann möchte ich Sie zu konvertieren zurück zu einer Punktewolke:

pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGB>);

for(int y=0;y<OpenCVPointCloudColor.rows;y++)
{
    for(int x=0;x<OpenCVPointCloudColor.cols;x++)
    {
        pcl::PointXYZRGB point;
        point.x = OpencVPointCloud.at<double>(0,y*OpenCVPointCloudColor.cols+x);
        point.y = OpencVPointCloud.at<double>(1,y*OpenCVPointCloudColor.cols+x);
        point.z = OpencVPointCloud.at<double>(2,y*OpenCVPointCloudColor.cols+x);

            cv::Vec3b color = OpenCVPointCloudColor.at<cv::Vec3b>(cv::Point(x,y));
        //Try 1 not working
        //uint8_t r = (color[2]); 
        //uint8_t g = (color[1]);
        //uint8_t b = (color[0]);

        //Try 2 not working
        //point.r = color[2];
        //point.g = color[1];
        //point.b = color[0];

        //Try 3 not working
        //uint8_t r = (color.val[2]);
        //uint8_t g = (color.val[1]);
        //uint8_t b = (color.val[0]);

        //test working WHY DO THE ABOVE CODES NOT WORK :/
        uint8_t r = 255; 
        uint8_t g = 0;
        uint8_t b = 0;
        int32_t rgb = (r << 16) | (g << 8) | b;
        point.rgb = *reinterpret_cast<float*>(&rgb);

        point_cloud_ptr -> points.push_back(point);
    }
} 

Kann jemand erklären, warum die Werte explizit angegeben 255,0,0 Farben alles rot. Aber wenn ich wählen Sie die Ausgabe von Farb-Bild, die Wolke ist falsch gefärbt?

Gestolpert diese, ich kann nicht sehen, welchen Unterschied mein code hat die anderen, als dann die cloud-Typ ist anders?

update

Lesen diese Diskussion über PCL endete bei mir der Wechsel zu xyzrgba (auch erwähnt auf stackoverflow). Der code, den ich versuchte dann bei der Konvertierung zurück ist:

point.b = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[0];
point.g = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[1];
point.r = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[2];
point.a = 255;

Die resultierende Farbe cloud ist anders als diejenigen, die erstellt, in XYZRGB, aber immer noch falsch :/WTF?

Extra

Selbst wenn ich die Kraft eine rote Farbe in alle Punkte OpenCVPointCloudColor mit cvCloudColor.at<cv::Vec3f>(x,y) = cv::Vec3f(0,0,255); dann das Lesen von OpenCVPointCloudColor noch schafft falsche Farbe Informationen in der pcl-cloud.

  • In dem Beispiel, Sie scheinen zum speichern der Punkte in OpenCVPointCloudColor beim Versuch, Sie zu Lesen von colorImage. Sind dies die gleichen?
  • ja sind Sie, ich werde zu aktualisieren, die Frage ist nun also haben Sie die gleichen Variablennamen. (nur hatte Sie in zwei Funktionsaufrufe).
  • (irrelevant vom code oben), Wenn Sie versuchen, Sie zu Lesen, aus einem Bild geladen mit OpenCV, beachten Sie, dass die Standard-Farbe-system der BGR statt RGB. Das könnte Einfluss auf die Farben.
  • ja, das ist richtig. Aber das sollte keinen Einfluss auf den code oben?
InformationsquelleAutor JTIM | 2017-01-23



One Reply
  1. 1

    Bin ich mir fast sicher, dass es ein Fehler irgendwo im code um diese Funktionen. Ich habe versucht, einfache Beispiel, nach Ihrem Paradigma, und es funktioniert perfekt (PCL 1.8 gebaut aus Quellen, OpenCV 3.1 gebaut aus Quellen, g++ 5.x oder g++ 6.x, Ubuntu 16.10):

    #include <pcl/visualization/cloud_viewer.h>
    
    #include <opencv2/core.hpp>
    #include <opencv2/imgproc.hpp>
    #include <opencv2/highgui.hpp>
    
    void draw_cloud(
        const std::string &text,
        const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud)
    {
        pcl::visualization::CloudViewer viewer(text);
        viewer.showCloud(cloud);
        while (!viewer.wasStopped())
        {
        }
    }
    
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr img_to_cloud(
            const cv::Mat& image,
            const cv::Mat &coords)
    {
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    
        for (int y=0;y<image.rows;y++)
        {
            for (int x=0;x<image.cols;x++)
            {
                pcl::PointXYZRGB point;
                point.x = coords.at<double>(0,y*image.cols+x);
                point.y = coords.at<double>(1,y*image.cols+x);
                point.z = coords.at<double>(2,y*image.cols+x);
    
                cv::Vec3b color = image.at<cv::Vec3b>(cv::Point(x,y));
                uint8_t r = (color[2]);
                uint8_t g = (color[1]);
                uint8_t b = (color[0]);
    
                int32_t rgb = (r << 16) | (g << 8) | b;
                point.rgb = *reinterpret_cast<float*>(&rgb);
    
                cloud->points.push_back(point);
            }
        }
        return cloud;
    }
    
    void cloud_to_img(
            const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud,
            cv::Mat &coords,
            cv::Mat &image)
    {
        coords = cv::Mat(3, cloud->points.size(), CV_64FC1);
        image = cv::Mat(480, 640, CV_8UC3);
        for(int y=0;y<image.rows;y++)
        {
            for(int x=0;x<image.cols;x++)
            {
                coords.at<double>(0,y*image.cols+x) = cloud->points.at(y*image.cols+x).x;
                coords.at<double>(1,y*image.cols+x) = cloud->points.at(y*image.cols+x).y;
                coords.at<double>(2,y*image.cols+x) = cloud->points.at(y*image.cols+x).z;
    
                cv::Vec3b color = cv::Vec3b(
                        cloud->points.at(y*image.cols+x).b,
                        cloud->points.at(y*image.cols+x).g,
                        cloud->points.at(y*image.cols+x).r);
    
                image.at<cv::Vec3b>(cv::Point(x,y)) = color;
            }
        }
    }
    
    int main(int argc, char *argv[])
    {
        cv::Mat image = cv::imread("test.png");
        cv::resize(image, image, cv::Size(640, 480));
        cv::imshow("initial", image);
    
        cv::Mat coords(3, image.cols * image.rows, CV_64FC1);
        for (int col = 0; col < coords.cols; ++col)
        {
            coords.at<double>(0, col) = col % image.cols;
            coords.at<double>(1, col) = col / image.cols;
            coords.at<double>(2, col) = 10;
        }
    
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = img_to_cloud(image, coords);
        draw_cloud("points", cloud);
    
        cloud_to_img(cloud, coords, image);
        cv::imshow("returned", image);
    
        cv::waitKey();
        return 0;
    }

    „initial“ und „zurück“ – Bilder sind völlig identisch. In der PCL-viewer sehe ich mein Bild als Punkt-Wolke, natürlich, mit z = 10, weil ich es hardcoded. Sie sollte möglicherweise verwenden Sie Mausrad um zu verkleinern und sehen das gesamte image.

    Für dieses Beispiel ausführen, sollten Sie die Datei mit dem Namen ‚test.png “ in Ihrem Arbeitsverzeichnis.

    Tut mir Leid für fest programmierte Eingabe-Datei name und Größe ändern, um die Feste Auflösung.

    Probieren Sie es aus, und wenn es in Ihrem system, versuchen Sie, finden Sie Fehler in Ihrem code. Wenn es nicht funktioniert, möglicherweise Ihre PCL-bauen ist zu alt oder sogar kaputt.

    • Danke, ich werde versuchen, dies morgen. Ich jedoch habe (pcl 1.7, Ubuntu 14.04, ROS indigo komplett, d.h. opencv 2.4). Hatte mehrere Probleme mit pcl-1,8 und opencv 3.1 und ROS. Ich war in der Lage zu laufen Pcl-Knoten und opencv Knoten, aber nichts in Verbindung für einige ungerade Grund. Dies war also der neue frische Installation. Trotzdem vielen Dank ich werde den code testen, um zu sehen, ob ich verrückt für ein Fehler.
    • Etwas muss gebrochen werden, in meiner Konfiguration. Danke für die Klarstellung es. Ich markiere ihn als gelöst, indem du

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.