Mam谩 duerme tranquilamente por la noche: recolectamos OpenCV para Raspbian'a

Las 煤ltimas dos semanas han sido dif铆ciles para nuestro equipo. Se lanz贸 OpenCV 4 , y con 茅l, se prepararon para el kit de herramientas OpenVINO R4 de Intel , que incluye OpenCV. Piensas, estoy distra铆do por un tiempo, mirar茅, como siempre, sobre los foros de OpenCV y los comentarios de los usuarios, y aqu铆 est谩 de moda que digas que OpenCV no es IoT, que bajo Raspberry Pi es suficiente para ensamblar, no hay suficiente soldadura para poner make -j2 . por la ma帽ana estar谩 listo si tienes suerte.


Por lo tanto, propongo unir nuestras manos y ver c贸mo puede ensamblar la biblioteca OpenCV para un sistema operativo de 32 bits que se ejecuta en un procesador ARM utilizando los recursos de una m谩quina con sistema operativo de 64 bits, impulsado por una excelente arquitectura de CPU. Brujer铆a 隆Compilaci贸n cruzada, no de otra manera!


Declaraci贸n del problema.


Compilar directamente en el tablero, que com煤nmente se llama nativo, es realmente laborioso, por lo que aqu铆 consideraremos una forma de construir un proyecto que permita dispositivos inform谩ticos m谩s fuertes (llam茅moslos hosts) para preparar binarios para sus peque帽os familiares. Adem谩s, ambas m谩quinas pueden tener diferentes arquitecturas de CPU. Esta es una compilaci贸n cruzada.


Entonces, para preparar una tarta de frambuesa rellena con OpenCV, necesitamos:


  • Carcasa de acoplador de imagen Ubuntu 16.04
  • La m谩quina host es m谩s potente que la Raspberry Pi (de lo contrario, 驴cu谩l es el punto, no?)
  • Compilador cruzado para ARMhf, as铆 como bibliotecas de la arquitectura correspondiente

Todo el proceso de construcci贸n de OpenCV tendr谩 lugar en la m谩quina host. Yo uso Ubuntu en casa. Con otra versi贸n de Linux, los problemas de reproducci贸n no deber铆an ocurrir. Para los usuarios de Windows: mi sincero deseo de no rendirme y tratar de resolverlo por nosotros mismos.


Instalar Docker


Comenc茅 a conocer a Docker hace aproximadamente una semana, as铆 que agregue sal gourmet y az煤car sint谩ctica al gusto. Tres ingredientes son suficientes para usted y para m铆: Dockerfile, el concepto de imagen y contenedor.


Docker es una herramienta para crear y reproducir la configuraci贸n de cualquier sistema operativo con el conjunto de componentes necesarios. Dockerfile es un conjunto de comandos de shell que usualmente se usa en la m谩quina host, pero en este caso, todos se aplican a la llamada imagen de docker .


Para instalar Docker, considere la forma m谩s simple: solicite un paquete a trav茅s del servicio de entrega apt-get :


 sudo apt-get install -y docker.io 

Le daremos al docker daemon todo lo que pida y cerraremos la sesi贸n del sistema (observe el inicio de sesi贸n correspondiente).


 sudo usermod -a -G docker $USER 

Preparando el espacio de trabajo


Raspberry Pi (en mi caso RPI 2 Modelo B) en la preparaci贸n m谩s com煤n es una CPU ARMv7 con el sistema operativo Raspbian (basado en Debian). Crearemos una imagen docker basada en Ubuntu 16.04, en la que informaremos el compilador cruzado, las bibliotecas del ej茅rcito y recopilaremos OpenCV en el mismo lugar.


Crea un pap谩 donde se encuentre nuestro Dockerfile :


 mkdir ubuntu16_armhf_opencv && cd ubuntu16_armhf_opencv touch Dockerfile 

Agregue informaci贸n sobre el sistema operativo base y la arquitectura armhf para el instalador del paquete apt-get :


 FROM ubuntu:16.04 USER root RUN dpkg --add-architecture armhf RUN apt-get update 

Tenga en cuenta que los comandos como FROM ... , RUN ... son la sintaxis de Dockerfile y est谩n escritos en el archivo de prueba Dockerfile creado.


Volvamos al directorio principal ubuntu16_armhf_opencv e intentemos crear nuestra imagen acoplable:


 docker image build ubuntu16_armhf_opencv 

Durante la ejecuci贸n del comando apt-get update , deber铆a ver los errores del siguiente tipo: Err:[] [url] xenial[-] armhf Packages


 Ign:30 http://archive.ubuntu.com/ubuntu xenial-backports/main armhf Packages Ign:32 http://archive.ubuntu.com/ubuntu xenial-backports/universe armhf Packages Err:7 http://archive.ubuntu.com/ubuntu xenial/main armhf Packages 404 Not Found Ign:9 http://archive.ubuntu.com/ubuntu xenial/restricted armhf Packages Ign:18 http://archive.ubuntu.com/ubuntu xenial/universe armhf Packages Ign:20 http://archive.ubuntu.com/ubuntu xenial/multiverse armhf Packages Err:22 http://archive.ubuntu.com/ubuntu xenial-updates/main armhf Packages 404 Not Found Ign:24 http://archive.ubuntu.com/ubuntu xenial-updates/restricted armhf Packages Ign:26 http://archive.ubuntu.com/ubuntu xenial-updates/universe armhf Packages Ign:28 http://archive.ubuntu.com/ubuntu xenial-updates/multiverse armhf Packages Err:30 http://archive.ubuntu.com/ubuntu xenial-backports/main armhf Packages 404 Not Found Ign:32 http://archive.ubuntu.com/ubuntu xenial-backports/universe armhf Packages 

Si observa el archivo /etc/apt/sources.list cada error corresponde a alguna l铆nea, por ejemplo:


Error


 Err:22 http://archive.ubuntu.com/ubuntu xenial-updates/main armhf Packages 404 Not Found 

L铆nea en /etc/apt/sources.list :


 deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted 

Soluci贸n :
Romper en dos:


 deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted 

Por lo tanto, debe reemplazar varias fuentes de paquetes. En nuestra ventana acoplable, los reemplazaremos todos con un comando:


 RUN sed -i -E 's|^deb ([^ ]+) (.*)$|deb [arch=amd64] \1 \2\ndeb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ \2|' /etc/apt/sources.list 

Ahora apt-get update deber铆a funcionar sin errores.


Ponemos los paquetes necesarios


Necesitamos suministrar paquetes de host como git , python-pip , cmake y pkg-config , as铆 como crossbuild-essential-armhf , que es un conjunto de compiladores cruzados gcc / g ++ ( arm-linux-gnueabihf-gcc y arm-linux-gnueabihf-g++ ) y bibliotecas del sistema de la arquitectura correspondiente:


 RUN apt-get install -y git python-pip cmake pkg-config crossbuild-essential-armhf 

Desde lo inusual: tambi茅n descargamos GTK (utilizado para dibujar ventanas en el m贸dulo highgui), GStreamer y Python, pero con una indicaci贸n expl铆cita de una arquitectura extranjera:


 RUN apt-get install -y --no-install-recommends \ libgtk2.0-dev:armhf \ libpython-dev:armhf \ libgstreamer1.0-dev:armhf \ libgstreamer-plugins-base1.0-dev:armhf \ libgstreamer-plugins-good1.0-dev:armhf \ libgstreamer-plugins-bad1.0-dev:armhf 

Y luego clonamos y recolectamos, indicando las banderas necesarias:


 RUN git clone https://github.com/opencv/opencv --depth 1 RUN mkdir opencv/build && cd opencv/build && \ export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig && \ cmake -DCMAKE_BUILD_TYPE=Release \ -DOPENCV_CONFIG_INSTALL_PATH="cmake" \ -DCMAKE_TOOLCHAIN_FILE="../opencv/platforms/linux/arm-gnueabi.toolchain.cmake" \ -DWITH_IPP=OFF \ -DBUILD_TESTS=OFF \ -DBUILD_PERF_TESTS=OFF \ -DOPENCV_ENABLE_PKG_CONFIG=ON \ -DPYTHON2_INCLUDE_PATH="/usr/include/python2.7" \ -DPYTHON2_NUMPY_INCLUDE_DIRS="/usr/local/lib/python2.7/dist-packages/numpy/core/include" \ -DENABLE_NEON=ON \ -DCPU_BASELINE="NEON" .. 

donde


  • CMAKE_TOOLCHAIN_FILE : la ruta al archivo cmake que define el proceso de compilaci贸n cruzada (establece el compilador deseado, restringe el uso de bibliotecas de host.


  • WITH_IPP=OFF , - deshabilita las dependencias pesadas.


  • BUILD_TESTS=OFF , BUILD_PERF_TESTS=OFF , deshabilita la compilaci贸n de prueba.


  • OPENCV_ENABLE_PKG_CONFIG=ON - para que pkg-config pueda encontrar dependencias como GTK. PKG_CONFIG_PATH es la ruta correcta donde pkg-config buscar谩 bibliotecas.


  • PYTHON2_INCLUDE_PATH , PYTHON2_NUMPY_INCLUDE_DIRS : rutas necesarias para los contenedores de compilaci贸n cruzada para python2.


  • ENABLE_NEON=ON , CPU_BASELINE="NEON" - habilita la optimizaci贸n NEON.


  • OPENCV_CONFIG_INSTALL_PATH : ajusta la ubicaci贸n de los archivos en el directorio de install .



Lo principal a lo que debe prestar atenci贸n despu茅s de la ejecuci贸n de cmake es que todos los m贸dulos necesarios est谩n ensamblados (python2, por ejemplo):


 -- OpenCV modules: -- To be built: calib3d core dnn features2d flann gapi highgui imgcodecs imgproc java_bindings_generator ml objdetect photo python2 python_bindings_generator stitching ts video videoio -- Disabled: world -- Disabled by dependency: - -- Unavailable: java js python3 -- Applications: tests perf_tests apps -- Documentation: NO -- Non-free algorithms: NO 

y se encontraron las dependencias necesarias, como GTK:


 -- GUI: -- GTK+: YES (ver 2.24.30) -- GThread : YES (ver 2.48.2) -- GtkGlExt: NO -- -- Video I/O: -- GStreamer: -- base: YES (ver 1.8.3) -- video: YES (ver 1.8.3) -- app: YES (ver 1.8.3) -- riff: YES (ver 1.8.3) -- pbutils: YES (ver 1.8.3) -- v4l/v4l2: linux/videodev2.h 

Todo lo que queda es llamar a make , make install y esperar a que se complete la compilaci贸n:


 Successfully built 4dae6b1a7d32 

Use esta id imagen para etiquetar y crear un contenedor:


 docker tag 4dae6b1a7d32 ubuntu16_armhf_opencv:latest docker run ubuntu16_armhf_opencv 

Y solo tenemos que bombear el OpenCV ensamblado fuera del contenedor. Primero, veamos el identificador del contenedor creado:


 $ docker container ls --all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e94667fe60d2 ubuntu16_armhf_opencv "/bin/bash" 6 seconds ago Exited (0) 5 seconds ago clever_yalow 

Y copie el directorio de instalaci贸n con OpenCV instalado:


 docker cp e94667fe60d2:/opencv/build/install/ ./ mv install ocv_install 

Poner la mesa


Copie ocv_install en Raspberry Pi, configure las rutas e intente ejecutar OpenCV desde python.


 export LD_LIBRARY_PATH=/path/to/ocv_install/lib/:$LD_LIBRARY_PATH export PYTHONPATH=/path/to/ocv_install/python/:$PYTHONPATH 

Ejecute el ejemplo de detecci贸n utilizando la red neuronal MobileNet-SSD desde https://github.com/chuanqi305/MobileNet-SSD :


 import cv2 as cv print cv.__file__ classes = ['backgroud', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'] cap = cv.VideoCapture(0) net = cv.dnn.readNet('MobileNetSSD_deploy.caffemodel', 'MobileNetSSD_deploy.prototxt') cv.namedWindow('Object detection', cv.WINDOW_NORMAL) while cv.waitKey(1) != 27: hasFrame, frame = cap.read() if not hasFrame: break frame_height, frame_width = frame.shape[0], frame.shape[1] blob = cv.dnn.blobFromImage(frame, scalefactor=0.007843, size=(300, 300), mean=(127.5, 127.5, 127.5)) net.setInput(blob) out = net.forward() for detection in out.reshape(-1, 7): classId = int(detection[1]) confidence = float(detection[2]) xmin = int(detection[3] * frame_width) ymin = int(detection[4] * frame_height) xmax = int(detection[5] * frame_width) ymax = int(detection[6] * frame_height) if confidence > 0.5: cv.rectangle(frame, (xmin, ymin), (xmax, ymax), color=(255, 0, 255), thickness=3) label = '%s: %.2f' % (classes[classId], confidence) labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1) ymin = max(ymin, labelSize[1]) cv.rectangle(frame, (xmin, ymin - labelSize[1]), (xmin + labelSize[0], ymin + baseLine), (255, 0, 255), cv.FILLED) cv.putText(frame, label, (xmin, ymin), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0)) cv.imshow('Object detection', frame) 


Eso es todo, un ensamblaje completo no lleva m谩s de 20 minutos. Adjunto la versi贸n final del Dockerfile continuaci贸n y, aprovechando esta oportunidad, propongo realizar una breve encuesta del equipo de OpenCV para aquellos que alguna vez tuvieron experiencia con la biblioteca: https://opencv.org/survey-2018.html .


Y s铆, 隆felicidades por OpenCV 4! Este no es solo el trabajo de un equipo separado, es el trabajo de toda la comunidad: OpenCV 4 usted.


 FROM ubuntu:16.04 USER root RUN dpkg --add-architecture armhf RUN sed -i -E 's|^deb ([^ ]+) (.*)$|deb [arch=amd64] \1 \2\ndeb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ \2|' /etc/apt/sources.list RUN apt-get update && \ apt-get install -y --no-install-recommends \ cmake \ pkg-config \ crossbuild-essential-armhf \ git \ python-pip \ libgtk2.0-dev:armhf \ libpython-dev:armhf \ libgstreamer1.0-dev:armhf \ libgstreamer-plugins-base1.0-dev:armhf \ libgstreamer-plugins-good1.0-dev:armhf \ libgstreamer-plugins-bad1.0-dev:armhf RUN pip install numpy==1.12.1 RUN git clone https://github.com/opencv/opencv --depth 1 RUN mkdir opencv/build && cd opencv/build && \ export PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig && \ cmake -DCMAKE_BUILD_TYPE=Release \ -DOPENCV_CONFIG_INSTALL_PATH="cmake" \ -DCMAKE_TOOLCHAIN_FILE="../opencv/platforms/linux/arm-gnueabi.toolchain.cmake" \ -DWITH_IPP=OFF \ -DBUILD_TESTS=OFF \ -DBUILD_PERF_TESTS=OFF \ -DOPENCV_ENABLE_PKG_CONFIG=ON \ -DPYTHON2_INCLUDE_PATH="/usr/include/python2.7" \ -DPYTHON2_NUMPY_INCLUDE_DIRS="/usr/local/lib/python2.7/dist-packages/numpy/core/include" \ -DENABLE_NEON=ON \ -DCPU_BASELINE="NEON" .. && make -j4 && make install 

Source: https://habr.com/ru/post/es430906/


All Articles