OpenCV使用指南(v2.1)

更新时间:
复制为 MD 格式

文档版本

作者

发布日期

说明

0.8

Haiyong

初始版本

1.0

Haiyong

更新opencv-python

1.5

Haiyong

补充修改 "已知问题”

2.1

ShangJun

版本更新

1. 概述

OpenCV 是一个广泛使用的开源计算机视觉库,提供图像处理、视频分析、特征提取、目标检测等丰富功能,适用于科研、工业和嵌入式开发等多种场景,它同时支持 CUDA 硬件加速,可将部分图像视频编解码,图像处理、滤波、几何变换、特征计算等操作卸载到GPU 上执行。
PPU SDK 可以兼容支持OpenCV的硬件加速能力,目前已支持最新的OpenCV版本为4.13。

带有硬件加速能力的opencv-python库: **opencv_contrib_python **已加入SAIL pip源,最新版本是4.13.0.90, 可直接pip install进行安装:

pip install opencv-contrib-python==4.13.0.90 -i https://art-pub.eng.t-head.cn/artifactory/api/pypi/pypi_index/simple --force-reinstall

如下文档介绍如何自行定制编译带硬件加速能力 OpenCV 和 OpenCV-python 包。

说明

在安装或者自行编译安装带硬件加速能力 的OpenCV 和 OpenCV-python 包之前,建议先卸载环境中已经安装的OpenCVOpenCV-python包。

2. 编译安装opencv

2.1 下载代码

    git clone --branch 4.13.0 --depth 1 https://github.com/opencv/opencv.git
    git clone --branch 4.13.0 --depth 1 https://github.com/opencv/opencv_contrib.git
    git clone --branch 4.13.0 --depth 1 https://github.com/opencv/opencv_extra.git
    
    cd opencv
    ln -sf ../opencv_contrib opencv_contrib

2.2 准备脚本

编译前请确认已经安装PPU SDK并执行了envsetup.sh,配置好SDK的环境

编译删除了一些模块,尽可能多的打开了cuda加速模块,用户可以根据自己的实际需要做增删修改:

mkdir build
cd build

cmake_option=""

# 根据需要配置SKIP modules,这里的skip只是示例,用户可以取消
SKIP_LIST=(xfeatures2d matlab xobjdetect xphoto wechat_qrcode)  
SKIP_DEFINES=''
for m in ${SKIP_LIST[@]}; do
    SKIP_DEFINES+=" -DBUILD_opencv_${m}=OFF"
done
cmake_option+=" ${SKIP_DEFINES}"

# 根据需要增加需要的module,这里打开了尽可能多的cuda加速modules
ENABLE_LIST=(legacy ximgproc cudev cudastereo cudaarithm cudaimgproc cudacodec cudafilters cudawarping cudaoptflow cudabgsegm cudafeatures2d cudaobjdetect cudalegacy)
ENABLE_DEFINES=''
for m in ${ENABLE_LIST[@]}; do
    ENABLE_DEFINES+=" -DBUILD_opencv_${m}=ON"
done
cmake_option+=" -DWITH_CUDA=ON -DWITH_CUDNN=ON -DWITH_CUBLAS=ON -DWITH_CUFFT=ON -DOPENCV_DNN_CUDA=ON -DCUDA_ARCH_BIN=80 -DWITH_NVCUVID=ON"
cmake_option+=" -DOPENCV_ENABLE_NONFREE=ON"
cmake_option+=" ${ENABLE_DEFINES}"

# 关掉了一些不是必须的选项,用户可以取消
cmake_option+=" -DWITH_OPENCL=OFF -DOPENCV_DNN_OPENCL=OFF"
cmake_option+=" -DWITH_ANDROID_MEDIANDK=OFF -DWITH_GTK=OFF -DWITH_IPP=OFF -DBUILD_JAVA=OFF"
cmake_option+=" -DWITH_V4L=OFF -DWITH_GSTREAMER=OFF -DWITH_1394=OFF"

# 指定opencv contrib位置,这里放在opencv目录下一级
cmake_option+=" -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules/"

# 这里指定编译安装位置在源码上一级目录;如果不指定,make install会安装到/usr/local目录
cmake_option+="-DOPENCV_GENERATE_PKGCONFIG -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=../"

2.3 配置FFmpeg支持

如果系统没有安装FFmpeg,在opencv configure时,仅仅打开-DWITH_FFMPEG=ON,编译是无法找到ffmpeg的,最终编译的libopencv_videoio.so不会包含对ffmpeg的支持。

有关FFmpeg的编译和使用,可以参考另一篇指南文档 “Video FFmpeg使用指南”。

假设你的FFmpeg安装目录是 FFMPEG_PATH,在build_opencv.sh中补充如下脚本:

export PKG_CONFIG_LIBDIR=$FFMPEG_PATH/lib/pkgconfig:$PKG_CONFIG_LIBDIR
cmake_option+=" -DWITH_FFMPEG=ON -DOPENCV_FFMPEG_USE_FIND_PACKAGE=ON -DOPENCV_FFMPEG_SKIP_BUILD_CHECK=ON -DFFMPEG_DIR=./"

配置成功,在编译的时候可以看到(Yes后面显示的是本地的FFmpeg版本):

--   Video I/O:
--     FFMPEG:                      YES (find_package)
--       avcodec:                   YES (60.31.102)
--       avformat:                  YES (60.16.100)
--       avutil:                    YES (58.29.100)
--       swscale:                   YES (7.5.100)
--       avresample:                NO

请把ffmpeg目录指向自编译的支持硬件加速的ffmpeg安装目录。

2.4 配置testcasesamples

增加如下option可以编译并安装opencv自带的testcasestestdata,此项不是必须的:

cmake_option+=" -DBUILD_PERF_TESTS=ON -DBUILD_TESTS=ON -DINSTALL_TESTS=ON -DOPENCV_TEST_DATA_PATH=../opencv_extra/testdata"

这里opencv_extratest data所在目录,前面的脚本已经从github下载了。

2.5 编译

cmake $cmake_option ..
make -j && make install

2.6 运行示例

进入安装目录下的bin目录:

cd ../bin
export LD_LIBRARY_PATH=$FFMPEG_PATH/lib:../lib:$LD_LIBRARY_PATH  # 把ffmpeg和opencv lib目录加入LD_LIBRARY_PATH
export OPENCV_TEST_DATA_PATH=../share/opencv4/testdata  # testdata是git clone https://github.com/opencv/opencv_extra.git得到的目录

可以执行相关native测试程序。

3. 编译安装opencv-python

3.1 下载代码

git clone --branch 90 --depth 1 https://github.com/opencv/opencv-python.git

因为上面我们编译的是opencv 4.13,所以这里需要下载对应的opencv-python版本。

3.2 修改setup.py

我们可以直接使用 #2.1 已经下载好的opencvopencv_contrib代码,不需要重新下载

cd opencv-python
rm opencv opencv_contrib opencv_extra multibuild -r
# 假设opencv-python, opencv, opencv_contrib都在同一个目录
ln -sf ../opencv opencv
ln -sf ../opencv_contrib opencv_contrib
ln -sf ../opencv_extra opencv_extra
git clone https://github.com/multi-build/multibuild.git

修改setup.py,去掉对submodulegit update,更改编译options(修改项跟上面#2.2差不多,可以根据需要自行增删):

diff --git a/setup.py b/setup.py
index e25e51b..cb8da9b 100755
--- a/setup.py
+++ b/setup.py
@@ -187,6 +187,49 @@ def main():
             "-DBUILD_DOCS=OFF",
             "-DPYTHON3_LIMITED_API=ON",
             "-DBUILD_OPENEXR=ON",
+            "-DWITH_OPENCL=OFF",
+            "-DOPENCV_DNN_OPENCL=OFF",
+            "-DWITH_FFMPEG=ON",
+            "-DOPENCV_FFMPEG_USE_FIND_PACKAGE=ON",
+            "-DOPENCV_FFMPEG_SKIP_BUILD_CHECK=ON",
+            "-DWITH_CUDA=ON",
+            "-DWITH_CUDNN=ON",
+            "-DWITH_CUBLAS=ON",
+            "-DWITH_CUFFT=ON",
+            "-DOPENCV_DNN_CUDA=ON",
+            "-DCUDA_ARCH_BIN=80",
+            "-DWITH_NVCUVID=ON",
+            "-DWITH_V4L=OFF",
+            "-DWITH_GSTREAMER=OFF",
+            "-DWITH_1394=OFF",
+            "-DWITH_ANDROID_MEDIANDK=OFF",
+            "-DWITH_GTK=OFF",
+            "-DWITH_IPP=OFF",
+            "-DBUILD_JAVA=OFF",
+            "-DWITH_VTK=OFF",
+            "-DENABLE_FLAKE8=OFF",
+            "-DENABLE_PYLINT=OFF",
+            "-DBUILD_opencv_legacy=ON",
+            "-DOPENCV_ENABLE_NONFREE=ON",
+            "-DBUILD_opencv_xfeatures2d=OFF",
+            "-DBUILD_opencv_matlab=OFF",
+            "-DBUILD_opencv_xobjdetect=OFF",
+            "-DBUILD_opencv_xphoto=OFF",
+            "-DBUILD_opencv_wechat_qrcode=OFF",
+            "-DBUILD_opencv_ximgproc=ON",
+            "-DBUILD_opencv_cudev=ON",
+            "-DBUILD_opencv_cudastereo=ON",
+            "-DBUILD_opencv_legacy=ON",
+            "-DOPENCV_ENABLE_NONFREE=ON",
+            "-DBUILD_opencv_xfeatures2d=OFF",
+            "-DBUILD_opencv_matlab=OFF",
+            "-DBUILD_opencv_xobjdetect=OFF",
+            "-DBUILD_opencv_xphoto=OFF",
+            "-DBUILD_opencv_wechat_qrcode=OFF",
+            "-DBUILD_opencv_ximgproc=ON",
+            "-DBUILD_opencv_cudev=ON",
+            "-DBUILD_opencv_cudastereo=ON",
         ]
         + (
             # CMake flags for windows/arm64 build

3.3 编译

依赖skbuild,可以 pip install scikit-build

export ENABLE_CONTRIB=1
python3 setup.py bdist_wheel

3.4 安装

编译生成的opencv_contrib_python-4.13.0.90-cp37-cp37m-linux_x86_64.whldist目录下

pip install dist/opencv_contrib_python-4.13.0.90-cp37-cp37m-linux_x86_64.whl

此时可以进入python交互页面,输入 import cv2看看能否成功。

4. 已知问题

  • cuBLAS

    • GEMM:cublasCgemm_v2 is not supported.

  • cuFFT:

    • Dft/Convolve:cufftPlan2d is not supported.

  • cudacodec:

    • 不支持MPEG4/MPEG2/VC1/VP8等比较旧的视频格式

  • cudaoptflow

    • 部分测试项不支持,PPU没有opt flow 硬件

除此之外,还会有少量native测试项在PPU上会失败,经过分析都是可以跳过的,主要包括如下情况:

  • 结果不一致,浮点精度有较小的误差,但在ulp许可范围。这其中有一些测试项在NV A100卡上也一样会Fail。

  • kernel代码变量没有初始化为0,或者分配的GPU内存没有memset0导致的结果差异:在NV的环境下,局部变量和分配的设备内存会被默认初始化为0,但PPU不会。

  • 算子或者算法采用不相同导致的结果差异。

5. 使能示例

Ultralytics yolov5使用opencv-python做目标检测模型推理的前处理和后处理的硬件编解码加速

https://github.com/ultralytics/yolov5.git

前处理使能PPU Video解码硬件加速,需要显式使用FFmpegVideoCapture,并配置cuvid硬件加速的选项,参考下面的代码段:

+os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "hwaccel;cuvid|video_codec;h264_cuvid|vsync;0"

- cap = cv2.VideoCapture(path)

+cap = cv2.VideoCapture(path, cv2.CAP_FFMPEG)

后处理cv2.VideoWriter默认使用FFmpeg进行视频编码,如果按照该文档配置了硬件加速的FFmpeg

默认会走到硬件编码,无需修改代码:

result = cv2.VideoWriter("object_tracking.mp4",
                       cv2.VideoWriter_fourcc(*'avc1'),
                       fps,
                       (w, h))