安装ROS Kinetic后,无法导入OpenCV。

47

我最初使用这个脚本从源代码安装了openCV。

当我测试时,它能够正常工作。

之后我安装了ROS kinetic,并打开了python3,运行import cv2 as cv,出现了以下错误:

Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2 as cv
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type

你的Python3正在尝试加载Python2模块?你能运行以下命令并将输出粘贴到你的问题中吗?:ldd /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.soecho $PYTHONPATH,(在Python控制台中)import sys; print(sys.path) - at-2500
12个回答

33

看起来这个问题是由ROS将 /opt/ros/kinetic/lib/python2.7/dist-packages 添加到python路径中引起的。当您使用命令 source /opt/ros/kinetic/setup.bash 激活ROS时,实际上就会发生这种情况。这行代码通常会添加到您的bashrc文件中,在 /home/username/.bashrc 中。

一种解决方法是从bashrc文件中删除此行代码。这样就可以正确使用python3 opencv包,并且您仍然可以运行 source /opt/ros/kinetic/setup.bash 使用ROS。但是这意味着您不能在同一个环境中同时使用ROS和python3。

希望有人能想出更好的答案,但在那之前,这个方法应该可以解决问题。


3
我的解决方法不是删除ROS添加的Python路径,而是将anaconda的路径附加到其中,例如: export PYTHONPATH="/home/userx/anaconda3/lib/python3.5/site-packages:$PYTHONPATH" - Lxrd-AJ
2
嗨。我已经在我的bashrc文件中注释了该行,并在我的代码中添加了sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages/')。当我打印路径时它不会显示出来,但是在我导入cv2时仍然会引起麻烦。你能帮忙吗? - Sarvagya Gupta

20

如果你正在使用Anaconda,激活你想要工作的环境,并从sys.path中删除罪犯。

为此,打开一个Python3控制台,在其中执行以下操作:

>>> import sys
>>> print(sys.path)

您将看到几条路径,其中您应该注意:

'/opt/ros/kinetic/lib/python2.7/dist-packages'

然后将其移除:

>>> sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

使用anaconda3和本地编译的opencv进行python3.5测试,很可能也适用于virtualenvs

要实现永久解决方案,请按@Paul的答案中提到的,在~/.bashrc中删除路径'/opt/ros/kinetic/lib/python2.7/dist-packages'


print(sys.path) instead of print('sys.path') - Steve
这不是一个永久性的解决方案,因为我需要同时使用ROS和Python3。 - Mehdi
@Mehdi 为什么要点踩?Paul的答案提供了“永久”的解决方案,可以同时使用ROS和python3。你可以针对你的具体问题提出新的问题或写下建设性的评论,以便得到帮助。 - calocedrus
1
我在我的~/.bashrc脚本中找不到/opt/ros/kinetic/lib/python2.7/dist-packages这一行... 它只引用了这两个文件:source /opt/ros/kinetic/setup.bash source ~/catkin_ws/devel/setup.bash... 有任何想法是ROS从哪里潜入并更改了我的sys.path吗?谢谢! - yuqli

14

正如指出的那样,在你的 .bashrc 文件中,source /opt/ros/kinetic/setup.bash 命令修改了 PYTHONPATH 的值:

> echo $PYTHONPATH
/opt/ros/kinetic/lib/python2.7/dist-packages

在我的情况下,由于我为我的Python 3项目使用virtualenv,因此当virtualenv被激活时,我只需运行以下命令来清除PYTHONPATH变量。

unset PYTHONPATH

现在,在Python 3虚拟环境中导入cv2可以顺利进行。我验证了cv2的路径:

In [1]: import cv2
In [2]: cv2.__file__
Out[2]: '<path_to_virtualenv>/lib/python3.5/site-packages/cv2/cv2.cpython-35m-x86_64-linux-gnu.so'
为了避免每次激活虚拟环境时都要运行此命令,我将其添加到虚拟环境目录中的 /bin/activate 文件中,如下所示:

为了避免每次激活虚拟环境时都要运行此命令,我将其添加到虚拟环境目录中的 /bin/activate 文件中,如下所示:

...
# unset irrelevant variables
deactivate nondestructive

unset PYTHONPATH

VIRTUAL_ENV="/home/kaiyuzh/pyenv/py3"
export VIRTUAL_ENV
...

这是一个简单而伟大的解决方案!谢谢。 - ewaolx

9
有同样的问题。问题是ROS为Python 2创建了自己的cv2.so文件,然后将每个导入请求路由到该文件。这是一个非常简单的解决方法:
进入您的site-packages文件夹。
cd /usr/local/lib/python3.5/site-packages/

注意,如果您正在使用虚拟环境,则必须在其中,并应该执行类似以下的操作:
cd ~/.virtualenvs/cv/lib/python3.5/site-packages/

然后,使用-f标志强制创建一个新的符号链接。
ln -sf /usr/local/lib/python3.5/site-packages/cv2.so cv2.so

这样应该就解决了!

在最后一行代码中,我可以问一下源是什么,目的地是什么吗?源是否等于虚拟环境站点包,并且目的地在哪里?谢谢。 - yuqli

7
如果以上的解决方案都对你无效(就像我的情况一样),你仍然可以尝试欺骗系统导入正确的opencv。
ros_path = '/opt/ros/kinetic/lib/python2.7/dist-packages'

if ros_path in sys.path:
    sys.path.remove()

import cv2 as cv

sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')

也许在引入cv2后,你可以考虑在正确的位置替换ros python路径。
尽管路径设置正确,我的python似乎有问题导入正确的cv2,可能是因为Python3 cv2库的奇怪命名(cv2.cpython-35m-x86_64-linux-gnu.so)与我在/opt/ros/kinetic/lib/python2.7/dist-packages中拥有的cv2.so不同。

救了我的一天!谢谢。 - Khang Vu
1
太棒了!做得好 :) 在Python 3.7中,应该用sys.path.remove(ros_path)替换sys.path.remove()。 - Sameer Pusegaonkar

5

步骤1:找到安装cv2.so的路径(如果您使用python-cv wheel安装opencv)

步骤2:将路径导出到您的.bashrc或.zshrc文件中,就像这样:

export PYTHONPATH="/home/userx/anaconda3/lib/python3.5/site-package‌​s:$PYTHONPATH"

感谢 @lxrd-aj

4

我试图删除/opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so.现在它可以工作了。


2
在ROS设置中运行/opt/ros/kinetic/setup.bash时,脚本会浏览每个分发包以获取Python2和Python3,然后将其添加到Python系统路径中。当您尝试使用Python 3导入import cv2时,它首先在路径中找到适用于Python 2 的OpenCV绑定。

如果您不打算在ROS项目中使用Python2.7,请考虑完全删除python2.7 OpenCV软件包,因此在运行ros设置脚本时,它不会被添加到路径中:

$ rm /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so

另一种更温和的方法是,如果您计划使用两个Python版本,则使用正确的绑定创建两个虚拟环境,并根据您的要求激活一个或另一个。


1
这对我有用。我仍然能够在Python2和Python3中导入cv2和rospy。删除这个意味着你必须使用自己安装的opencv,可以通过pip完成。 - Watchdog101

2

实际上,我也遇到了这个问题。我只是注释掉了源代码:

/opt/ros/kinetic/setup.bash

然后,打开终端,在Anaconda lib路径下执行:
sudo ln -sf /home/apg/miniconda3/lib/python3.6/site-packages/cv2.so /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so
其中/home/apg/miniconda3是Python3安装的路径,/opt/ros/kinetic/lib/python2.7/dist-packages/cv2.soopencv-python安装的路径。
我还不知道为什么这个命令有效,但它确实解决了之前无法导入cv2的问题。

执行完这个命令后,/opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so 中的 cv2.so 成为了一个损坏的链接。 - Shuai Li

1

我这里也有类似的问题。正如其他人建议的那样,/opt/ros/kinetic/setup.bash会在PYTHONPATH变量中添加一个ROS opencv的路径。

如果你正在使用多个virtualenv并且需要一个适用于大多数情况的解决方案,则可以将以下代码片段放入你的.bashrc文件中:

source /opt/ros/kinetic/setup.bash
array=( $(find ~/.virtualenvs/ -mindepth 1 -maxdepth 1 -type d) )

for i in "${array[@]}"
do
  export PYTHONPATH="$i/lib/python2.7/site-packages:$PYTHONPATH"
done

因此,这个想法是如果您拥有所有虚拟环境的集中目录(例如,当您使用virtualenvwrapper时),我们可以使用以下方式搜索这些目录:

$(find ~/.virtualenvs/ -mindepth 1 -maxdepth 1 -type d)

假设我们所有的virtualenv都在~/.virtualenvs下。这将给我们列出所有virtualenv根目录的列表。

然后,我们循环遍历virtualenv目录数组,并将它们的路径(例如~/.virtualenvs/testenv/lib/python2.7/site-packages)附加到PYTHONPATH中。请注意,在执行source /opt/ros/kinetic/setup.bash执行此操作。

这并不是完美的解决方案,因为如果两个环境具有不同的opencv版本,则仍然可能会发生冲突,但对于最初的问题,至少应该可以解决。

或者,您可以手动为所需的virtualenv执行相同的技巧:

export PYTHONPATH=~/.virtualenvs/testenv/lib/python2.7/site-packages:$PYTHONPATH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接