2017-01-23 69 views
2

rcl情報をpcl形式からcv :: Matに、そしてpclに戻そうとしています。私はconvert mat to pointcloudをstackoverflowで見つけました。cv :: Matを色付きのpcl :: pointcloudに変換する方法

更新

コードIは、従って、出発点としてstackoverflowの上に見出されるコードを使用しました。

//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); 

色は(画像は原画像と目で比較されて)正しく抽出されていることを私に確実に上の画像を表示:そして今、次があります。

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); 
    } 
} 

明示的に255,0,0の値を明示的に指定した理由は誰でも説明できますか?しかし、私がカラー画像から出力を選択すると、クラウドは間違って色付けされていますか?

つまずいたthis、私のコードは、雲の種類以外の違いが表示されませんか? PCLにthis説明を読む

更新

は、私は(もstackoverflowに言及した)xyzrgbaへの切り替えで終わりました。バック変換するとき、私はその後、試したコードは次のとおりです。

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; 

結果の色の雲はXYZRGBで作成されたものとは異なっているが、まだ間違っている:/ WTF?

エクストラ

は私がOpenCVPointCloudColorからの読み取り、その後cvCloudColor.at<cv::Vec3f>(x,y) = cv::Vec3f(0,0,255);を使用して、すべての点OpenCVPointCloudColorに赤い色を強制場合でも、まだPCLクラウドで間違った色情報を作成します。

+1

この例では、 'OpenCVPointCloudColor'にポイントを保存しているように見えますが、' colorImage'からポイントを読み取ろうとしています。それらは同じですか? – iamai

+0

@iamaiはい、彼らは同じ変数名を持つように今質問を更新します。 (ちょうど2つの関数呼び出しでそれらを持っていた)。 – JTIM

+0

(上記のコードとは関係ありません)OpenCVを使用して読み込まれた画像からそれらを読み取ろうとする場合、デフォルトのカラーシステムはRGBではなくBGRです。それは色に影響するかもしれません。 – ilke444

答えて

1

これらの機能のコードのどこかにバグがあることはほとんど確信しています。 (ソースから構築されたOpenCVの3.1、G ++ 5.xまたはグラムはUbuntuの16.10、6.xの++、ソースから構築されたPCL 1.8)私はあなたのパラダイム以下、簡単な例を試みたが、それは完璧に動作します:

#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; 
} 

"初期" 「返された」画像はまったく同じです。 PCLのビューアでは、画像をポイント・クラウドと見なします。もちろん、z = 10の場合は、ハード・コード化しています。マウスホイールを使用して、ズームアウトして画像全体を表示する必要があります。

この例を実行するには、作業ディレクトリに 'test.png'という名前のファイルが必要です。

ハードコードされた入力ファイル名はごめんね、固定解像度にリサイズしてください。

お試しください。システムで動作する場合は、コードにバグを見つけてください。それが動作しない場合は、PCLビルドが古すぎたり、壊れている可能性があります。

+0

ありがとうございます私は明日これを試してみます。しかし、私は持っている(pcl 1.7、Ubuntu 14.04、ROS indigo full、すなわちopencv 2.4)。 pcl 1.8とopencv 3.1とROSに関する複数の問題がありました。私はPclノードとopencvノードを実行することができましたが、何らかの奇妙な理由のために何も一緒に何もしませんでした。これは新しく新しくインストールされたものです。それにもかかわらず、おかげさまで私はあなたのコードをテストして、私が大失敗をしたかどうかを確認します。 – JTIM

+0

私の設定で何かが壊れている必要があります。それを明確にしていただきありがとうございます。私はそれをあなたが解決したものとしてマークします – JTIM

関連する問題