Mama schläft nachts ruhig - wir sammeln OpenCV für Raspbian'a

Die letzten Wochen waren für unser Team schwierig. OpenCV 4 wurde veröffentlicht und damit auf das OpenVINO-Toolkit R4 von Intel vorbereitet, das OpenCV enthält. Du denkst, ich bin für eine Weile abgelenkt, ich werde mich wie üblich mit OpenCV-Foren und Benutzerkommentaren befassen, und hier ist es Mode für dich zu sagen, dass OpenCV kein IoT ist, dass es unter Raspberry Pi ausreicht, um es zusammenzubauen - es gibt nicht genug Lötmittel, um make -j2 zu setzen - Am Morgen ist es fertig, wenn Sie Glück haben.


Daher schlage ich vor, Hand in Hand zu gehen und zu sehen, wie Sie die OpenCV-Bibliothek für ein 32-Bit-Betriebssystem zusammenstellen können, das auf einem ARM-Prozessor ausgeführt wird. Dabei werden die Ressourcen eines Computers mit 64-Bit-Betriebssystem verwendet, der von einer hervorragenden CPU-Architektur angetrieben wird. Hexerei Cross Compilation, sonst nicht!


Erklärung des Problems


Das Kompilieren direkt auf der Platine, die allgemein als native bezeichnet wird, ist sehr mühsam. Daher werden wir hier eine Möglichkeit betrachten, ein Projekt zu erstellen, mit dem stärkere Computergeräte (nennen wir sie Hosts) Binärdateien für ihre kleinen Verwandten vorbereiten können. Darüber hinaus können beide Maschinen unterschiedliche CPU-Architekturen aufweisen. Dies ist eine Kreuzkompilierung.


Um einen mit OpenCV gefüllten Himbeerkuchen zuzubereiten, benötigen wir:


  • Ubuntu 16.04 Image Docker Kadaver
  • Der Host-Computer ist leistungsstärker als der Raspberry Pi (ansonsten, was ist der Sinn, nicht wahr?)
  • Cross-Compiler für ARMhf sowie Bibliotheken der entsprechenden Architektur

Der gesamte Prozess der Erstellung von OpenCV findet auf dem Host-Computer statt. Ich benutze Ubuntu zu Hause. Bei einer anderen Linux-Version sollten keine Wiedergabeprobleme auftreten. Für Windows-Benutzer - mein aufrichtiger Wunsch, nicht aufzugeben und zu versuchen, es selbst herauszufinden.


Installieren Sie Docker


Ich begann meine Bekanntschaft mit Docker vor ungefähr einer Woche, also fügen Sie Gourmet-Salz und syntaktischen Zucker hinzu, um zu schmecken. Drei Zutaten reichen für Sie und mich - Dockerfile, das Konzept von Image und Container.


Docker selbst ist ein Tool zum Erstellen und Reproduzieren der Konfiguration eines Betriebssystems mit den erforderlichen Komponenten. Dockerfile ist eine Reihe von Shell-Befehlen, die Sie normalerweise auf dem Host-Computer verwenden. In diesem Fall gelten sie jedoch alle für das sogenannte docker Image.


Um Docker zu installieren, gehen Sie wie folgt vor: Bestellen Sie ein Paket über den apt-get Lieferservice:


 sudo apt-get install -y docker.io 

Wir geben dem Docker-Daemon alles, was er verlangt, und melden uns vom System ab (beachten Sie die entsprechende Anmeldung).


 sudo usermod -a -G docker $USER 

Arbeitsbereich vorbereiten


Raspberry Pi (in meinem Fall RPI 2 Modell B) ist in der häufigsten Vorbereitung eine ARMv7-CPU mit dem Betriebssystem Raspbian (Debian-basiert). Wir werden ein docker Image basierend auf Ubuntu 16.04 erstellen, in dem wir den Cross-Compiler und die Armeebibliotheken melden und OpenCV an derselben Stelle sammeln.


Erstelle einen Daddy, in dem unsere Dockerfile liegen wird:


 mkdir ubuntu16_armhf_opencv && cd ubuntu16_armhf_opencv touch Dockerfile 

Fügen Sie Informationen zum Basisbetriebssystem und zur armhf Architektur für das apt-get armhf :


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

Bitte beachten Sie, dass Befehle wie FROM ... , RUN ... die docker Syntax sind und in die erstellte Dockerfile Testdatei geschrieben werden.


ubuntu16_armhf_opencv wir zum übergeordneten Verzeichnis ubuntu16_armhf_opencv und versuchen, unser Docker-Image zu erstellen:


 docker image build ubuntu16_armhf_opencv 

Während der Ausführung des Befehls apt-get update sollten Fehler der folgenden Art Err:[] [url] xenial[-] armhf Packages : 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 

Wenn Sie sich die Datei /etc/apt/sources.list entspricht jeder dieser Fehler einer Zeile, zum Beispiel:


Fehler


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

Zeile in /etc/apt/sources.list :


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

Lösung :
In zwei Teile teilen:


 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 

Daher müssen Sie mehrere Paketquellen ersetzen. In unserem Docker werden wir sie alle durch einen Befehl ersetzen:


 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 

Jetzt sollte apt-get update fehlerfrei funktionieren.


Wir legen die notwendigen Pakete


Wir müssen Host-Pakete wie git , python-pip , cmake und pkg-config sowie crossbuild-essential-armhf , eine Reihe von gcc / g ++ - Cross-Compilern ( arm-linux-gnueabihf-gcc und arm-linux-gnueabihf-g++ ) und Systembibliotheken der entsprechenden Architektur:


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

Aus dem Ungewöhnlichen - wir laden auch GTK (zum Zeichnen von Fenstern im Highgui-Modul), GStreamer und Python herunter, jedoch mit einem expliziten Hinweis auf eine fremde Architektur:


 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 

Und dann klonen und sammeln wir und geben die erforderlichen Flags an:


 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" .. 

wo


  • CMAKE_TOOLCHAIN_FILE - Der Pfad zur cmake-Datei, der den Cross-Compilation-Prozess definiert (legt den gewünschten Compiler fest und schränkt die Verwendung von Host-Bibliotheken ein.


  • WITH_IPP=OFF , - Deaktiviert starke Abhängigkeiten.


  • BUILD_TESTS=OFF , BUILD_PERF_TESTS=OFF , deaktivieren Sie den BUILD_PERF_TESTS=OFF .


  • OPENCV_ENABLE_PKG_CONFIG=ON - damit pkg-config Abhängigkeiten wie GTK finden kann. PKG_CONFIG_PATH ist der richtige Pfad, in dem pkg-config nach Bibliotheken sucht.


  • PYTHON2_INCLUDE_PATH , PYTHON2_NUMPY_INCLUDE_DIRS - Pfade, die zum Cross-Compilieren von Wrappern für Python2 erforderlich sind.


  • ENABLE_NEON=ON , CPU_BASELINE="NEON" - NEON-Optimierung aktivieren.


  • OPENCV_CONFIG_INSTALL_PATH - OPENCV_CONFIG_INSTALL_PATH den Speicherort der Dateien im install .



Die Hauptsache, auf die Sie nach der Ausführung von cmake achten sollten, ist, dass alle erforderlichen Module zusammengesetzt sind (z. B. python2):


 -- 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 

und die notwendigen Abhängigkeiten wie GTK wurden gefunden:


 -- 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 

Sie müssen nur noch make aufrufen, make install und warten, bis der Build abgeschlossen ist:


 Successfully built 4dae6b1a7d32 

Verwenden Sie diese Bild- id , um einen Container zu markieren und zu erstellen:


 docker tag 4dae6b1a7d32 ubuntu16_armhf_opencv:latest docker run ubuntu16_armhf_opencv 

Und wir müssen nur das zusammengebaute OpenCV aus dem Behälter pumpen. Schauen wir uns zunächst die Kennung des erstellten Containers an:


 $ 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 

Und kopieren Sie das Installationsverzeichnis mit installiertem OpenCV:


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

Stellen Sie den Tisch ein


Kopieren Sie ocv_install auf den Raspberry Pi, legen Sie die Pfade fest und versuchen Sie, OpenCV über Python auszuführen.


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

Führen Sie das Erkennungsbeispiel mit dem neuronalen MobileNet-SSD-Netzwerk unter https://github.com/chuanqi305/MobileNet-SSD aus :


 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) 


Das ist alles, eine komplette Montage dauert nicht länger als 20 Minuten. Ich habe die endgültige Version der Dockerfile unten aufgeführt und Dockerfile diese Gelegenheit. Ich schlage vor, eine kurze Umfrage des OpenCV-Teams für diejenigen Dockerfile , die einmal Erfahrung mit der Bibliothek hatten: https://opencv.org/survey-2018.html .


Und ja, herzlichen Glückwunsch zu OpenCV 4! Dies ist nicht nur die Arbeit eines separaten Teams, sondern die Arbeit der gesamten Community - OpenCV 4 you.


 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/de430906/


All Articles