Docker中配置CUDA 版本的OpenCV和FFmpeg,支持H264,以及Anaconda虚拟环境调用

一、 前言

1. 背景说明

目的是Anaconda虚拟环境中调用支持GPU的OpenCV和支持CUVID的FFmpeg,且支持H264视频编码格式, 另外解除ffmpeg-gpu的NVENC的限制。前面文字都是踩坑记录,如果想看详细命令, 直接查看文末Dockerfile.

简单来说,主要特性包含以下几点:

  • 安装有GPU支持的Opencv和CUDA;
  • 支持H264格式编码;
  • 解除了FFmpeg最大Session(最多支持编解码路数)限制

2. GPU架构说明

Geforce系列 核心代号 ( Code Name ) 年代 ( time ) 例 ( Instance )
更早 (无科学家名称代号) 远古~2006 GeForce 7800 GTX
8000系 特斯拉 ( Tesla ) 2007~2008 GeForce 8800 GTS
9000系 特斯拉 ( Tesla ) 2008~2009 GeForce 9600 GSO
100系 特斯拉 ( Tesla ) 2009~2009 GeForce GTS 150
200系 特斯拉 ( Tesla ) 2009~2009 GeForce GTX 295
300系 特斯拉 ( Tesla ) 2009~2010 GeForce GT 335
400系 费米 ( Fermi ) 2010~2011 GeForce GTX 460
500系 费米 ( Fermi ) 2011~2012 GeForce GTX 555
600系 开普勒 ( Kepler ) 2012~2013 GeForce GTX 690
700系 麦克斯韦尔 ( Maxwell ) 2013~2014 GeForce GTX 750 Ti
900系 麦克斯韦尔 ( Maxwell ) 2014~2016 GeForce GTX 960
10系 帕斯卡 ( Pascal ) 2016~2018 GeForce GTX 1080 Ti
20系 图灵 ( Turing ) 2018~2020 GeForce RTX 2080 Ti
30系 安培 ( Ampere ) 2020~未来 GeForce RTX™ 3080

3. 显卡算力的CUDA_ARCH_BIN和 CUDA_ARCH_PTX 的解释

参考文档

  • NVIDIA*编译器允许生成二进制代码(cubin and fatbin)和中间代码(Parallel Thread eXecution,PTX)。 BIN二进制代码通为特定的GPU架构生成,因此不能保证与其他GPU的兼容性。PTX中间代码是编译后的GPU代码的一种中间形式,它可以再次编译为原生的GPU二进制码。PTX代码针对我们指定的显卡算力所对应虚拟平台。 在第一次调用时使用JIT编译器转化为二进制代码(实际物理显卡算力需要大于等于指定的算力,否则编译失败)

  • CUDA_ARCH_BIN一般需要指定,且最好不要把所有版本都编译,如CUDA_ARCH_BIN="3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5 8.6".
    最好根据上面的说明,查一下当前显卡的型号,以及对应的显卡算力,然后在这里指定一个即可,如3080显卡可以保持 CUDA_ARCH_BIN="8.6"。否则全部编译一遍速度会很慢。

  • CUDA_ARCH_PTX 中间代码一般使用得少,如3080显卡可以保持 CUDA_ARCH_PTX =""

4. 关于OpenCV编译选项的一些说明

详细可以看:

  1. CMake编译opencv各选项的含义
  2. 官方配置教程

二、安装过程说明


以下只叙述流程,详细的步骤请参考文末Dockerfile


1. NVIDIA-Driver、CUDA、Cudnn安装

这部分是常识,这里不做赘述

2. 基础库安装

也可以apt包管理工具(Ubuntu)安装(不排除有冗余包):

apt-get clean && 
apt-get -y update && 
apt-get 
        -o Acquire::BrokenProxy="true" 
        -o Acquire::http::No-Cache="true"  
        -o Acquire::http::Pipeline-Depth="0" 
    -y install 
        python3 
        python3-dev 
        make 
        cmake 
        build-essential 
        pkg-config 
        libatlas-base-dev 
        gfortran 
        libgl1-mesa-glx 
        libjasper-dev 
        libgtk2.0-dev 
        libtbb2 
        libtbb-dev 
        libavcodec-dev 
        libavformat-dev 
        libswscale-dev 
        libjpeg-dev 
        libpng-dev 
        libtiff5-dev 
        libdc1394-22-dev 
        libtiff-dev 
        libv4l-dev 
        liblapacke-dev 
        libx264-dev 
        software-properties-common 
        yasm 
        nasm 
        ninja-build 
        sysstat 
        libtcmalloc-minimal4 
        autoconf 
        libtool 
        flex 
        bison 
        libsm6 
        libxext6 
        libxrender1 
        libx264-dev 
        libx265-dev 
        libsndfile1 
        libmp3lame-dev 
        gcc 
        g++ 
        libavutil-dev 
        libavcodec-dev 
        libavformat-dev 
        libswscale-dev 
        libavresample-dev

3. FFmpeg安装

可以使用官方Docker镜像,也可以从源码编译。

3.1 直接使用容器

本人为了方便使用了这个方法,https://hub.docker.com/r/jrottenberg/ffmpeg/,参考该镜像的Dockerfile在https://github.com/jrottenberg/ffmpeg。然后上面第一步镜像已经安装好,第二部进行了手动安装,详见Dockerfile。

3.2 从源码编译

这步可以参考
使用GPU硬件加速FFmpeg视频转码, 写的详细且亲测通过。

  • x264库在上一步已经安装,请确保 编译时--enable-libx264
  • 为了支持GPU编解码,需要确保 --enable-cuda --enable-cuvid --enable-nvenc. 编译完成后执行ffmpeg -codecs | grep cuvid查看cuvid提供的GPU编解码器,应当有类似如下结果:

4. OpenCV安装

详细命令见Dockerfile。这里有几个坑需要注意:

4.1 如果安装了Anaconda,最好先把环境变量注释掉(重要),否则很容易出未定义的引用 XXX;

可以先获取虚拟环境的信息,然后取消激活

    source activate torch_37  && 
    OPENCV_PYTHON_EXECUTABLE_ANACONDA=$(which python${PYTHON_VERSION}) && 
    OPENCV_INSTALL_PATH=$(python -c "import sys; print(sys.prefix)") && 
    OPENCV_INCLUDE_DIR_ANACONDA=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") && 
    OPENCV_PACKAGE_ANACONDA=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") && 
    conda deactivate && 

之后Cmake时候指定这些变量即可,如:

      -D PYTHON${PYTHON_VERSION%%.*}_EXECUTABLE=$${OPENCV_PYTHON_EXECUTABLE_ANACONDA} 
      -D PYTHON_DEFAULT_EXECUTABLE=${OPENCV_PYTHON_EXECUTABLE_ANACONDA} 
      -D CMAKE_INSTALL_PREFIX=${OPENCV_INSTALL_PATH} 
      -D PYTHON${PYTHON_VERSION%%.*}_INCLUDE_DIR=${OPENCV_INCLUDE_DIR_ANACONDA} 
      -D PYTHON${PYTHON_VERSION%%.*}_PACKAGES_PATH=${OPENCV_PACKAGE_ANACONDA} 

4.2 如果添加了opencv_contrib , 有可能缺少文件,是Cmake配置时候下载失败导致的。错误信息如下:

/boostdesc.cpp:654:20: fatal error: boostdesc_bgm.i: No such file or directory

解决办法: 参考安装OpenCV时提示缺少boostdesc_bgm.i文件的问题解决方案(附带百度云资源) 把资源下载下来拷贝到opencv_contrib/modules/xfeatures2d/src/目录下。(Dockerfile中我的链接有可能超时失效,请从这里下载)

4.3 CUDA_ARCH_BIN请根据上文所述显卡算力进行修改

各个型号的显卡算力【CUDA_ARCH_BIN】如下图,该部分主要用于OpenCV编译时指定, 也可以从链接对应官网查询(以下为截图)。

4.4 解释器路径

Dockerfile中,python库安装到了Torch_37虚拟环境,这里可以根据实际python解释器情况修改。

三、详细Dockerfile

# ffmpeg - http://ffmpeg.org/download.html
#
# From https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
#
# ffmpeg docker - https://hub.docker.com/r/jrottenberg/ffmpeg/
#
# opencv docker - https://github.com/Valian/docker-python-opencv-ffmpeg and https://github.com/Borda/docker_python-opencv-ffmpeg/blob/master/gpu/Dockerfile

FROM    tigerdockermediocore/cuda-ffmpeg-docker:4.2.3-cu102

LABEL maintainer="Geoffrey Wong <wangruifeng@mininglamp.com>"

COPY env.yml env.yml
COPY tritonclient-2.4.0-py3-none-any.whl tritonclient-2.4.0-py3-none-any.whl
# 这是我的项目压缩包,这里可以替换成自己的项目
COPY rail-welding-dev.zip rail-welding-dev.zip
COPY boostdesc.zip boostdesc.zip

# Install OpenCV
ARG PYTHON_VERSION=3.7
ARG OPENCV_VERSION=4.3.0
ARG ANACONDA_PATH='/root/miniconda3'

SHELL ["/bin/bash", "-c"]
ENV PATH="${ANACONDA_PATH}/bin:$PATH"
ENV DEBIAN_FRONTEND noninteractive
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,video,utility


# Install all dependencies for OpenCV
RUN source ~/.bashrc && 
    sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list && 
    sed -i '$adeb http://security.ubuntu.com/ubuntu xenial-security main' /etc/apt/sources.list && 
    apt-get -y update -qq --fix-missing && 
    apt-get 
        -o Acquire::BrokenProxy="true" 
        -o Acquire::http::No-Cache="true" 
        -o Acquire::http::Pipeline-Depth="0" 
        -y install --no-install-recommends 
        # python${PYTHON_VERSION} 
        # python${PYTHON_VERSION}-dev 
        # $( [ ${PYTHON_VERSION%%.*} -ge 3 ] && echo "python${PYTHON_VERSION%%.*}-distutils" ) 
        git 
        wget 
        unzip 
        make 
        cmake 
        libtbb2 
        gfortran 
        apt-utils 
        pkg-config 
        checkinstall 
        qt5-default 
        build-essential 
        libatlas-base-dev 
        libgtk2.0-dev 
        libavcodec57 
        libjasper-dev 
        libgl1-mesa-glx 
        libavcodec-dev 
        gfortran 
        libavformat57 
        libavformat-dev 
        libavutil-dev 
        libswscale4 
        libswscale-dev 
        libjpeg8-dev 
        libpng-dev 
        libtiff5-dev 
        libdc1394-22 
        libdc1394-22-dev 
        libxine2-dev 
        libv4l-dev 
        libgstreamer1.0 
        libgstreamer1.0-dev 
        libgstreamer-plugins-base1.0-0 
        libgstreamer-plugins-base1.0-dev 
        libglew-dev 
        libpostproc-dev 
        libeigen3-dev 
        libtbb-dev 
        libgtk2.0-dev 
        zlib1g-dev 
        yasm 
        nasm 
        ninja-build 
        fastjar 
        sysstat 
        libtcmalloc-minimal4 
        autoconf 
        libtool 
        flex 
        bison 
        libsm6 
        libxext6 
        libxrender1 
        gcc 
        g++ 
        # 一些额外可选工具
        rsync 
        openssh-server 
        wget 
        module-init-tools 
        openconnect 
        kmod 
        curl 
        vim && 
    # 解决VIM中文乱码
    sed -i '$a set encoding=UTF-8
set langmenu=zh_CN.UTF-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
set fileencoding=utf-8' /etc/vim/vimrc && 
# install python dependencies, 如果不使用Anaconda,而是使用系统Python解释器,那么运行下面这段
    # sysctl -w net.ipv4.ip_forward=1 && 
    # wget https://bootstrap.pypa.io/get-pip.py --progress=bar:force:noscroll && 
    # python${PYTHON_VERSION} get-pip.py && 
    # rm get-pip.py && 
    # pip${PYTHON_VERSION} install numpy && 
# Install Anaconda, Create Virtual Environment
    wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_4.9.2-Linux-x86_64.sh && 
    /bin/bash Miniconda3-py39_4.9.2-Linux-x86_64.sh -b -p /root/miniconda3 && 
    rm Miniconda3-py39_4.9.2-Linux-x86_64.sh && 
    sed -i '$a export PATH="${ANACONDA_PATH}/bin:$PATH"' ~/.bashrc && 
    # export PATH="${ANACONDA_PATH}/bin:$PATH" && 
    # echo 'export PATH="/root/miniconda3/bin:$PATH"' >> ~/.bashrc && 
    source ~/.bashrc && 
    conda clean -a -y && 
    # 添加北京交大源
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/pkgs/free/ && 
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/pkgs/main/ && 
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/cloud/conda-forge/ && 
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/cloud/bioconda/ && 
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/cloud/msys2/ && 
    conda config --add channels https://mirror.bjtu.edu.cn/anaconda/cloud/pytorch/ && 
    conda config --set show_channel_urls yes  && 
    # 创建虚拟环境
    conda env create -f env.yml && 
    sed -i '$a source activate torch_37' ~/.bashrc && 
    source activate torch_37  && 
    ln -s ${ANACONDA_PATH}/envs/torch_37/lib/python3.7/site-packages/pytz/zoneinfo/Asia/Shanghai /etc/localtime && 
    pip install tritonclient-2.4.0-py3-none-any.whl && 
    # 清理无用包
    rm tritonclient-2.4.0-py3-none-any.whl && 
    conda clean -a -y && 
    rm -rf ${ANACONDA_PATH}/pkgs && 
# Get OpenCV,下载
    cd / && 
    wget https://github.com/opencv/opencv/archive/$OPENCV_VERSION.zip -O opencv.zip --progress=bar:force:noscroll && 
    unzip -q opencv.zip && 
    mv /opencv-$OPENCV_VERSION /opencv && 
    rm opencv.zip && 
    wget https://github.com/opencv/opencv_contrib/archive/$OPENCV_VERSION.zip -O opencv_contrib.zip --progress=bar:force:noscroll && 
    unzip -q opencv_contrib.zip && 
    mv /opencv_contrib-$OPENCV_VERSION /opencv_contrib && 
    rm opencv_contrib.zip && 
    # 这几个文件由于网络问题无法自动下载,如果失效可以自己网上找一下
    # wget https://dts.mininglamp.com/pontus/download/wangruifeng/boostdesc.zip?valid_info=%5Ej%A1%B5%83%B0%DA%A60%EC%09%8BM%DB%9DJ%28P%8BF%24p%EE%B1%9E%03q%2F%08%8C%5D%DB%5D%3Dg2%FD%1F%DBp%BD%15%F8%A6%8FQK%B4U%9C%B7%D9%87%29%81x%CA%96%17HUR%3B6%A5%1B6%EA%FE%F9%3D%B9wP%B8G%97%B4%BC%D2A%9A%0B%A2d%C8%20%DC%2B%11%7F%29e%9F%A3%F9v%29i%0D%96e%C2%AA%19E%E6%A5%9A%F4C%CF%02%EC%E6u%29%C9%0C0Gx%18%0A%88%F9%90%0D%FD%EB%24%0C%24%89%7B%13g%E6ihci%24%5C%D4YT%2A%D0%C6a%3Dn%0C%B0%C7U%E7%B9%3E%18%D4%8A%AF%C5%D5%18N_%EAZ98%B1%82jE%88%C0%C2%7BZ%8C%13s%5D%1F%29%9Cj%E8%0F%02%88%EBud%BCm%BFm%1E%9E%B74I%A4%7B%9D%F5%F9%A5%CB%96%09%94%EA%B5%EDV%F1%5C%7F%CE%C8Q%28%C3U%C9%E0%B2%BCD%AF%B5fc%0B%27%AB%0E%20%16ds%20%3E%8D%CB%92%B3%E7%A4%CC%BEyc%C0%D6%243%05%BD%A0NE%2A%83%BAz%BB%AE%5C%9E4%88%26T5%C1%98%AB%FD%CE%8B%2Fd%CC%82z%8B%B1%C2%A8Y%96%9DW%23g%90%00%15M%AF%D4Q%C0%BE%5C%E5%D8%D9%ECq%A0%C0%FF%19%1E%BC%9Bt.Pd3%DC%AE%1AL%1AI%9E%09EG%FE%3E%F2%D8.%F6%8CEv%0D%C2%A0g%0Fq%FB%A7%3F%89G%16%FE%D8%CD%85l%CA%D1pJ%7C%D4%D4Zi%06aS%05r%C2U%F5%20%9AB.%86%94v%81%1Ab%CF%28%F9g%9A%A0%D3F%16%E3%17w%FF%C4%40%C4%2F%9Aj6l%9Cf%83%0B%EB%FAIK%B4%3Di%21%27%23l%CF%DE%BB%C1%F0%974p%B0L%98%DE%A4%8D%E2%D8%C8%DC%D6%F3-L%2FyS%22%C3%19%FC%D8%CF%99%B1%B1%9A%F3%E2%82Z%B7%0C%0B%ABJ%88H%80%B0%09%04%13%22%7EI%ABi%24%D9%F3%C9%E5%0C%7CB%80%28%DF%3C%EC%CB%BA%8By%3E8%27%9B%CFwDk%93d%E0%81  -O boostdesc.zip && 
    unzip -q /tmp/workdir/boostdesc.zip -d /opencv_contrib/modules/xfeatures2d/src/  && 
    unzip -q /tmp/workdir/boostdesc.zip -d /opencv_contrib/modules/xfeatures2d/test/  && 
    rm -rf /tmp/workdir/boostdesc.zip && 
# Python Path,获取虚拟环境的路径、解释器、头文件呢、库文件路径
    # source activate torch_37  && 
    OPENCV_PYTHON_EXECUTABLE_ANACONDA=$(which python${PYTHON_VERSION}) && 
    OPENCV_INSTALL_PATH=$(python -c "import sys; print(sys.prefix)") && 
    OPENCV_INCLUDE_DIR_ANACONDA=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") && 
    OPENCV_PACKAGE_ANACONDA=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") && 
    OPENCV_LIBRARY_ANACONDA=$(python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR'))") && 
    # conda deactivate && 
# Prepare Build
    mkdir /opencv/build && 
    cd /opencv/build && 
    cmake 
      -D INCLUDE_DIRS=${OPENCV_INCLUDE_DIR_ANACONDA} $INCLUDE_DIRS 
      -D LIBRARY_DIRS=$OPENCV_LIBRARY_ANACONDA $LIBRARY_DIRS 
      -D CMAKE_BUILD_TYPE=RELEASE 
      -D BUILD_PYTHON_SUPPORT=ON 
      -D BUILD_DOCS=ON 
      -D BUILD_PERF_TESTS=OFF 
      -D BUILD_TESTS=OFF 
      -D CMAKE_INSTALL_PREFIX=/usr/local/opencv 
      -D OPENCV_EXTRA_MODULES_PATH=/opencv_contrib/modules 
      -D BUILD_opencv_python3=ON 
      -D BUILD_opencv_python2=OFF 
      -D PYTHON${PYTHON_VERSION%%.*}_EXECUTABLE=${OPENCV_PYTHON_EXECUTABLE_ANACONDA} 
      -D PYTHON${PYTHON_VERSION%%.*}_INCLUDE_DIR=${OPENCV_INCLUDE_DIR_ANACONDA} 
      -D PYTHON${PYTHON_VERSION%%.*}_PACKAGES_PATH=${OPENCV_PACKAGE_ANACONDA} 
      -D BUILD_EXAMPLES=OFF 
      -D WITH_GTK=ON 
      -D WITH_GTK_2_X=ON 
      -D WITH_IPP=ON 
      -D BUILD_TIFF=ON 
      -D BUILD_opencv_cvv=OFF 
      -D INSTALL_CREATE_DISTRIB=ON 
      -D WITH_FFMPEG=ON 
      -D WITH_GSTREAMER=ON 
      -D WITH_V4L=ON 
      -D WITH_LIBV4L=ON 
      -D WITH_TBB=ON 
      -D WITH_QT=ON 
      -D WITH_OPENGL=ON 
      -D WITH_CUDA=ON 
      -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda 
      -D CMAKE_LIBRARY_PATH=/usr/local/cuda/lib64/stubs 
      ## 注意这里算力7.5对应2080Ti显卡,需要根据物理机GPU型号更改,或者全部加入
      -D CUDA_ARCH_BIN="7.5" 
      -D CUDA_ARCH_PTX="" 
      -D WITH_CUBLAS=ON 
      -D WITH_NVCUVID=ON 
      -D ENABLE_FAST_MATH=1 
      -D CUDA_FAST_MATH=1 
      -D ENABLE_PRECOMPILED_HEADERS=OFF 
      .. && 
      ldconfig && 
# Build, Test and Install
    cd /opencv/build && 
    make -j$(nproc) && 
    make install && 
    mkdir /workspace && 
    cd /workspace && 
    rm -rf /opencv && 
    rm -rf /opencv_contrib && 
    ldconfig && 
# NVENC and NvFBC patches for Nvidia drivers
    git clone https://gitee.com/xsxsxsxsxs/nvidia-patch.git && 
    cp nvidia-patch/patch.sh /usr/local/bin/patch.sh && 
    cp nvidia-patch/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh && 
    mkdir -p  /patched-lib  && 
    chmod +x /usr/local/bin/patch.sh /usr/local/bin/docker-entrypoint.sh   && 
# Create Project
    unzip -q /tmp/workdir/rail-welding-dev.zip -d /workspace/  && 
    rm -rf /tmp/workdir

ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
WORKDIR /workspace/rail-welding-dev

cmake配置结果类似如下:

原文地址:https://www.cnblogs.com/geoffreyone/p/14765124.html