Ask Your Question
2

Display in 3D at set of binary labelled cv::Mat images... somekind of slices of a 3D object

asked 2012-10-12 07:50:46 -0500

alexcv gravatar image

Hi all,

I would like to display for demonstration purpose a set of cv::Mat that are actually the slices of a 3D shape. Each slice is a labbelled blob image of the same size. PointCloud library sounds nice, however, can we use it from OpenCV ? i also saw this discussion here http://opencv.willowgarage.com/wiki/OpenCVandPCL but no other information. Also an example from martin Peris seems interesing http://blog.martinperis.com/2012/01/3d-reconstruction-with-opencv-and-point.html but is a hand made data transfert from one lib to the other. Then, is there an "official" compatibility porting tool to display such 3D volumes in a simple way for free visualisation & object observation ?

Thanks people

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
1

answered 2012-10-12 10:48:14 -0500

Martin Peris gravatar image

As far as I know, binary compatibility between OpenCV and PCL data structures is not always possible, so unless somebody came up recently with an "automagic" way to do it, you will have to make it happen manually.

You can also consider other possibilities for visualization, like OpenGL for instance.

edit flag offensive delete link more

Comments

Hi, thank you for your answer. Yes, OpenGL would definitely be a solution, but i was curious about the PCL links with OpenCV as shown on you blog (nice job&presentation) Thanks Alex

alexcv gravatar imagealexcv ( 2012-10-17 07:30:56 -0500 )edit
1

answered 2012-10-21 08:44:28 -0500

alexcv gravatar image

Hi all, Thank you Martins for recommendations. I answer my own question for those who are interested by the topic:

You can create in few lines a 3D viewer on which you can add point clouds and shapes : Please refer to the official tutorials for details http://pointclouds.org/documentation/tutorials/pcl_visualizer.php

/* generic 3D viewer display, similar to the official tutorials. changes added : camera setup :

_ use the viewer->resetCameraViewpoint("Considered blobs"); to point to the middle of your point cloud

_ use viewer->setCameraPosition (cameraPoxitionX, cameraPoxitionY, cameraPoxitionZ, viewX, viewY, viewZ) // to set the camera position and its directions

*/

Consider the following includes... first check your system configuration (add pcl library and dependencies),

#include <pcl/common/common_headers.h>
#include <pcl/point_cloud.h>
#include <pcl/impl/point_types.hpp>>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

// This method display 3D COLOURED points

boost::shared_ptr<pcl::visualization::PCLVisualizer> createVisualizer (pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{

    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
    viewer->setBackgroundColor (0, 0, 0);
    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
    viewer->addPointCloud<pcl::PointXYZRGB> (cloud, rgb, "myPoints");
    viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "myPoints");
    viewer->addCoordinateSystem ( 1.0 );
    viewer->initCameraParameters ();
    viewer->resetCameraViewpoint("myPoints"); // camera points to the center of the point cloud
    viewer->setCameraPosition   (   camXPos, camXPos, camXPos, // camera position

            0, 1, 0 // camera direction to cloud center
            );  // ... then camera faces the point cloud
    return (viewer);
}

Once prepared and considering a cv::Mat image "colorImage" and a binary mask "areas" , add points to your point cloud and display it : ... take care of X&Y inversions (take into account the top left (0,0) of cv::Mat reference points) ...HINT, the Z axis can be used as the temporal information like in this exemple (time is refered as "frameIndex" here

Allocate your point cloud :

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

Fill the point cloud with the localizes and coloured segmented blob points

        for(int y=0;y<colorImage.rows;++y)
            for(int x=0;x<colorImage.cols;++x)
            {
                // get pixel data
                cv::Scalar maskPoint = areas.at<unsigned char>(cv::Point2d(x,y));
                cv::Vec3b colorPoint = colorImage.at<cv::Vec3b>(cv::Point2d(x,y));

                if (maskPoint[0])
                {
                    //std::cout<<"New point (x,y,z) = "<<x<<", "<<y<<", "<<frameIndex
                    //      <<" // (r,g,b) = "<<(int)pr<<", "<<(int)pg<<", "<<(int)pb<<std::endl;

                    //Insert info into point cloud structure
                    pcl::PointXYZRGB point;
                    point.x = -x;
                    point.y = -y;
                    point.z = frameIndex;
                    uint32_t rgb = (static_cast<uint32_t>(colorPoint.val[2]) << 16 |
                            static_cast<uint32_t>(colorPoint.val[1]) << 8 | static_cast<uint32_t>(colorPoint.val[0]));
                    point.rgb = *reinterpret_cast<float*>(&rgb);
                    point_cloud_ptr->points.push_back (point);
                }
            }

Finally, when the cloud is ready, display it by calling the first procedure :

... check doc to add any supplementary shape, here, a cude is added (dims are image size*timeLength).

    std::cout<<"Pointcould size : "<<point_cloud_ptr->points.size()<<std::endl;
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = createVisualizer( point_cloud_ptr );
    viewer->addCube (-colorImage.cols, 0, -colorImage.rows, 0, 0, timeLength);
    //Main user ...
(more)
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

Stats

Asked: 2012-10-12 07:50:46 -0500

Seen: 4,767 times

Last updated: Oct 21 '12