0
$\begingroup$

Rosanswers logo

I am following the steps from a Book, for setting up OpenCV to work together ROS through cv_bridge. The book is a bit old, and the original code was a legacy python2 code. The Camera is a Kinect V1.

I used 2to3 to convert it to python3, and after several runs catching the error codes and updating (or trying to) to new OpenCV commands I got it running,

But in the book, says it was supposed to show 3 windows: RBG, Depth and Edges.

When I run my "adjusted" code, it only shows Depth and Edges. Would somebody know what is missing on it?

# This is the original Code

import rospy
import sys
import cv2
import cv2.cv as cv
from sensor_msgs.msg import Image, CameraInfo
from cv_bridge import CvBridge, CvBridgeError
import numpy as np

class cvBridgeDemo():
    def __init__(self):
        self.node_name = "cv_bridge_demo"
        #Initialize the ros node
        rospy.init_node(self.node_name)
                
        # What we do during shutdown
        rospy.on_shutdown(self.cleanup)

        # Create the OpenCV display window for the RGB image
        self.cv_window_name = self.node_name
        cv.NamedWindow(self.cv_window_name, cv.CV_WINDOW_NORMAL)
        cv.MoveWindow(self.cv_window_name, 25, 75)
        
        # And one for the depth image
        cv.NamedWindow("Depth Image", cv.CV_WINDOW_NORMAL)
        cv.MoveWindow("Depth Image", 25, 350)

        # Create the cv_bridge object
        self.bridge = CvBridge()

        # Subscribe to the camera image and depth topics and set
        # the appropriate callbacks
        self.image_sub = rospy.Subscriber("/camera/rgb/image_color", Image,self.image_callback)
        self.depth_sub = rospy.Subscriber("/camera/depth/image_raw", Image,self.depth_callback)
        rospy.loginfo("Waiting for image topics...")

    def image_callback(self, ros_image):

        # Use cv_bridge() to convert the ROS image to OpenCV format
        try:
            frame = self.bridge.imgmsg_to_cv(ros_image, "bgr8")
        except CvBridgeError, e:
            print e
        # Convert the image to a Numpy array since most cv2 functions

        # require Numpy arrays.
        frame = np.array(frame, dtype=np.uint8)

        # Process the frame using the process_image() function
        display_image = self.process_image(frame)

        # Display the image.
        cv2.imshow(self.node_name, display_image)

        # Process any keyboard commands
        self.keystroke = cv.WaitKey(5)
        if 32 <= self.keystroke and self.keystroke < 128:
            cc = chr(self.keystroke).lower()
            if cc == 'q':
                # The user has press the q key, so exit
                rospy.signal_shutdown("User hit q key to quit.")

    def depth_callback(self, ros_image):
        # Use cv_bridge() to convert the ROS image to OpenCV format
        try:
            # The depth image is a single-channel float32 image
            depth_image = self.bridge.imgmsg_to_cv(ros_image,"32FC1")
        except CvBridgeError, e:
            print e
        # Convert the depth image to a Numpy array since most cv2 functions

        # require Numpy arrays.
        depth_array = np.array(depth_image, dtype=np.float32)
        # Normalize the depth image to fall between 0 (black) and 1 (white)
        cv2.normalize(depth_array,depth_array, 0, 1, cv2.NORM_MINMAX)
        # Process the depth image
        depth_display_image = self.process_depth_image(depth_array)

        # Display the result
        cv2.imshow("Depth Image", depth_display_image)


    def process_image(self, frame):
        # Convert to grayscale
        grey = cv2.cvtColor(frame, cv.CV_BGR2GRAY)
        # Blur the image
        grey = cv2.blur(grey, (7, 7))

        # Compute edges using the Canny edge filter
        edges = cv2.Canny(grey, 15.0, 30.0)
        return edges


    def process_depth_image(self, frame):
        # Just return the raw image for this demo
        return frame

    def cleanup(self):
        print "Shutting down vision node."
        cv2.destroyAllWindows()

def main(args):
    try:
        cvBridgeDemo()
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down vision node."
        cv.DestroyAllWindows()


if __name__ == '__main__':
    main(sys.argv)

And this is my roughly adjusted one:

#!/usr/bin/env python

import rospy
import sys
import cv2

from sensor_msgs.msg import Image, CameraInfo
from cv_bridge import CvBridge, CvBridgeError
import numpy as np

class cvBridgeDemo():
    def __init__(self):
        self.node_name = "cv_bridge_node"
        #Initialize the ros node
        rospy.init_node(self.node_name,anonymous=True)
                
        # What we do during shutdown
        rospy.on_shutdown(self.cleanup)

        # Create the OpenCV display window for the RGB image
        self.cv_window_name = self.node_name
        cv2.namedWindow(self.cv_window_name, cv2.WINDOW_NORMAL)
        cv2.moveWindow(self.cv_window_name, 25, 75)
        
        # And one for the depth image
        cv2.namedWindow("Depth Image", cv2.WINDOW_NORMAL)
        cv2.moveWindow("Depth Image", 25, 350)


        # Create the cv_bridge object
        self.bridge = CvBridge()

        # Subscribe to the camera image and depth topics and set
        # the appropriate callbacks
        self.image_sub = rospy.Subscriber("/camera/rgb/image_raw", Image,self.image_callback)
        self.depth_sub = rospy.Subscriber("/camera/depth/image_raw", Image,self.depth_callback)
        rospy.loginfo("Waiting for image topics...")

    def image_callback(self, ros_image):

        # Use cv_bridge() to convert the ROS image to OpenCV format
        try:
            frame = self.bridge.imgmsg_to_cv2(ros_image, "bgr8")#bgr8
        except CvBridgeError as e:
            print(e)
        # Convert the image to a Numpy array since most cv2 functions

        # require Numpy arrays.
        frame = np.array(frame, dtype=np.uint8)

        # Process the frame using the process_image() function
        display_image = self.process_image(frame)

        # Display the image.
        cv2.imshow(self.node_name, display_image)

        # Process any keyboard commands
        self.keystroke = cv2.waitKey(5)
        if 32 <= self.keystroke and self.keystroke < 128:
            cc = chr(self.keystroke).lower()
            if cc == 'q':
                # The user has press the q key, so exit
                rospy.signal_shutdown("User hit q key to quit.")

    def depth_callback(self, ros_image):
        # Use cv_bridge() to convert the ROS image to OpenCV format
        try:
            # The depth image is a single-channel float32 image
            depth_image = self.bridge.imgmsg_to_cv2(ros_image,"32FC1")
        except CvBridgeError as e:
            print(e)
        # Convert the depth image to a Numpy array since most cv2 functions

        # require Numpy arrays.
        depth_array = np.array(depth_image, dtype=np.float32)
        # Normalize the depth image to fall between 0 (black) and 1 (white)
        cv2.normalize(depth_array,depth_array, 0, 1, cv2.NORM_MINMAX)
        # Process the depth image
        depth_display_image = self.process_depth_image(depth_array)

        # Display the result
        cv2.imshow("Depth Image", depth_display_image)


    def process_image(self, frame):
        # Convert to grayscale
        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # Blur the image
        grey = cv2.blur(grey, (7, 7))

        # Compute edges using the Canny edge filter
        edges = cv2.Canny(grey, 15.0, 30.0)
        return edges


    def process_depth_image(self, frame):
        # Just return the raw image for this demo
        return frame

    def cleanup(self):
        print("\n\n\nShutting down vision node.")
        cv2.destroyAllWindows()

def main(args):
    try:
        cvBridgeDemo()
        rospy.spin()
    except KeyboardInterrupt:
        print("\n\n\nShutting down vision node.")
        cv2.destroyAllWindows()


if __name__ == '__main__':
    main(sys.argv)

Originally posted by msantos on ROS Answers with karma: 21 on 2021-02-11

Post score: 0


Original comments

Comment by tryan on 2021-02-12:
I only see two instances each of imshow() and namedWindow() , so I'm not sure why three images are expected--even in the original code. In image_callback(), the BGR image is processed (self.process_image()) into a Canny edge image before display. If you want to see the color image, you'll have to add an extra display.

Comment by msantos on 2021-02-13:
@tryan That was my feeling too. I got reading again a few times to ensure is nothing missing in that example... This is wahy I asked before concluding with my low-level about openCV. Perhaps the editors have missed something. I will try to add it and see how it goes.

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

tryan's comment was actually the answer. I could manage to fix it by adding the following lines:

In the init func:

cv2.namedWindow('Image RBG', cv2.WINDOW_NORMAL)
cv2.moveWindow('Image RBG', 25, 350)

And in the callback func:

cv2.imshow('Image RBG', frame)

Originally posted by msantos with karma: 21 on 2021-02-15

This answer was ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.