1. 报错如下
Traceback (most recent call last):
File "inference_realsense_hand.py", line 10, in <module>
import cv2
ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
2. 问题原因
问题描述:
Ubuntu16.04 安装了ROS Kinetic之后Python3不能import cv2
据了解在,python中是通过cv2.so调用opencv的库的:
Python调用opencv的原理是:opencv编译出共享库文件,python把这个共享库文件作为一个模块加载并使用。通俗点就是,编译opencv的时候开启python接口选项,编译好了会产生cv2.so(linux下)或者cv2.pyd(windows下)这个共享库文件,python代码中import这个cv2就可以用了。为了能正确import它,往往需要把cv2.so放在python找包能找到的路径下,或者修改PYTHONPATH环境变量让它包含cv2.so所在路径。
可以看出这个问题是由ROS添加/opt/ros/kinetic/lib/python2.7/dist-packages到python路径引起的。
3. 解决步骤
2.1 网上的解决方案都是指向了同一个,修改环境配置文件.bashrc,这个方法(传送门)里的比较详尽,可是改完以后还是一样的报错;
2.2 既然是python路径问题,那么我就把.bashrc文件里的关于ros的文件先屏蔽掉,原.bashrc文件内容如下:
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
source /opt/ros/kinetic/setup.bash
export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}
export PATH=/opt/ros/kinetic/include/opencv-3.3.1-dev/opencv2${PATH:+:${PATH}}
#export LD_LIBRARY_PATH=/opt/ros/kinetic/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export LD_LIBRARY_PATH=/home/neousys/Desktop/IRIM_EVENTUAL/src/object_detection${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export PKG_CONFIG_PATH
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/ros/kinetic/lib/x86_64-linux-gnu
export ROS_HOSTNAME=neousys-Nuvo-5000
#export ROS_MASTER_URI=http://agv:11311
#export ROS_HOSTNAME=192.168.103.17
#export ROS_MASTER_URI=http://192.168.103.17:11311
#export ROS_HOSTNAME=192.168.103.5
#export ROS_MASTER_URI=http://192.168.103.5:11311
#cd Desktop/IRIM_EVENTUAL
#source /home/neousys/Desktop/IRIM_EVENTUAL/devel/setup.bash
#source /home/neousys/Desktop/IRIM_EVENTUAL/devel/setup.bash
#source ~/lee_ws/devel/setup.bash
#source ~/ws_moveit/devel/setup.bash
#source ~/lee/ThroatSwab/devel/setup.bash
#source ~/catkin_ws/devel/setup.bash
#source /home/neousys/catkin_ws/devel/setup.bash
source /home/neousys/Desktop/IRIM_EVENTUAL/devel/setup.bash
export PATH="/home/neousys/anaconda3/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export PATH="/home/neousys/anaconda2/bin:$PATH"
export CUDA_HOME=/usr/local/cuda-10.1
#export LD_LIBRARY_PATH=${CUDA_HOME}/lib64
export PATH=${CUDA_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=/opt/ros/kinetic/lib
屏蔽完以后再source发现还是不行
2.3 在python代码里面import cv2之前加上这么一句,详见传送门2把/opt/ros/kinetic/lib/python2.7/dist-packages
给移除掉,也没起作用
import sys
sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
3. 真相
3.1 ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
这个报错的原因没有别的,前面也解释了,就是import cv2的路径不对,这里的解决方案还是跟 上面2.1 的方案一样,只是要特别注意两个问题:
(1)export的路径不对;
这个链接示例的路径是export PYTHONPATH="/home/userx/anaconda3/lib/python3.5/site-packages:$PYTHONPATH"
,但这条路径大概率是有错的(即使改了userx),
最好的办法就是在你的conda环境下运行pip install opencv-python
这个指令,命令行会返回信息,这个返回的路径才是真正的cv路径,我这里是home/neousys/miniconda3/envs/CenterNet/lib/python3.6/site-packages
,把上面的那个export 替换成export PYTHONPATH="/home/neousys/miniconda3/envs/CenterNet/lib/python3.6/site-packages:$PYTHONPATH"
就可以了
neousys@neousys-Nuvo-5000:~/wqw/Myproject/hand_detection_tf$ pip install opencv-python
Requirement already satisfied: opencv-python in /home/neousys/miniconda3/envs/CenterNet/lib/python3.6/site-packages (4.1.1.26)
Requirement already satisfied: numpy>=1.11.3 in /home/neousys/miniconda3/envs/CenterNet/lib/python3.6/site-packages (from opencv-python) (1.19.2)
neousys@neousys-Nuvo-5000:~/wqw/Myproject/hand_detection_tf$
3.2 这一步最重要,要执行source ~/.bashrc,且要在建立的虚拟环境下source,如图:
至此,大功告成!