Сборка OpenCV с поддержкой NVIDIA GPU

Использование нейронных сетей (да, сейчас это модно) дает дополнительные возможности в области безопасности, а имнно в охранных системах видеонаблюдения. Имея хороший процессор или мощную видеокарту, вы, фактически на лету можете анализировать видеопоток с камер, классифицируя (classification) или находя необходимые объекты (object detection) в кадре. Последующий детальный анализ таких кадров трудно переоценить.


Для запуска нейросетки нужен «движок». Без «движка» нейросетка всего лишь двоичный файл на диске и пользы от него нет.

Есть два популярных способа запустить нейросетку:
1) используя родной «движок» на котором эта сеть и была обучена (например установить в систему библиотеки Tensorflow);
2) взять «движок» стороннего производителя, который понимает такую нейросеть и умеет пропускать изображения через нее.

В этой статье мы будем собирать из исходников «движок» типа 2, от стороннего производителя, а именно OpenCV. Этот пакет умеет работать со многими типами нейронных сетей использую модуль «Deep Neural Network» (dnn), а с недавнего времени dnn научился запускать их и на GPU.

Нейросеть лучше запускать на графическом ускорителе (gpu). Именно графические ускорители Nvidia с технологией CUDA, дают значительное ускорение при работе нейросетей. Поэтому пакет OpenCV мы будем компилировать с поддержкой GPU.

Собирать будем под Linux. Неважно какой LInux. Можно Ubuntu, можно CentOS. Разницы нет никакой, кроме начального этапа. Инструкция универсальная и привязка к дистрибутиву сведена к минимуму.

При установке будем придерживаться следующих принципов:

  1. Как можно меньше использовать учетную запись «root» (только для установки самых необходимых библиотек).
  2. Ставить все в домашнюю директорию и ничего «не размазывать по системе».
  3. Придерживаться принципа «все свое ношу с собой», для этого в домашней директории создадим папку, например «system» и все будем складывать в нее.

NVidia драйвер и библиотеки CUDA

Перед тем, как приступить к сборке OpenCV необходимо, чтобы в вашей системе були установлены:

  1. Драйвер NVidia (гуглите как это делается именно для вашей конкретной системы).
  2. Библиотеки CUDA (вот здесь я подробно и с картиками рассказал, как это сделать.

Шаг 1 — устанавливаем необходимые библиотеки

Это очень важный шаг. Если на этом этапе не установить какую-то библиотеку, то сборщик OpenCV отметит для себя, что ее нет в системе и продолжит сборку дальше, а именно без этой фичи. А вы потом ищите, почему, например не работает экспорт в jpg. А все потому что libjpeg не был установлен и сборщик пропустил его. Лучше сразу все поставить, чтобы потом не бегать по stackoverflow с вопросами.

CentOS 8

dnf -y group install "Development Tools"

dnf -y install dnf-plugins-core

dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

rpm -ivh http://repo.okay.com.mx/centos/8/x86_64/release/okay-release-1-3.el8.noarch.rpm

dnf config-manager --set-enabled PowerTools

dnf -y install https://download.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
dnf localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
dnf -y install --nogpgcheck https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm

dnf -y install http://rpmfind.net/linux/epel/7/x86_64/Packages/s/SDL2-2.0.10-1.el7.x86_64.rpm

dnf -y install gcc gcc-c++ make \
        unzip openssl-devel pkgconfig libjpeg-devel libpng-devel libtiff-devel \
        ffmpeg ffmpeg-devel libv4l-devel xvidcore-devel x264-devel \
        gtk3-devel atlas atlas-devel ccache eigen3-devel protobuf protobuf-compiler \
        openblas-devel protobuf-devel leveldb-devel snappy-devel \
        hdf5-devel gflags-devel glog-devel lmdb-devel tbb tbb-devel \
        jasper-devel libdc1394-devel gstreamer1-devel hdf5-static \
        gstreamer1-libav, libffi-devel

 

Ubuntu

sudo apt-get install build-essential cmake unzip pkg-config \
        libjpeg-dev libpng-dev libtiff-dev \
        libavcodec-dev libavformat-dev libswscale-dev \
        libv4l-dev libxvidcore-dev libx264-dev \
        libgtk-3-dev libatlas-base-dev gfortran python3-dev \
        libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
        libtbb-dev qt5-default libatlas-base-dev \
        libfaac-dev libmp3lame-dev libtheora-dev \
        libvorbis-dev libxvidcore-dev libopencore-amrnb-dev \
        libopencore-amrwb-dev libavresample-dev \
        x264 v4l-utils libprotobuf-dev protobuf-compiler \
        libgoogle-glog-dev libgflags-dev \
        libgphoto2-dev libeigen3-dev libhdf5-dev doxygen \
        libffi6 libffi-dev libblas3 libboost-all-dev

Библиотеки установлены. Все последующие шаги не будут зависить от конкретного дистрибутива Linux. Поэтому инструкции подойдут, как Ubuntu, так и любому другому Linux.

Шаг 2 — устанаваливаем необходимый софт

Для сборки opencv потребуется установить некоторый софт. Скорей всего это уже установлено на вашем компьютере, но непонятно какой версии. Поэтому лучше собрать все из исходников. Для этого создаем в домашней директории папку «system»:

mkdir ~/system

В этой папке будут установлены вспомогательные программы и сама библиотека opencv.

cmake

Для сборки opencv требуется cmake причем довольно свежий. Качаем из официального репо и распаковываем в ~/system

cd ~/system
wget https://github.com/Kitware/CMake/releases/download/v3.19.5/cmake-3.19.5-Linux-x86_64.tar.gz
tar zxvf cmake-3.19.5-Linux-x86_64.tar.gz
cd cmake-3.19.5-Linux-x86_64
mv * ../
cd ../
rm -rf cmake*

 

Сразу же добавляем cmake в путь для поиска:

export PATH=~/system/bin:$PATH

И проверяем:

which cmake
cmake --version
cmake version 3.19.5

Python

Если вас устраивает Python, установленный в вашей системе, то этот шаг можете пропустить. Я предпочитаю собирать Python из исходников (делается это быстро). Устанавливать все необходимые пакеты и пользоваться ужеэтой сборкой. Можно использовать еще Anaconda, но это кому как нравится.
Собираем Python из исходников:

wget https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz
tar zxvf Python-3.9.1.tgz
cd Python-3.9.1
./configure --prefix=/home/username/system
make
make install

ln -s ~/system/bin/python3 ~/system/bin/python
ln -s ~/system/bin/pip3 ~/system/bin/pip
cd ../
rm -rf Python*

Проверяем установку:

which python3
~/system/bin/python3
python3 --version
Python 3.8.1

устанавливаем дополнительные Python модули

pip install --upgrade pip
pip install flake8 imutils pylint protobuf pyserial

Шаг 5 — собираем OpenCV из исходников

Скачиваем свежую релизную версию с github:

cd ~/system
mkdir opencv_build
cd opencv_build
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.1.zip
unzip opencv.zip
mv opencv-4.5.1 opencv

wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.1.zip
unzip opencv_contrib.zip
mv opencv_contrib-4.5.1 opencv_contrib

Создаем скрипт для сборки:
build.sh

cd opencv
mkdir build
cd build

Редактируем build.sh и вставляем туда следующий код:

cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/home/username/system \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_CUDA=ON \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D CUDA_TOOLKIT_ROOT_DIR=/home/username/system/cuda \
-D ENABLE_FAST_MATH=1 \
-D CUDA_FAST_MATH=1 \
-D CUDA_ARCH_BIN=7.5 \
-D WITH_CUBLAS=1 \
-D OPENCV_EXTRA_MODULES_PATH=/home/username/system/opencv_build/opencv_contrib/modules \
-D HAVE_OPENCV_PYTHON3=ON \
-D PYTHON_DEFAULT_EXECUTABLE=/home/username/system/bin/python3 \
-D OPENCV_ENABLE_NONFREE=ON \
-D BUILD_EXAMPLES=ON ..

Это очень важный файл. Любая ошибка допущенная в нем сложно потом отлавливается. Поэтому проверьте все пути.
После того, как скрипт отработает появится следующий output.

Если сконфигурировали правильно, то должно быть как в зеленой рамочке.
Ну а дальше классическое:

make -j4
make install

Крайне рекомендую использовать мультипроцессорность при сборке (-j[кол-во ядер]). Сборка проходит очень медленно. На старом 4-х ядерном Intel i3 OpenCV собирался всю ночь.

После установки обязательно проверяем OpenCV Python модуль:

~/system/lib/python3.9/site-packages/cv2/python-3.9
ls -alp
8987416 Feb 17 18:36 cv2.cpython-39-x86_64-linux-gnu.so

Настраиваем environment, добавляем следующие строки в ~/.bashrc

export PATH=~/system/bin:$PATH
export LD_LIBRARY_PATH=~/system/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=~/system/cuda/lib64:$LD_LIBRARY_PATH
export PATH=~/system/cuda/bin:$PATH

Шаг 6 — проверка сборки openCV с GPU

Express проверка

cv2.cuda.getCudaEnabledDeviceCount() — количество видеокарт доступных OpenCV;
cv2.__version__ — установленная версия OpenCV.

python
Python 3.9.1 (default, Feb 17 2021, 16:04:10) 
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> count = cv2.cuda.getCudaEnabledDeviceCount()
>>> print(count)
1
>>> cv2.__version__
'4.5.1'
>>>

OpenCV dnn object detection

Реальный (боевой) пример использования OpenCV dnn библиотеки для запуска предобученной нейросети на Python.
За основу взят вот этот пример.
Я его слегка модифицировал для задействования gpu.
Скачиваем пример.
Распаковываем и запускаем:

python3 mobilenet_ssd_python.py --video vehicles.mp4

Для мониторинга нагрузки GPU запускаем еще одну терминалку и в ней:

watch -n 1 nvidia-smi

Почитать еще: