ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Probably late, but for the record:

The topic that you are subscribing to has 32 bit depth - which can not be visualized by image_viewer. Try one of the other depth topics - I cannot recall right now which one could be seen. Try rostopic list | grep depth , rostopic list lists all of the published topics, while grep depth filters the output so that you only see the ones that have the word "depth" in them.

Despite not being able to see the that topic you are subscribing to, you can use it in any of your nodes. Or maybe in RVIZ if you want to see the 3d points.

Here is one example node that subscribes to /camera/depth_registered/hw_registered/image_rect_raw and /camera/rgb/image_color from a Turtlebot 1. It then saves the depth images as 16 bit png and tiff :

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

/*Este es un nodo de ROS Hydro para guardar imagenes de /camera/depth_registered/image_raw
 * y de /camera/rgb/color/image_raw de un Turtlebot1 para luego procesarlas con otro programa. 
 * Las de profundidad se guardan como unsigned int de 16 bits 
 * y 1 canal, las de color se guardan como unsigned int de 8 bits en 3 canales.
 * Se guardan adonde se corra el nodo.
 * ---------------------------------------------------------
 * Creado por Fabricio Emder y Pablo Aguado en el 2014 */


volatile int cnt = 0;       //Contador para ponerle nombre a las imagenes.

void retorno_depth(const sensor_msgs::Image& msg)
{
    cv_bridge::CvImagePtr img_ptr;
    try{
        img_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::TYPE_16UC1);
    }
    catch (cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception:  %s", e.what());
        return;
    }

    cv::Mat &mat = img_ptr->image;

    char file1[100];
    char file2[100];
    cnt++;                                          //each time an image comes increment cnt
    sprintf(file1,"imagen%d_depth.png",cnt);        //Solo guarda en 16 bits si es png o tiff 
    sprintf(file2,"imagen%d_depth.tiff",cnt);        

    std::vector<int> parametros;                    //Objeto vector de C++.
    parametros.push_back(CV_IMWRITE_PNG_COMPRESSION);
    parametros.push_back(0);

    imwrite(file1,mat,parametros);
    imwrite(file2,mat);

    ROS_INFO_STREAM("Imagen de profundidad guardada\n");
}

void retorno_color(const sensor_msgs::Image& msg)
{
    cv_bridge::CvImagePtr img_ptr;
    try{
        img_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::TYPE_8UC3);
    }
    catch (cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception:  %s", e.what());
        return;
    }

    cv::Mat &mat = img_ptr->image;

    char file1[100];
    char file2[100];
    //cnt++;                                        //each time an image comes increment cnt
    sprintf(file1,"imagen%d_color.png",cnt);        //Solo guarda en 16 bits si es png o tiff 
    sprintf(file2,"imagen%d_color.tiff",cnt);        

    std::vector<int> parametros;                    //Objeto vector de C++.
    parametros.push_back(CV_IMWRITE_PNG_COMPRESSION);
    parametros.push_back(0);

    imwrite(file1,mat,parametros);
    imwrite(file2,mat);

    ROS_INFO_STREAM("Imagen color guardada\n");
}


int main(int argc, char **argv)
{
    //initialize the ROS system and become a node.
    ros::init(argc, argv, "guardar_imagenes");
    ros::NodeHandle nh;


    //image_transport::ImageTransport it(nh);
    ros::Subscriber suscriptor_depth;
    ros::Subscriber suscriptor_color;

    suscriptor_depth = nh.subscribe("/camera/depth_registered/hw_registered/image_rect_raw", 1, &retorno_depth);
    suscriptor_color = nh.subscribe("/camera/rgb/image_color", 1, &retorno_color);

    ROS_INFO_STREAM("Apretar enter para guardar las imagenes\n");

    while(ros::ok())
    {
        while (1)
        {
            if ('\n' == getchar())
               break;
        }

        ros::spinOnce();    //Le da el control a los handlers
    }
    return 0;
}

Probably late, but for the record:

The topic that you are subscribing to has 32 bit depth - which can not be visualized by image_viewer. image_viewer. Try one of the other depth topics - I cannot recall right now which one could be seen. Try rostopic list | grep depth , rostopic list lists all of the published topics, while grep depth filters the output so that you only see the ones that have the word "depth" in them.

Despite not being able to see the that topic you are subscribing to, you can use it in any of your nodes. Or maybe in RVIZ if you want to see the 3d points.

Here is one example node that subscribes to /camera/depth_registered/hw_registered/image_rect_raw /camera/depth_registered/hw_registered/image_rect_raw and /camera/rgb/image_color /camera/rgb/image_color from a Turtlebot 1. It then saves the depth images as 16 bit png and tiff :

Source and more

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

/*Este /* Este es un nodo de ROS Hydro Indigo para guardar imagenes de /camera/depth_registered/image_raw
/camera/depth_registered/image_rect_raw
 * y de /camera/rgb/color/image_raw /camera/rgb/color/image_rect_raw de un Turtlebot1 para luego procesarlas con otro programa. 
 * Las de profundidad se guardan como unsigned int de 16 bits 
 * y 1 canal, las de color se guardan como unsigned int de 8 bits en 3 canales.
 * Se guardan adonde se corra utiliza un suscriptor sincronizado para guardar el nodo.
par de imagenes que estén más
 * cercanas en el tiempo.
 * LAS IMAGENES SE GUARDAN ADONDE SE EJECUTE EL NODO.
 * ---------------------------------------------------------
 * Creado por Fabricio Emder y Pablo Aguado en el 2014 2016 */


volatile /* This is a ROS Indigo node for saving Turtlebot images from the /camera/depth_registered/image_rect_raw
 * and /camera/rgb/color/image_rect_raw topics, for further processing outside of the program. 
 * Depth images are saved as 1 channel 16 bit unsigned int PNGs (CV_16UC1), and 
 * RGB images are saved as 3 channel 8 bit unsigned int PNGs (CV_8UC3).
 * A synchronized subscriber is used, for saving the pair of images that are most closer in time.
 * THE IMAGES ARE SAVED WHEREVER THE NODE IS RUN.
 * Created by Fabricio Emder and Pablo Aguado - 2016
 * */

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>    // OpenCV
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>


/* La política de sincronización exacta NO FUNCIONA para los topics seleccionados, ya 
 * que la Kinect o sus drivers no los están publicando con la misma marca temporal.
 * Ver más en http://wiki.ros.org/message_filters 
 * 
 * Exact sychronization policy IS NOT WORKING for the topics used, because the kinect
 * is not publishing them with the same timestamp. 
 * See more in http://wiki.ros.org/message_filters  */

//#define EXACT
#define APPROXIMATE


#ifdef EXACT
#include <message_filters/sync_policies/exact_time.h>
#endif
#ifdef APPROXIMATE
#include <message_filters/sync_policies/approximate_time.h>
#endif



using namespace std;
//using namespace sensor_msgs;
using namespace message_filters;


// Contador para la numeración de los archivos.
// Counter for filenames.
unsigned int cnt = 0;       //Contador para ponerle nombre a las imagenes.

1;



// Handler / callback
void retorno_depth(const sensor_msgs::Image& msg)
callback( const sensor_msgs::ImageConstPtr& msg_rgb , const sensor_msgs::ImageConstPtr& msg_depth )
{
        //ROS_INFO_STREAM("Adentro del callback\n");
      cv_bridge::CvImagePtr img_ptr;
img_ptr_rgb;
        cv_bridge::CvImagePtr img_ptr_depth;
    try{
        img_ptr img_ptr_depth = cv_bridge::toCvCopy(msg, cv_bridge::toCvCopy(*msg_depth, sensor_msgs::image_encodings::TYPE_16UC1);
    }
    catch (cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception:  %s", e.what());
        return;
    }

    cv::Mat &mat     try{
        img_ptr_rgb = img_ptr->image;

    char file1[100];
    char file2[100];
    cnt++;                                          //each time an image comes increment cnt
    sprintf(file1,"imagen%d_depth.png",cnt);        //Solo guarda en 16 bits si es png o tiff 
    sprintf(file2,"imagen%d_depth.tiff",cnt);        

    std::vector<int> parametros;                    //Objeto vector de C++.
    parametros.push_back(CV_IMWRITE_PNG_COMPRESSION);
    parametros.push_back(0);

    imwrite(file1,mat,parametros);
    imwrite(file2,mat);

    ROS_INFO_STREAM("Imagen de profundidad guardada\n");
}

void retorno_color(const sensor_msgs::Image& msg)
{
    cv_bridge::CvImagePtr img_ptr;
    try{
        img_ptr = cv_bridge::toCvCopy(msg, cv_bridge::toCvCopy(*msg_rgb, sensor_msgs::image_encodings::TYPE_8UC3);
    }
    catch (cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception:  %s", e.what());
        return;
    }

    cv::Mat &mat cv::Mat& mat_depth = img_ptr->image;

img_ptr_depth->image;
        cv::Mat& mat_rgb = img_ptr_rgb->image;

        char file1[100];
file_rgb[100];
        char file2[100];
    //cnt++;                                        //each time an image comes increment cnt
    sprintf(file1,"imagen%d_color.png",cnt);        //Solo guarda en 16 bits si es png o tiff 
    sprintf(file2,"imagen%d_color.tiff",cnt);        

    std::vector<int> parametros;                    //Objeto vector de C++.
    parametros.push_back(CV_IMWRITE_PNG_COMPRESSION);
    parametros.push_back(0);

    imwrite(file1,mat,parametros);
    imwrite(file2,mat);

    ROS_INFO_STREAM("Imagen color guardada\n");
file_depth[100];

        sprintf( file_rgb, "%04d_rgb.png", cnt );
        sprintf( file_depth, "%04d_depth.png", cnt );

        vector<int> png_parameters;
        png_parameters.push_back( CV_IMWRITE_PNG_COMPRESSION );
        /* We save with no compression for faster processing.
         * Guardamos PNG sin compresión para menor retardo. */
        png_parameters.push_back( 9 ); 

        cv::imwrite( file_rgb , mat_rgb, png_parameters );
        cv::imwrite( file_depth, mat_depth, png_parameters );

        ROS_INFO_STREAM(cnt << "\n");
        ROS_INFO_STREAM("Imágenes guardadas - "
                        "Images saved\n");

        cnt++;

}
 

int main(int argc, char **argv)
char** argv)
{
    //initialize // Initialize the ROS system and become a node.
   ros::init(argc, argv, "guardar_imagenes");
   ros::NodeHandle nh;


    //image_transport::ImageTransport it(nh);
    ros::Subscriber suscriptor_depth;
    ros::Subscriber suscriptor_color;

    suscriptor_depth = nh.subscribe("/camera/depth_registered/hw_registered/image_rect_raw", 1, &retorno_depth);
    suscriptor_color = nh.subscribe("/camera/rgb/image_color", 1, &retorno_color);

    ROS_INFO_STREAM("Apretar enter message_filters::Subscriber<sensor_msgs::Image> subscriber_depth( nh , "/camera/depth_registered/hw_registered/image_rect_raw" , 1 );
    message_filters::Subscriber<sensor_msgs::Image> subscriber_rgb( nh , "/camera/rgb/image_rect_color" , 1 );


#ifdef EXACT
    typedef sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image> MySyncPolicy;
#endif
#ifdef APPROXIMATE
    typedef sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image> MySyncPolicy;
#endif


  // ExactTime or ApproximateTime take a queue size as its constructor argument, hence MySyncPolicy(10)
  Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), subscriber_rgb, subscriber_depth );
  sync.registerCallback(boost::bind(&callback, _1, _2));


    while(ros::ok())
    {
        char c;

        ROS_INFO_STREAM("\nIngrese 'a' para guardar las imagenes\n");

    while(ros::ok())
un par de imágenes o 'b' para guardar 300 imágenes\n"
                        "Enter 'a' to save a pair of images or 'b' to automatically save 300 images\n");
        cin.get(c);
        cin.ignore();
        c = tolower(c);
        ROS_INFO_STREAM("You entered " << c << "\n");

        if( c == 'a' )
        {
        while (1)
        {
            if ('\n' == getchar())
               break;
        }

        ros::spinOnce();    //Le da         /* Le damos el control a los handlers
la función callback cuando haya imágenes.
                * We give control to the callback function.*/
                ros::spinOnce();    
        }
 
        else if( c == 'b' )
        {
            unsigned int cnt_init = cnt;
            while( cnt - cnt_init < 300 )
            {
                ros::spinOnce();
            }
        }

        else break;

    }
    ROS_INFO_STREAM("Cerrando nodo\nClosing node\n");

  return 0;
}