Pull to refresh

Кросс-компиляция OpenCV 4 для Raspberry Pi и BeagleBone Black

Reading time 11 min
Views 12K
Всем привет.

Когда я захотел установить OpenCV на свою малинку для одного проекта, я был сильно разочарован результатом. Оказалось, что для новых версий образов Raspbian с поддержкой Python3.7 невозможно установить из репозитория библиотеку столь привычной командой pip install.

Причины
pip install opencv-python выдал неожиданный для меня результат: «Could not find a version that satisfies the requirement ...». Абсолютно недавно таким образом я ставил эту библиотеку на своем основном компьютере, и результат был положительный.

Когда я перепроверил себя на криворукость и убедился, что все еще способен правильно набрать команду из 25 символов без опечаток, настало время выяснить, что еще могло повлиять на результат.

Многое прояснила официальная страница opencv-python на pypi.org:
… Note that the wheel (especially manylinux) format does not currently support properly ARM architecture so there are no packages for ARM based platforms in PyPI. However, opencv-python packages for Raspberry Pi can be found from www.piwheels.org.

… Обратите внимание, что формат wheel (особенно manylinux) в настоящее время не поддерживает должным образом архитектуру ARM, поэтому в PyPI нет пакетов для платформ на основе ARM. Однако пакеты opencv-python для Raspberry Pi можно найти по адресу www.piwheels.org.
Окей…

Проверил, что raspberry тянет пакеты из правильного источника, но последний блок сайта расставил все на свои места:
Wheels provided support all Raspberry Pi models (Pi 3, Pi 2, Pi 1 and Pi Zero). Wheels are provided for Raspbian Jessie (Python 3.4) and Raspbian Stretch (Python 3.5). We plan to add support for Raspbian Buster (Python 3.7) in due course.

Предоставленные wheel поддерживают все модели Raspberry Pi (Pi 3, Pi 2, Pi 1 и Pi Zero. Wheel поддерживают Raspbian Jessie (Python 3.4) и Raspbian Stretch (Python 3.5) Мы планируем добавить поддержку Raspbian Buster (Python 3.7) в свое время.
Я уже был готов к бессонной ночи с компиляцией OpenCV на малинке, но вспомнил про статью о кросс-компиляции библиотеки (недаром же нам преподаватели в институте предлагали по ней делать лабораторную вместо методичек). Немного изменив параметры из статьи (нужно было добавить импорт для python3 и проверить, все ли библиотеки есть для OpenCV 4.1.0 ), я смог бы добиться вожделенного мной результата.

Однако лень взяла вверх, и я начал искать готовые решения такой проблемы. Так я наткнулся на эту статью. Следуя ей, я собрал всё с первого раза без танцев с бубнами и других шаманских ритуалов. Думаю, эта статья будет полезна и другим.

Представляю мой вольный перевод статьи «Cross compiling OpenCV 4 for Raspberry Pi and BeagleBone Black» Paul Silisteanu. Возможно, кому-то он сэкономит минуты или часы, которые можно потратить на более интересное занятие, чем игру в детектива.

От себя я добавил некоторые примечания к переводу, которые посчитал важными: [они выделены в тексте].

Приятного прочтения!

Кросс-компиляция OpenCV 4 для Raspberry Pi и BeagleBone Black


В этой статье я покажу вам, как установить последнюю версию OpenCV для Raspberry Pi и BeagleBone Black, используя кросс-компиляцию. На момент написания этой статьи [ее обновление на момент перевода — 17.07.2019] последняя версия OpenCV – 4.1.0, а версия, поставляемая со стандартными ОС, была 3.2.0. Конечно, возможно собрать OpenCV из исходников непосредственно на Raspberry или BeagleBone Black, но это может занять несколько часов. А кросс-компиляция OpenCV для armhf — это процесс продолжительностью 20-30 минут. И, в зависимости от скорости вашего компьютера, он может быть еще быстрее.

Я рекомендую делать сборку на виртуальной машине Debian Buster или в Docker контейнере, чтобы не захламлять вашу основную ОС. Если вы решили установить Buster на виртуальную машину, обязательно используйте минимальную сборку [Я рекомендую сделать именно так — проверил это на своей шкуре]. Очень важно начать с простой системы, потому что нам нужно установить исполняемые файлы и библиотеки armhf. Используя минимальную систему, мы избегаем потенциальные конфликты с родными версиями x86-64.

В статье описана работа только на Raspberry PI с системой Raspbian, но, если вы используете BeagleBone Black, все должно работать ровно так же.

Я предполагаю, что у вас уже есть чистая установленная Raspbian. Я использовал образ последней доступной desktop версии. На самом деле, вы можете следовать статье на Raspbian Lite, но я делал все свои тесты, используя версию с графическим интерфейсом.

Сначала давайте убедимся, что наша виртуальная машина или контейнер обновлены:

sudo apt update
sudo apt upgrade

Далее необходимо подключить armhf архитектуру.

sudo dpkg --add-architecture armhf
sudo apt update
sudo apt install qemu-user-static

На этом этапе вы сможете устанавливать библиотеки и приложения для armhf в своей системе и запускать их.

Мы собираемся собрать OpenCV с поддержкой Python и C++. Давайте установим Python2 и Python3, а также пакт NumPy для них:

sudo apt-get install python3-dev
sudo apt-get install python3-numpy
sudo apt-get install python-dev
sudo apt-get install python-numpy

Также нам понадобится libpython для armhf архитектуры:

sudo apt-get install libpython2-dev:armhf
sudo apt-get install libpython3-dev:armhf

Далее мы установим libgtk-3, чтобы иметь возможность писать простые программы с графическим интерфейсом. Если вы планируете использовать OpenCV исключительно в автономном режиме, вы можете спокойно игнорировать следующие две библиотеки:

$ sudo apt install libgtk-3-dev:armhf libcanberra-gtk3-dev:armhf

Нам также нужно установить несколько других библиотек, необходимых для OpenCV (поддержка различных форматов изображений и видео):

sudo apt install libtiff-dev:armhf zlib1g-dev:armhf
sudo apt install libjpeg-dev:armhf libpng-dev:armhf
sudo apt install libavcodec-dev:armhf libavformat-dev:armhf libswscale-dev:armhf libv4l-dev:armhf
sudo apt-get install libxvidcore-dev:armhf libx264-dev:armhf

Далее мы собираемся установить кросс-компиляторы для Debian, которые можно использовать для создания двоичных файлов armhf для Raspberry Pi:

sudo apt install crossbuild-essential-armhf
sudo apt install gfortran-arm-linux-gnueabihf

На момент написания этой статьи вышеприведенный набор инструментов основан на GCC версии 8.3, которая является такой же, как в Raspbian.

Наконец, мы установим Cmake, git, pkg-config и wget:

sudo apt install cmake git pkg-config wget

Далее мы можем скачать текущую версию OpenCV. Я покажу вам, как установить полную версию OpenCV (библиотеки по умолчанию и contrib):

cd ~
mkdir opencv_all && cd opencv_all
wget -O opencv.tar.gz https://github.com/opencv/opencv/archive/4.1.0.tar.gz
tar xf opencv.tar.gz
wget -O opencv_contrib.tar.gz https://github.com/opencv/opencv_contrib/archive/4.1.0.tar.gz
tar xf opencv_contrib.tar.gz
rm *.tar.gz

Нам нужно временно изменить две системные переменные, необходимые для успешной сборки поддержки GTK +:

export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig
export PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig

На данный момент мы можем использовать Cmake для генерации скриптов сборки OpenCV:

cd opencv-4.1.0
mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/opt/opencv-4.1.0 \
    -D CMAKE_TOOLCHAIN_FILE=../platforms/linux/arm-gnueabi.toolchain.cmake \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_all/opencv_contrib-4.1.0/modules \
    -D OPENCV_ENABLE_NONFREE=ON \
    -D ENABLE_NEON=ON \
    -D ENABLE_VFPV3=ON \
    -D BUILD_TESTS=OFF \
    -D BUILD_DOCS=OFF \
    -D PYTHON2_INCLUDE_PATH=/usr/include/python2.7 \
    -D PYTHON2_LIBRARIES=/usr/lib/arm-linux-gnueabihf/libpython2.7.so \
    -D PYTHON2_NUMPY_INCLUDE_DIRS=/usr/lib/python2/dist-packages/numpy/core/include \
    -D PYTHON3_INCLUDE_PATH=/usr/include/python3.7m \
    -D PYTHON3_LIBRARIES=/usr/lib/arm-linux-gnueabihf/libpython3.7m.so \
    -D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \
    -D BUILD_OPENCV_PYTHON2=ON \
    -D BUILD_OPENCV_PYTHON3=ON \
    -D BUILD_EXAMPLES=OFF ..

Описание параметров
CMAKE_INSTALL_PREFIX — Директория, где будут расположены собранные данные
CMAKE_TOOLCHAIN_FILE — Параметр, показывающий Cmake, что будет кросс-компиляция
OPENCV_EXTRA_MODULES_PATH — Путь до дополнительных модулей OpenCV
OPENCV_ENABLE_NONFREE=ON — Включить в сборку запатентованные алгоритмы
Обратите внимание, что на использование алгоритмов SIFT и SURF стоят патентные ограничения. И если вы планируете сборку для коммерческого использования, подумайте, нужны ли они вам, и ознакомьтесь с ограничениями.
ENABLE_NEON=ON — Включить инструкции NEON для оптимизации для ARM
ENABLE_VFPV3=ON — Включить инструкции VFPv3-D32 для оптимизации для ARM
BUILD_TESTS=OFF — Отключить правила для сборки тестов (так будет быстрее)
BUILD_DOCS=OFF — Отключить правила для сборки документации
PYTHON2_INCLUDE_PATH — Путь до python2.7
PYTHON2_LIBRARIES — Путь до скаченной ранее библиотеки libpython2
PYTHON2_NUMPY_INCLUDE_DIRS — Путь до NumPy для python2.7
PYTHON3_INCLUDE_PATH — Путь до python3
PYTHON3_LIBRARIES — Путь до скаченной ранее библиотеки libpython3
PYTHON3_NUMPY_INCLUDE_DIRS — Путь до NumPy для python3
BUILD_OPENCV_PYTHON2=ON — Включить в сборку правила для python2
BUILD_OPENCV_PYTHON3=ON — Включить в сборку правила для python4
BUILD_EXAMPLES=OFF — Отключить правила для сборки всех примеров

Если у вас не было ошибок, то в результате вы получите Makefile в папке сборки. Теперь мы можем начать фактическую сборку:

make -j16

[В статье указано 16 параллельных процессов при сборки, но этот параметр нужно будет подбирать под вашу хостовую ОС]

После завершения фазы сборки мы можем установить библиотеку:

sudo make install/strip

Затем нам нужно изменить имя библиотеки, которую установщик по ошибке назвал библиотекой x86_64, хотя на самом деле она является armhf:

cd /opt/opencv-4.1.0/lib/python3.7/dist-packages/cv2/python-3.7/
sudo cp cv2.cpython-37m-x86_64-linux-gnu.so cv2.so

Давайте сожмем установочную папку и сохраняем архив в домашней директории:

cd /opt
tar -cjvf ~/opencv-4.1.0-armhf.tar.bz2 opencv-4.1.0
cd ~

Чтобы сделать нашу жизнь проще, я также подготовил простой файл настроек pkg-config с именем opencv.pc. Скачать его вы сможете таким образом:

git clone https://gist.github.com/sol-prog/ed383474872958081985de733eaf352d opencv_cpp_compile_settings
cd opencv_cpp_compile_settings
cp opencv.pc ~
cd ~

[На самом деле, необязательно это делать на хостовой машине. Скачать файл можно сразу на Raspberry. Но автор пожелал сделать это именно в такой последовательности]

opencv.pc
Поскольку файл относительно небольшой, позволю себе его вставить в текст статьи:

libdir = /opt/opencv-4.1.0/lib
includedir = /opt/opencv-4.1.0/include/opencv4

Name: OpenCV
Description: OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library.
Version: 4.1.0
Libs: -L${libdir} -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_calib3d -lopencv_ccalib -lopencv_core -lopencv_datasets -lopencv_dnn_objdetect -lopencv_dnn -lopencv_dpm -lopencv_face -lopencv_features2d -lopencv_flann -lopencv_freetype -lopencv_fuzzy -lopencv_gapi -lopencv_hfs -lopencv_highgui -lopencv_imgcodecs -lopencv_img_hash -lopencv_imgproc -lopencv_line_descriptor -lopencv_ml -lopencv_objdetect -lopencv_optflow -lopencv_phase_unwrapping -lopencv_photo -lopencv_plot -lopencv_quality -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_shape -lopencv_stereo -lopencv_stitching -lopencv_structured_light -lopencv_superres -lopencv_surface_matching -lopencv_text -lopencv_tracking -lopencv_videoio -lopencv_video -lopencv_videostab -lopencv_xfeatures2d -lopencv_ximgproc -lopencv_xobjdetect -lopencv_xphoto
Cflags: -I${includedir}


Скопируйте opencv-4.1.0-armhf.tar.bz2 и opencv.pc из вашей домашней папки в RPi.

В следующей части статьи я предполагаю, что вы все выполняете уже на вашей Raspberry Pi.

Убедитесь, что в вашем RPi есть все библиотеки разработки, которые мы использовали. Как и раньше, если вы не планируете использовать GTK +, игнорируйте первую строку из следующих команд. Большинство из этих библиотек должны быть уже установлены, если вы используете полную версию Raspbian:

sudo apt install libgtk-3-dev libcanberra-gtk3-dev
sudo apt install libtiff-dev zlib1g-dev
sudo apt install libjpeg-dev libpng-dev
sudo apt install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev

Распакуйте и переместите библиотеку в папку /opt вашего RPi:

tar xfv opencv-4.1.0-armhf.tar.bz2
sudo mv opencv-4.1.0 /opt

При желании вы можете стереть архив:

rm opencv-4.1.0-armhf.tar.bz2

Далее давайте также переместим opencv.pc в папку, где pkg-config сможет найти его:

sudo mv opencv.pc /usr/lib/arm-linux-gnueabihf/pkgconfig

Чтобы операционная система могла найти библиотеки OpenCV, нам нужно добавить их в путь к библиотеке:

echo 'export LD_LIBRARY_PATH=/opt/opencv-4.1.0/lib:$LD_LIBRARY_PATH' >> .bashrc
source .bashrc

Выйдите и войдите в систему или перезапустите Терминал.

Далее создадим несколько символических ссылок, которые позволят Python загружать вновь созданные библиотеки:

sudo ln -s /opt/opencv-4.1.0/lib/python2.7/dist-packages/cv2 /usr/lib/python2.7/dist-packages/cv2
sudo ln -s /opt/opencv-4.1.0/lib/python3.7/dist-packages/cv2 /usr/lib/python3/dist-packages/cv2

На этом этапе вы сможете использовать библиотеку OpenCV из C ++ или Python.
В репозитории для этой статьи вы можете найти несколько тестовых программ на C ++ и Python. Вы можете скачать код на своем Pi с помощью команд:

git clone https://github.com/sol-prog/raspberry-pi-opencv.git
cd raspberry-pi-opencv/tests

Есть два автономных теста, которые вы можете использовать, даже если у вас нет дисплея, подключенного к вашему RPi: cli_cpp_test.cpp и cli_python_test.py. Я также включил два графических теста, которые требуют отображения: gui_cpp_test.cpp и gui_python_test.py.

Вы можете создавать и запускать тесты C ++ следующим образом:

g++ cli_cpp_test.cpp -o cli_cpp_test `pkg-config --cflags --libs opencv`
./cli_cpp_test

И, если у вас есть дисплей, подключенный к вашему RPi:

g++ gui_cpp_test.cpp -o gui_cpp_test `pkg-config --cflags --libs opencv`
./gui_cpp_test

Вот скриншот теста C ++ GUI, выполняющегося на моем Pi:



Для тестов Python используйте:

python3 cli_python_test.py

или

python3 gui_python_test.py

Как примечание, также возможна кросс-компиляция программ на C ++, использующих OpenCV в вашей системе Debian x86-64, и запуск двоичного кода на вашем RPi.

[Далее в статье автор рекомендует к прочтению книгу Дерека Моллоя о программировании для RaspberryPi. Реферальную ссылку на книгу вы можете найти в оригинале статьи].
Ссылка на оригинал статьи

Небольшое дополнение от себя
Я подготовил Dockerfile, который позволит выполнить все действия из статьи, не разворачивая виртуальную машину.

Процесс установки:
Создаем Dockerfile.

mkdir opencv && cd opencv && mkdir armhf_opencv
touch armhf_opencv/Dockerfile
nano armhf_opencv/Dockerfile

Далее вставляем в Dockerfile код и после этого запускаем сборку образа.

docker image build armhf_opencv/

После окончания сборки вы должны увидеть идентификатор собранного образа:

>>> Successfully built babdc99ba2d8

Используем этот идентификатор для установки тега для образа и запустим его:

docker tag babdc99ba2d8 armhf_opencv:latest
docker run armhf_opencv

После запуска контейнера необходимо из него выкачать собранный архив и файл opencv.pc. Для этого нам понадобится его идентификатор:

docker container ls  --all
>>> CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                      PORTS               NAMES
>>> 369dff5a0a9b        armhf_opencv            "bash"                   9 seconds ago       Exited (0) 7 seconds ago                        affectionate_wu

Скопируем нужные нам файлы в текущую директорию:

docker cp 369dff5a0a9b:/root/opencv-4.1.0-armhf.tar.bz2 ./
docker cp 369dff5a0a9b:/root/opencv.pc ./

После этого рекомендую удалить image, поскольку он занимает 2.5ГБ места.

Сборка через docker на моем i59600К с 16ГБ заняла около 30-40 минут, при этом много времени было затрачено на скачивание данных с репозитория.

Далее процесс установки на Raspberry Pi ничем не отличается от описанного в статье.

Сам Dockerfile:

FROM debian:buster
USER root

RUN apt update && apt upgrade

RUN dpkg --add-architecture armhf && \
    apt update && apt install -y qemu-user-static

RUN apt install -y python3-dev python3-numpy python-dev python-numpy

RUN apt install -y libpython2-dev:armhf libpython3-dev:armhf \
    libgtk-3-dev:armhf libcanberra-gtk3-dev:armhf \ 
    libtiff-dev:armhf zlib1g-dev:armhf \
    libjpeg-dev:armhf libpng-dev:armhf \ 
    libavcodec-dev:armhf libavformat-dev:armhf \
    libswscale-dev:armhf libv4l-dev:armhf \
    libxvidcore-dev:armhf libx264-dev:armhf

RUN apt install -y crossbuild-essential-armhf gfortran-arm-linux-gnueabihf
RUN apt install -y cmake git pkg-config wget

RUN mkdir opencv_all && cd opencv_all && \
    wget -O opencv.tar.gz https://github.com/opencv/opencv/archive/4.1.0.tar.gz  && \
    tar -xf opencv.tar.gz -C /tmp  && \
    wget -O opencv_contrib.tar.gz https://github.com/opencv/opencv_contrib/archive/4.1.0.tar.gz  && \
    tar -xf opencv_contrib.tar.gz -C /tmp  && \
    rm *.tar.gz  && \
    export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig && \
    export PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig && \
    cd /tmp/opencv-4.1.0 && mkdir build && cd build && \
    cmake -D CMAKE_BUILD_TYPE=RELEASE \
        -D CMAKE_INSTALL_PREFIX=/opt/opencv-4.1.0 \
        -D CMAKE_TOOLCHAIN_FILE=../platforms/linux/arm-gnueabi.toolchain.cmake \
        -D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv_contrib-4.1.0/modules \
        -D OPENCV_ENABLE_NONFREE=ON \
        -D ENABLE_NEON=ON \
        -D ENABLE_VFPV3=ON \
        -D BUILD_TESTS=OFF \
        -D BUILD_DOCS=OFF \
        -D PYTHON2_INCLUDE_PATH=/usr/include/python2.7 \
        -D PYTHON2_LIBRARIES=/usr/lib/arm-linux-gnueabihf/libpython2.7.so \
        -D PYTHON2_NUMPY_INCLUDE_DIRS=/usr/lib/python2/dist-packages/numpy/core/include \
        -D PYTHON3_INCLUDE_PATH=/usr/include/python3.7m \
        -D PYTHON3_LIBRARIES=/usr/lib/arm-linux-gnueabihf/libpython3.7m.so \
        -D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \
        -D BUILD_OPENCV_PYTHON2=ON \
        -D BUILD_OPENCV_PYTHON3=ON \
        -D BUILD_EXAMPLES=OFF .. && \
    make -j6 && make install/strip

RUN cd /opt/opencv-4.1.0/lib/python3.7/dist-packages/cv2/python-3.7/ && \
    cp cv2.cpython-37m-x86_64-linux-gnu.so cv2.so

RUN cd /opt && tar -cjvf /root/opencv-4.1.0-armhf.tar.bz2 opencv-4.1.0 

RUN git clone https://gist.github.com/sol-prog/ed383474872958081985de733eaf352d opencv_cpp_compile_settings && \
    cd opencv_cpp_compile_settings && \
    cp opencv.pc /root/ 

Tags:
Hubs:
+22
Comments 6
Comments Comments 6

Articles