After install ROS Kinetic, cannot import OpenCV

2019-01-17 20:43发布

问题:

I have first installed openCV from source using this script. When I tested it was working well.

After I installed ROS kinetic, and open python3 and run import cv2, got the following error:

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
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

回答1:

It looks like this problem is caused by ROS adding /opt/ros/kinetic/lib/python2.7/dist-packages to the python path. This actually happens when you activate ROS with the command source /opt/ros/kinetic/setup.bash. This line is often added at the end of your bashrc file, in /home/username/.bashrc.

A workaround is to remove this line from the bashrc file. This way the python3 opencv packages will be correctly used, and you can still run source /opt/ros/kinetic/setup.bash to use ROS. However, this does mean you cannot use ROS and python3 from the same environment.

Hopefully someone can come up with a better answer, but this should work until then.



回答2:

If you are working with anaconda, activate the environment you want to work from, and remove the culprit from sys.path.

To do so, open a python3 console, from which:

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

You will see several path, among which you should notice:

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

Then remove it:

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

Tested with python3.5 on anaconda3 with locally compiled opencv. This is likely applicable to virtualenvs as well.

For a permanent solution, remove the path '/opt/ros/kinetic/lib/python2.7/dist-packages' from ~/.bashrc as mentioned in @Paul's answer.



回答3:

Was having the exact same problem. The issue is that ROS creates it's own cv2.so file for python 2, and then routes every import request to that file. It's a pretty easy fix:

go to your site-packages folder

cd /usr/local/lib/python3.5/site-packages/

note, if you are using a virtual environment, you must be within that, and should instead do something like:

cd ~/.virtualenvs/cv/lib/python3.5/site-packages/

Then, force a new sym-link this time using the -f flag

ln -sf /usr/local/lib/python3.5/site-packages/cv2.so cv2.so

And that should fix things!



回答4:

Step1: Find the path where your cv2.so is installed (if you use the python-cv wheel to install the opencv)

Step2: Export the path to your .bashrc or .zshrc file, just like this:

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

Thanks to @lxrd-aj



回答5:

I tried to remove /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so. Now It is working.



回答6:

Actually, I also encounter this problem. I just commented-out the source:

/opt/ros/kinetic/setup.bash

and then, open the terminal, In the anaconda lib path I executed:

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 is the path where my python3 was installed, and /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so was the path that opencv-python was installed.

I don't know yet why this command works, but it did work for me to solve the problem that I was not able to import cv2 previously.



回答7:

If none of those solutions works for you (as in my case) you could still try to trick your system into importing the right opencv

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

if ros_path in sys.path:

    sys.path.remove()

import cv2

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

Maybe you might consider replacing the ros python path at the right location after importing cv2.

It seems that my python had problems importing the correct cv2 even though the path was set correctly, probably because of the weird naming of the python3 cv2 library (cv2.cpython-35m-x86_64-linux-gnu.so) compared to the cv2.so I have in /opt/ros/kinetic/lib/python2.7/dist-packages



回答8:

During ROS setup running /opt/ros/kinetic/setup.bash, the script between other things will go to every distribution package for python2 and python3 and it will add it to the python system path. When you try to import cv2 using python3 it will first find the cv2 binding for Python2 as included in the path.

If you are not planning on using python2.7 at all for your ROS project, consider removing entirely the python2.7 OpenCV package, so it won't be added to the path when running the ros setup script:

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

Another more gentle approach if you are planning to use both Python versions would be to create two virtual environments with the correct bindings, and activate one or another depending on your requirements.



回答9:

Similar problem over here. As others suggested, /opt/ros/kinetic/setup.bash appends a path to ROS opencv in the PYTHONPATH variable.

If you are working with multiple virtualenvs and you need a solution that will work in most of the cases, then you can put the following code snippet in your .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

So the idea is that if you have a centralised directory of all of your virtualenvs (e.g when you use virtualenvwrapper) we can search for those directories using:

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

given that all of our virtualenvs are under ~/.virtualenvs. This should give us a list of all of our virtualenvs root directory.

We are then looping over the array of virtualenv directories and we are appending their path (e.g ~/.virtualenvs/testenv/lib/python2.7/site-packages) to the PYTHONPATH. Note that this should be done just after the source /opt/ros/kinetic/setup.bash.

It's not a perfect solution to the problem as you can still get conflicts if two envs have different opencv versions, but for the initial problem, at least it should work.

Alternatively, you can just manually do the same trick for the desired virtualenv:

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