Ask Your Question
1

"cv_bridge" throws boost import error in Python 3 and ROS Melodic

asked 2020-04-28 16:10:11 -0500

hermanoid gravatar image

I'm running a script that uses cv_bridge with OpenCV 4, on Python 3, on ROS Melodic, on Raspbian, on a Raspberry Pi 4, and I'm running into errors trying to dynamically import cv_bridge.boost and failing.

I built ROS from source following these instructions, and installed opencv with sudo pip3 install opencv-contrib-python==4.1.0.25. I've had to do a bit of a hack to get it to import properly (I run sys.path.append('/usr/lib/python2.7/dist-packages') before I import cv2) but beyond these hacks, OpenCV 4 seems to be playing nice with Python 3, and Python 3 seems to be playing nice with ROS.

I from cv_bridge import CvBridge, CvBridgeError without issue, then run:

self.bridge = CvBridge()
image_opencv = self.bridge.imgmsg_to_cv2(data, desired_encoding="passthrough")

on a helper class, where data (as the function suggests) is a standard ROS Image message. (In my case, I'm getting these messages from the cv_camera topic /cv_camera/image_raw)

when I try to run that, I get this error:

[ERROR] [1588106367.612936]: bad callback: <bound method tpu_detector.callback of <__main__.tpu_detector object at 0xa7061df0>>
Traceback (most recent call last):
  File "/opt/ros/melodic/lib/python2.7/dist-packages/rospy/topics.py", line 750, in _invoke_callback
    cb(msg)
  File "/home/pi/catkin_ws/src/edge_tpu/scripts/detect_ros.py", line 91, in callback
    data, desired_encoding="passthrough")
  File "/home/pi/catkin_build_ws/install/lib/python2.7/dist-packages/cv_bridge/core.py", line 163, in imgmsg_to_cv2
    dtype, n_channels = self.encoding_to_dtype_with_channels(img_msg.encoding)
  File "/home/pi/catkin_build_ws/install/lib/python2.7/dist-packages/cv_bridge/core.py", line 99, in encoding_to_dtype_with_channels
    return self.cvtype2_to_dtype_with_channels(self.encoding_to_cvtype2(encoding))
  File "/home/pi/catkin_build_ws/install/lib/python2.7/dist-packages/cv_bridge/core.py", line 91, in encoding_to_cvtype2
    from cv_bridge.boost.cv_bridge_boost import getCvType
ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)

every time an image message arrives. Which, to put it lightly, really sucks. I've googled the snot out of it, and come up with a few pages, all of which tell me to build cv_bridge for Python 3 - but I already have. Multiple times. Following the instructions in this Medium post line by line, the error persists. The error traceback above prooves that this custom-built package is being imported like it's supposed to.

It's worth noting that I had to use catkin_make to build cv_bridge properly; catkin build cv_bridge(with all the extra flags of https://stackoverflow.com/questions/4..., plus an extra -DPYTHON3=1 I added to placate NumPy) fails for no apparent reason (I've pasted the output into this gist if anyone believes it to be related to the issue)

I have been stuck on this issue for a multitude of hours and have gotten no closer to a solution - any help will be much appreciated!

edit retag flag offensive close merge delete

Comments

Hey did you find the solution? I'm getting the same error. If you did can you help me pls?

Onurcan gravatar image Onurcan  ( 2021-03-28 06:55:07 -0500 )edit

@Onurcan Thanks for the reminder! See my new answer on this thread.

hermanoid gravatar image hermanoid  ( 2021-03-29 08:05:24 -0500 )edit
1

While this isn't a specific answer to your problem, you are going to have a lot less headaches using python2 and opencv 3 when working with ROS melodic. If you want to stick with python 3 and opencv 4, depending on your Raspbian version, you can install ROS noetic instead since they officially ported to python 3.

404RobotNotFound gravatar image 404RobotNotFound  ( 2021-04-10 16:39:27 -0500 )edit

1 Answer

Sort by » oldest newest most voted
5

answered 2021-03-29 08:04:53 -0500

hermanoid gravatar image

While this is probably not the best solution, the way I eventually solved this was to remove any reference to dysfunctional libraries from the source code. The result is very solution-specific, so you'll have to make sure that your input and output data types line up - bgr8, for my example. You might be able to adapt it to a different data type if needed. The code looks like this:

NotCvBridge.py

"""
    Provides conversions between OpenCV and ROS image formats in a hard-coded way.  
    CV_Bridge, the module usually responsible for doing this, is not compatible with Python 3,
     - the language this all is written in.  So we create this module, and all is... well, all is not well,
     - but all works.  :-/
"""
import sys
import numpy as np
from sensor_msgs.msg import Image

def imgmsg_to_cv2(img_msg):
    if img_msg.encoding != "bgr8":
        rospy.logerr("This Coral detect node has been hardcoded to the 'bgr8' encoding.  Come change the code if you're actually trying to implement a new camera")
    dtype = np.dtype("uint8") # Hardcode to 8 bits...
    dtype = dtype.newbyteorder('>' if img_msg.is_bigendian else '<')
    image_opencv = np.ndarray(shape=(img_msg.height, img_msg.width, 3), # and three channels of data. Since OpenCV works with bgr natively, we don't need to reorder the channels.
                    dtype=dtype, buffer=img_msg.data)
    # If the byt order is different between the message and the system.
    if img_msg.is_bigendian == (sys.byteorder == 'little'):
        image_opencv = image_opencv.byteswap().newbyteorder()
    return image_opencv

def cv2_to_imgmsg(cv_image):
    img_msg = Image()
    img_msg.height = cv_image.shape[0]
    img_msg.width = cv_image.shape[1]
    img_msg.encoding = "bgr8"
    img_msg.is_bigendian = 0
    img_msg.data = cv_image.tostring()
    img_msg.step = len(img_msg.data) // img_msg.height # That double line is actually integer division, not a comment
    return img_msg
edit flag offensive delete link more

Comments

thank you. was having endless problems with cvbridge and the above fixed them

Kelly Jones gravatar image Kelly Jones  ( 2021-04-10 15:41:36 -0500 )edit

This is the most underrated solution on the internet.. Thank you!!

rosgeller gravatar image rosgeller  ( 2021-07-27 18:42:08 -0500 )edit
1

I've upvoted this answer since it is an elegant solution if you can't use cv_bridge in some context (or don't want to). However, for 95% of people reading this post: You shouldn't try to use Python3 with ROS Melodic. If you want to use Python 3, use ROS Noetic. Everything else will give you endless headaches.

Martin Günther gravatar image Martin Günther  ( 2021-07-28 02:55:02 -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

2 followers

Stats

Asked: 2020-04-28 16:10:11 -0500

Seen: 2,388 times

Last updated: Mar 29