Ask Your Question
5

Publishing an image from disk

asked 2011-10-14 01:58:24 -0500

quimnuss gravatar image

Hi!

What's te best way to solely stream an image from disk? How do I convert from cv::Mat to proper ROS image message?

The relevant snippet would be:

cv_bridge::CvImagePtr cv_ptr;
cv_ptr->image = cv::imread(this->filename_);
image_pub_.publish(cv_ptr->toImageMsg());

How can the cv_bridge::CvImagePtr be initialized? The command above aborts at runtime as one would expect if the constructor requires something else. The error:

iri_simple_perception: /usr/include/boost/smart_ptr/shared_ptr.hpp:418: T* boost::shared_ptr< <template-parameter-1-1> >::operator->() const [with T = cv_bridge::CvImage]: Assertion `px != 0' failed.

Having a look at toCvCopyImpl seems a bit of an overkill ( http://www.ros.org/doc/api/cv_bridge/html/c++/cv__bridge_8cpp_source.html#l00200 ). So, any suggestions?

edit retag flag offensive close merge delete

6 Answers

Sort by ยป oldest newest most voted
4

answered 2011-10-14 03:20:28 -0500

cv_bridge::CvImagePtr is a pointer type that points to NULL by default. You have to allocate storage before you can actually use it, and the boost assertion catches the null pointer dereference.

Correct would be either something like

cv_bridge::CvImagePtr cv_ptr(new cv_bridge::CvImage);

or

cv_bridge::CvImagePtr cv_ptr;
cv_ptr.reset (new cv_bridge::CvImage);

As a rule of thumb, every ROS type xxxPtr is a pointer type for xxx.

edit flag offensive delete link more

Comments

Yes, that looks more like what I was thinking of. There's, however, something I'm still missing: a fatal is reported by the publish(cv_ptr->toImageMsg()). 'Call to publish() on an invalid image_transport::Publisher'. I've tried both filling the header and encoding as well as leaving them blank.
quimnuss gravatar imagequimnuss ( 2011-10-14 03:30:35 -0500 )edit
I'll mark the question as unresolved, in case somebody steps up to this alternative approach.
quimnuss gravatar imagequimnuss ( 2011-10-16 22:38:55 -0500 )edit
1
Did you advertise the publisher properly? It is not sufficient just to declare a Publisher image_pub_, you must call ImageTransport::advertise() or something similar to get a valid Publisher object.
roehling gravatar imageroehling ( 2011-10-17 00:46:14 -0500 )edit
Yes, I did. image_transport::Publisher pub = imgtransport_.advertise("disk/image", 1);
quimnuss gravatar imagequimnuss ( 2011-10-18 00:45:43 -0500 )edit
There was a bug, it perfectly works now.
quimnuss gravatar imagequimnuss ( 2011-10-24 05:23:19 -0500 )edit
2

answered 2014-02-13 12:31:40 -0500

TFinleyosu gravatar image

updated 2014-02-13 12:34:20 -0500

Here is my example that I got working in Hydro

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

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;

    cv_bridge::CvImage cv_image;
    cv_image.image = cv::imread("/home/taylor/Pictures/face.jpg",CV_LOAD_IMAGE_COLOR);
    cv_image.encoding = "bgr8";
    sensor_msgs::Image ros_image;
    cv_image.toImageMsg(ros_image);

  ros::Publisher pub = nh.advertise<sensor_msgs::Image>("/static_image", 1);
  ros::Rate loop_rate(5);

  while (nh.ok()) 
  {
    pub.publish(ros_image);
    loop_rate.sleep();
  }
}
edit flag offensive delete link more

Comments

Thank you very much! This code is excellent!

sam gravatar imagesam ( 2015-07-13 01:10:40 -0500 )edit
1

answered 2011-10-14 02:19:12 -0500

John Hoare gravatar image

I've used the gscam driver to publish saved video files as a camera, and you can also use it to do snapshots, or really anything that gstreamer supports. You would be able to do what you want using this driver.

edit flag offensive delete link more

Comments

Would it work with a single still jpg image?
quimnuss gravatar imagequimnuss ( 2011-10-14 02:23:25 -0500 )edit
Sure, however you'll have to adjust the gstreamer pipeline to constantly publish the same image.
John Hoare gravatar imageJohn Hoare ( 2011-10-14 02:32:54 -0500 )edit
Looks good. Although I am not familiar with the syntax, I've managed to publish the image through gst-launch. I'll look into it to port it to the gscam config export definition. Or you do know what that would be?
quimnuss gravatar imagequimnuss ( 2011-10-14 02:36:31 -0500 )edit
It will be the same syntax as the gst-launch command. Store the command you used to the gst-launch (without the sink) to the environment variable GSCAM_CONFIG. See the wiki for details.
John Hoare gravatar imageJohn Hoare ( 2011-10-14 02:40:57 -0500 )edit
Indeed it works! Thanks!
quimnuss gravatar imagequimnuss ( 2011-10-14 02:48:24 -0500 )edit
0

answered 2012-06-13 00:21:11 -0500

tayyab gravatar image

updated 2012-06-13 00:22:19 -0500

@quimnuss you can do something like

cv::Mat image; // fill in image with your image data

CvImagePtr img_ptr;

image.copyto(img_ptr->image);

link text

edit flag offensive delete link more
0

answered 2014-12-19 08:14:11 -0500

lucasw gravatar image

This takes an image file name from a command line and publishes at desired rate:

https://github.com/lucasw/vimjay/blob...

Making it take the filename from a rostopic could be nice.

#!/usr/bin/env python
# Lucas Walter
# GNU GPLv3
# Load an image from disk and publish it repeatedly

import cv2
import numpy as np
import rospy
import sys
from sensor_msgs.msg import Image

if __name__ == '__main__': 
    rospy.init_node('image_publish')

    name = sys.argv[1]
    image = cv2.imread(name)
    #cv2.imshow("im", image)
    #cv2.waitKey(5)

    hz = rospy.get_param("~rate", 1)
    rate = rospy.Rate(hz)

    pub = rospy.Publisher('image', Image, queue_size=1)

    msg = Image()
    msg.header.stamp = rospy.Time.now()
    msg.encoding = 'bgr8'
    msg.height = image.shape[0]
    msg.width = image.shape[1]
    msg.step = image.shape[1] * 3
    msg.data = image.tostring()
    pub.publish(msg)

    while not rospy.is_shutdown():
        pub.publish(msg)
        rate.sleep()
edit flag offensive delete link more
0

answered 2011-10-14 03:13:25 -0500

quimnuss gravatar image

The solution from John Hoare works. Although the filename has to be established within an environment variable, which might be inconvinient. I do have a node that sets the filename through dynamic_reconfigure and reads the image with imread. The sole thing missing is how a cv::Mat can be transformed to a publishable image ros message. The ros wiki explains how to do so once we have a cv_bridge::CvImagePtr but it does not explain how to construct the CvImagePtr given a cv::Mat.

edit flag offensive delete link more

Comments

how can I convert from CvImagePtr to cv::Mat

Robot gravatar imageRobot ( 2014-10-07 03:49:15 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2011-10-14 01:58:24 -0500

Seen: 5,577 times

Last updated: Dec 19 '14