Ubuntu18.04自带的python3.6下使用cv_bridge
- 我自己为什么不想用Ubuntu16.04的ROS kinetic版本
- 一、什么是cv_bridge
- 1.cv_bridge官方文档
- 2.调用方法
- 二、往已有的功能包里添加所需要的依赖包(这一步出现了问题,可以直接跳过)
- 1.要添加的包
- 2.修改相应的配置文件
- 3.运行图像转换脚本
- 4.报错
- 三、重新在python3.6的环境下编译cv_bridge
- 1.修改配置文件(如果没有看【二】,可以跳过这一小步)
- 2.重新修改配置文件
- 3.从官网下载cv_bridge的源码并用python3.6编译
- 补充
- 4.调用用python3.6编译好的cv_bridge
- 四、在ROS中用python3.6调用opencv
- 1.这些之前在ROS kinetic上遇到的一些问题(废话可跳过:)
- 2.直接在脚本中导入cv2
- 五、在之前的调用cv_bridge的脚本中同时使用cv2
我自己为什么不想用Ubuntu16.04的ROS kinetic版本
- 因为Ubuntu16.4自带的python3版本是3.5。因为我在开发过程中需要torch==1.6.0,需要python3.6+的环境,Ubuntu18.04自带的python3.6会舒服很多。
- 但是仍然可以把Ubuntu16.04的python3.5升级为python3.7,然后使用更高版本的包,通过升级得到的python3.7会出现很多问题。百度上这样的教程有很多,我可能会总结一下发一篇博客:)P
- 建议升级Ubuntu18.04系统,安装melodic版本的ROS,kinetic和melodic没有什么太大的区别,可以兼容kinetic。
一、什么是cv_bridge
1.cv_bridge官方文档
cv_bridge的官方教程。
http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython
- cv_bridge是一个将ROS图像(sensor_msgs/Image)转换为OpenCV图像,并将OpenCV图像转换为ROS和OpenCV的接口。
2.调用方法
from cv_bridge import CvBridge
bridge = CvBridge()
# opencv图像转换为sensor_msgs/Image图像
image_message = bridge.cv2_to_imgmsg(cv_image, encoding="bgr8")
# 把sensor_msgs/Image图像转换为opencv图像
cv_image = bridge.imgmsg_to_cv2(image_message, desired_encoding='bgr8')
二、往已有的功能包里添加所需要的依赖包(这一步出现了问题,可以直接跳过)
1.要添加的包
sensor_msgs
opencv2
cv_bridge
2.修改相应的配置文件
- 进入当前功能包(my_pkg功能包为例)的目录下,打开package.xml文件。
- 添加如下配置。(和上面格式一样)
- 打开CMakeLists.txt文件。添加如下的配置:
- 重新编译当前工作空间
cd ../../ && catkin_make
。
编译的时候报错,提示找不到opencv的CMakeLists.txt文件,然后我把opencv2从上面的配置文件中删除,重新编译成功。
3.运行图像转换脚本
- 运行
rosrun my_pkg imgmsg_to_cv2.py
,然后开启一个发布sensor_msgs/Image消息的topic,这里我自己录了一个包,里面有摄像头发布这个数据的topic,所以直接用rosbag play xxx.bag
发布消息。
#!/usr/bin/python3
#-*- coding:UTF-8 -*-
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
def ConvertCallback(msg):
bridge = CvBridge()
# 把ROS图像转换为opencv图像
cvimg = bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')
rospy.loginfo("Convert image_message to cv2_img successfully.")
def cameralane_subcriber():
# ROS节点初始化
rospy.init_node('convert_subcriber', anonymous=True)
# 创建一个Subcriber,订阅一个发布sensor_msgs/Image的topic,注册回调函数 ConvertCallback()
rospy.Subscriber("/xxx/topic", Image, ConvertCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
cameralane_subcriber()
4.报错
- 报错。
ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)
三、重新在python3.6的环境下编译cv_bridge
1.修改配置文件(如果没有看【二】,可以跳过这一小步)
- 把相应的cv_bridge从上面的配置文件中删除。
2.重新修改配置文件
- 参考【二】中的第2小步,把
sensor_msgs
这个包添加到package.xml和CMakeLists.txt中。 - 重新编译工作空间
catkin_make
。
3.从官网下载cv_bridge的源码并用python3.6编译
用python3.6编译源码的全部过程参考这个链接(这个链接是在kinetic版本下用python3.5编译的):https://stackoverflow.com/questions/49221565/unable-to-use-cv-bridge-with-ros-kinetic-and-python3?rq=1
-
sudo apt-get install python-catkin-tools python3-dev python3-catkin-pkg-modules python3-numpy python3-yaml ros-melodic-cv-bridge
安装一些相关的依赖包。 -
cd ~ && mkdir cv_bridge_ws
在用户根目录下创建新的cv_bridge的工作空间。 cd cv_bridge_ws && catkin init
初始化工作空间,这一步会出现一些红色的提示,不用管。-
catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.6m.so
设置cmake编译选项。 -
catkin config --install
把所有编译好的包放在工作空间的install文件夹下(暂时没有该文件夹,不用管)。 -
git clone https://github.com/ros-perception/vision_opencv.git src/vision_opencv
把源码克隆到工作空间的src目录下 apt-cache show ros-melodic-cv-bridge | grep Version
在本地仓库中找cv_bridge的版本。cd src/vision_opencv/ && git checkout 1.13.0
cd ../../ && catkin build cv_bridge
编译cv_bridge,按照上面的步骤来的话,应该不会有Error出现,如果出现了,可以自行百度:(source install/setup.bash --extend
把当前的功能包(vision_opencv)扩展到环境中?然后其他的功能包就可以使用了。不想每次打开终端都要source一下,可以把source命令写进~/.bashrc文件中。sudo gedit ~/.bashrc
补充
- 如果遇到下面的这个问题:
- 原因是:cmake要找到libboost_python3.so这个库,但是在Ubuntu16.04中这个库叫libboost_python-py35.so这个名字路径是(/usr/lib/x86_64-linux-gnu/libboost_python-py35.so)。要把
src/vision_opencv/cv_bridge/CMakeLists.txt
中的find_package(Boost REQUIRED python3)
改为find_package(Boost REQUIRED python-py35)
然后重新编译工作空间。 - 这个是在kinetic版本中出现的,在melodic版本中没有出现这个问题。
- (在不同环境下,比如说kinetic和Xavier)在自己的脚本中调用cv_bridge的时候,
from cv_bridge import getType(好像是这个)
,会出现报错。只需要把~/cv_bridge_ws/src/vision_opencv/cv_bridge
这个文件夹复制到自己脚本所在的目录问题就可以解决了。
4.调用用python3.6编译好的cv_bridge
roscore
-
rosrun my_pkg imgmsg_to_cv2.py
启动在【二】(3)编写好的图像转换脚本。 -
rosbag play xxx.bag
重现有sensor_msgs/Image消息的bag包。 - 运行成功。
四、在ROS中用python3.6调用opencv
1.这些之前在ROS kinetic上遇到的一些问题(废话可跳过:)
- 之前用Ubuntu16.04中ROS的kinetic的版本的时候,调用opencv的时候出现了很多问题。原因是ROS默认使用pyhton2.7,但是当脚本中指定运行环境为python3的时候,
- /opt/ros/kinetic/lib/python2.7/dist-packages 路径下的opencv找不到cv.2so还是cv.so(具体的忘记了)。
- 百度上有许多类似这样的解决方法。
- 但是现在,只要在python3下安装opencv就可以了,
pip3 install opencv-python==3.4.3.18
。(之前在ROS kinetic上就不行,可能只是我个人的问题:)
- 因为遇到上面这些问题的时候,是在我刚学ROS的时候,遇到的所有问题,都只有查博客。在不断的查资料的过程中,我得到了很多经验,现在把这些经验记录一下。(
因为项目需要python3.6+的环境,而ROS Kinetic只有原生的python3.5,在我一顿操作把它升级到python3.7之后,出现了一些我暂时解决不了的问题,然后被迫重新安装有原生python3.6的ROS Melodic。又是从头开始查资料,幸好之前把整个过程都自己跑了一下,所以新版本的安装异常顺利。)
2.直接在脚本中导入cv2
rosrun my_pkg cv2_test.py
记得设置py脚本的可执行权限。- vscode中有个很头疼的问题,好像不支持系统的相对路径?vscode代码中的根目录好像是当前的工作空间?建议直接使用绝对路径!
- 脚本如下
#!/usr/bin/python3
#-*- coding:UTF-8 -*-
import cv2
if __name__ =="__main__":
img = cv2.imread('/home/mkid/ros_bag/srcimg.jpg')
cv2.imshow('img', img)
#cv2.imwrite('~/ros_bag/convert.jpg', img)
cv2.imwrite('/home/mkid/ros_bag/convert.jpg', img)
print('yes')
五、在之前的调用cv_bridge的脚本中同时使用cv2
- 和【四】(2)一样,只要在bridge.imgmsg_to_cv2函数下调用cv2相关的函数就行。
- 之前的脚本在【二】(3)中。