ROS Resources: Documentation | Support | Discussion Forum | Service Status | Q&A answers.ros.org
Ask Your Question
0

How to publish images quickly

asked 2015-06-27 14:05:54 -0500

troman gravatar image

updated 2015-06-29 17:12:24 -0500

ROS Indigo, Python, OpenCV (cv_bridge)

I wrote a node that does differential imaging on the webcam feed from a Kinect, but when I publish the final images and try to view them in image_view, the frame rate is really slow. If I instead use cv2.imshow() at the same place I'm publishing, the frame rate is fine. What is causing the the frame rate to be so slow when publishing and viewing with image_view, rather than just viewing through OpenCV?

Here's my publisher setup:

...other code...

image_pub = rospy.Publisher("/motion_image", Image, queue_size=10)

...other code...

try:
        img = bridge.cv2_to_imgmsg(motion_img, "bgr8")
        image_pub.publish(img)
except CvBridgeError, e:
        print e

And my subscriber if helpful:

image_sub = rospy.Subscriber("/camera/rgb/image_color", Image, callback, queue_size=10)

I just want to be able to grab one image at a time so I unregister at each call, when I want another image I resubscribe

def callback(data):
    global camera_img, image_sub

    try:
        bridge = CvBridge()
        camera_img = bridge.imgmsg_to_cv2(data, "bgr8")
        image_sub.unregister()
    except CvBridgeError, e:
        print e

Update: Here's the rest of my code, feel free to comment on other things as well. I'm new to Python and ROS and I want to get better. Sorry it's not posted direct, I was having trouble getting it to format correctly.

http://pastebin.com/RveN6esS

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2015-06-27 15:51:41 -0500

cyborg-x1 gravatar image

updated 2015-06-28 03:46:46 -0500

Keep your connection alive.

Unregistering and registering takes time. At least some milliseconds, it is done by XMLRPC and this means as the name says, parsing an XML message on each side, then opening a port and creating the connection.

(Update:)

more detailed what happens:

First you subscribe:
Node -XMLRPC -> Master (I subscribe topic xyz)
Master -XMLRPC -> Node (There is a publisher X)
Node -XMLRPC-> NodeX (I want topic xyz)
NodeX -XMLRPC-> Node (I opened port Y for you)
Node <-ROSMSG Header-> NodeX:PortY(ROSMSG Header)
NodeX -ROSMSG Binary-> constantly sending when published

Then you unsubscribe:
Node -XMLRPC-> NodeX (I do not want topic xyz anymore)
NodeX -XMLRPC> Node (OK) 
Close connection on PortY (both)
Node -XMLRPC-> Master (I am not interested in xyz anymore)
Master -XMLRPC-> OK

So why don't you just disable the processing in the callback itself instead of resubscribing when you do not want to have images?

Like

void callback(...)
{
  if(image_processing_enable) 
  {
   .... Save your image, processing ... what ever ...
   image_processing_enable=false; // for getting only one image. 
  }
}

Regards,

Christian

edit flag offensive delete link more

Comments

Hi Christian, thanks for the reply. The reason I subscribe like this is so that I can grab a new image at a specific time. I have a loop going were I need to grab two sequential images, and as far as I could tell, that was the only way I could accomplish this.

troman gravatar imagetroman ( 2015-06-27 19:36:39 -0500 )edit

I don't think this is the root of my performance issue though. When I display the image mid loop using opencv, and still subscribing in this way it works fine. The performance issue seems to be coming from publishing lt and viewing it from another node

troman gravatar imagetroman ( 2015-06-27 19:40:08 -0500 )edit

Even if you want this image at a specific time there is no need to resubscribe. You as soon as you want the next image in my approach you do image_processing_enable = true. Then you get your image even closer to the time you want.

cyborg-x1 gravatar imagecyborg-x1 ( 2015-06-28 03:41:33 -0500 )edit

Is this

image_pub = rospy.Publisher("/motion_image", Image, queue_size=10

in the same loop like

try:
        img = bridge.cv2_to_imgmsg(motion_img, "bgr8")
        image_pub.publish(img)
except CvBridgeError, e:
        print e

?

cyborg-x1 gravatar imagecyborg-x1 ( 2015-06-28 03:42:46 -0500 )edit

If yes you would also always recreate your publisher before you publish it which would do almost the same like above with the subscriber master communication, that would lead to a very low frequency

cyborg-x1 gravatar imagecyborg-x1 ( 2015-06-28 03:43:40 -0500 )edit

The publisher is created outside of the loop, and is told to publish inside the loop. The subscriber is created outside the loop, subscribed outside to initialize the first image, and then resubscribed in the loop to get the next image.

troman gravatar imagetroman ( 2015-06-28 08:20:08 -0500 )edit

I haven't been able to try your suggestion yet but as soon as I can I will. Then I'll update here. Thanks for the help!

troman gravatar imagetroman ( 2015-06-28 08:21:55 -0500 )edit

You could also consider my answer to this, http://answers.ros.org/question/21235... if the bandwith is critical for you

cyborg-x1 gravatar imagecyborg-x1 ( 2015-06-28 16:53:13 -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

1 follower

Stats

Asked: 2015-06-27 14:05:54 -0500

Seen: 2,491 times

Last updated: Jun 29 '15