Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: 'cv2.cv.cvmat' object has no attribute 'shape' #51

Closed
pirobot opened this issue Dec 1, 2014 · 2 comments
Closed

AttributeError: 'cv2.cv.cvmat' object has no attribute 'shape' #51

pirobot opened this issue Dec 1, 2014 · 2 comments

Comments

@pirobot
Copy link

pirobot commented Dec 1, 2014

I'm not sure if this is an OpenCV issue or a cv_bridge issue but it started with cv_bridge so I'll post here first.

I have a Python ROS node that runs fine under Hydro. When switching to Indigo, the script first threw the error:

AttributeError: CvBridge instance has no attribute 'cv_to_imgmsg'

Somehow I figured out that this has been changed to cv2_to_imgsmsg so I did the substitution. Now I get the error in the subject line:

Traceback (most recent call last):
  File "/home/patrick/catkin_ws/src/rbx1/rbx1_vision/nodes/video2ros.py", line 199, in <module>
    main(sys.argv)
  File "/home/patrick/catkin_ws/src/rbx1/rbx1_vision/nodes/video2ros.py", line 193, in main
    v2r = Video2ROS()
  File "/home/patrick/catkin_ws/src/rbx1/rbx1_vision/nodes/video2ros.py", line 109, in __init__
    image_pub.publish(bridge.cv2_to_imgmsg(cv.fromarray(frame), "bgr8"))
  File "/opt/ros/indigo/lib/python2.7/dist-packages/cv_bridge/core.py", line 161, in cv2_to_imgmsg
    img_msg.height = cvim.shape[0]
AttributeError: 'cv2.cv.cvmat' object has no attribute 'shape'
Shutting down video2ros node.

The script I am trying to run is listed below:

#!/usr/bin/env python

""" video2ros.py - Version 1.1 2013-12-20

    Read in a recorded video file and republish as a ROS Image topic.

    Created for the Pi Robot Project: http://www.pirobot.org
    Copyright (c) 2012 Patrick Goebel.  All rights reserved.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details at:

    http://www.gnu.org/licenses/gpl.html

"""

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

class Video2ROS:
    def __init__(self):
        rospy.init_node('video2ros', anonymous=False)

        rospy.on_shutdown(self.cleanup)

        """ Define the input (path to video file) as a ROS parameter so it
            can be defined in a launch file or on the command line """
        self.input = rospy.get_param("~input", "")

        """ Define the image publisher with generic topic name "output" so that it can
            be remapped in the launch file. """
        image_pub = rospy.Publisher("output", Image, queue_size=30)

        # The target frames per second for the video
        self.fps = rospy.get_param("~fps", 25)

        # Do we restart the video when the end is reached?
        self.loop = rospy.get_param("~loop", False)

        # Start the video paused?
        self.start_paused = rospy.get_param("~start_paused", False)

        # Show text feedback by default?
        self.show_text = rospy.get_param("~show_text", True)

        # Resize the original video?
        self.resize_video = rospy.get_param("~resize_video", False)

        # If self.resize_video is True, set the desired width and height here
        self.resize_width = rospy.get_param("~resize_width", 0)
        self.resize_height = rospy.get_param("~resize_height", 0)

        # Initialize a few variables
        self.paused = self.start_paused
        self.loop_video = True
        self.keystroke = None
        self.restart = False
        self.last_frame = None

        # Initialize the text font
        font_face = cv2.FONT_HERSHEY_SIMPLEX
        font_scale = 0.5

        # Define the capture object as pointing to the input file
        self.capture = cv2.VideoCapture(self.input)

        # Get the original frames per second
        fps = self.capture.get(cv.CV_CAP_PROP_FPS)

        # Get the original frame size
        self.frame_size = (self.capture.get(cv.CV_CAP_PROP_FRAME_HEIGHT), self.capture.get(cv.CV_CAP_PROP_FRAME_WIDTH))

        # Check that we actually have a valid video source
        if fps == 0.0:
            print "Video source", self.input, "not found!"
            return None        

        # Bring the fps up to the specified rate
        try:
            fps = int(fps * self.fps / fps)
        except:
            fps = self.fps

        # Create the display window
        cv.NamedWindow("Video Playback", True) # autosize the display
        cv.MoveWindow("Video Playback", 375, 25)

        # Create the CvBridge object
        bridge = CvBridge()

        # Enter the main processing loop
        while not rospy.is_shutdown():
            # Get the next frame from the video
            frame = self.get_frame()

            # Convert the frame to ROS format
            try:
                image_pub.publish(bridge.cv2_to_imgmsg(cv.fromarray(frame), "bgr8"))
            except CvBridgeError, e:
                print e

            # Create a copy of the frame for displaying the text
            display_image = frame.copy()

            if self.show_text:
                cv2.putText(display_image, "FPS: " + str(self.fps), (10, 20), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, "Keyboard commands:", (20, int(self.frame_size[0] * 0.6)), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, " ", (20, int(self.frame_size[0] * 0.65)), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, "space - toggle pause/play", (20, int(self.frame_size[0] * 0.72)), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, "     r - restart video from beginning", (20, int(self.frame_size[0] * 0.79)), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, "     t - hide/show this text", (20, int(self.frame_size[0] * 0.86)), font_face, font_scale, cv.RGB(255, 255, 0))
                cv2.putText(display_image, "     q - quit the program", (20, int(self.frame_size[0] * 0.93)), font_face, font_scale, cv.RGB(255, 255, 0))

            # Merge the original image and the display image (text overlay)
            display_image = cv2.bitwise_or(frame, display_image)

            # Now display the image.
            cv2.imshow("Video Playback", display_image)

            """ Handle keyboard events """
            self.keystroke = cv.WaitKey(1000 / fps)

            """ Process any keyboard commands """
            if 32 <= self.keystroke and self.keystroke < 128:
                cc = chr(self.keystroke).lower()
                if cc == 'q':
                    """ user has press the q key, so exit """
                    rospy.signal_shutdown("User hit q key to quit.")
                elif cc == ' ':
                    """ Pause or continue the video """
                    self.paused = not self.paused
                elif cc == 'r':
                    """ Restart the video from the beginning """
                    self.restart = True
                elif cc == 't':
                    """ Toggle display of text help message """
                    self.show_text = not self.show_text        


    def get_frame(self):
        # If the video is paused, return the last frame
        if self.paused and not self.last_frame is None:
            frame = self.last_frame
        else:
            # Get the next frame
            ret, frame = self.capture.read()

        if frame is None:
            # If we've run out of frames, loop if set True
            if self.loop_video:
                self.restart = True     

        # Did we receive the restart command?
        if self.restart:
            # To restart, simply reinitialize the capture object
            self.capture = cv2.VideoCapture(self.input)
            self.restart = False
            ret, frame = self.capture.read()

        # Were we asked to resize the video?
        if self.resize_video:
            frame = cv2.resize(frame, (self.resize_width, self.resize_height))

        # Store the last frame for when we pause
        self.last_frame = frame

        return frame

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

def main(args):
    help_message =  "Hot keys: \n" \
          "\tq     - quit the program\n" \
          "\tr     - restart video from beginning\n" \
          "\tspace - toggle pause/play\n"

    print help_message

    try:
        v2r = Video2ROS()
    except KeyboardInterrupt:
        print "Shutting down video2ros..."
        cv2.destroyAllWindows()

if __name__ == '__main__':
    main(sys.argv)
@vrabaud
Copy link
Contributor

vrabaud commented Dec 2, 2014

Right, this is because you are sending an OpenCV1 matrix, which is not supported anymore. Just sending frame (and not cv.fromarray(frame)) should work.
Now, I'll leave this bug open as there should be a type check to get a clearer error message right up.

@pirobot
Copy link
Author

pirobot commented Dec 2, 2014

Many thanks Vincent--that was it (of course!). All is well again.

vrabaud added a commit that referenced this issue Dec 14, 2014
@vrabaud vrabaud closed this as completed Dec 14, 2014
luca-della-vedova pushed a commit to luca-della-vedova/vision_opencv that referenced this issue Sep 2, 2020
…vice

Adds a SetMap service message to support swap maps functionality in amcl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants