{"id":37914,"date":"2019-10-31T22:20:31","date_gmt":"2019-10-31T19:20:31","guid":{"rendered":"https:\/\/prohoster.info\/blog\/opencv-na-stm32f7-discovery\/"},"modified":"2019-10-31T22:20:31","modified_gmt":"2019-10-31T19:20:31","slug":"opencv-na-stm32f7-discovery","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","title":{"rendered":"OpenCV auf STM32F7-Discovery","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenCV auf STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a2248ee685ee210ce8f7781435dd1d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/> Ich bin einer der Entwickler des Betriebssystems <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">Embox<\/a><\/noindex>, und in diesem Artikel werde ich dar\u00fcber berichten, wie ich es geschafft habe, OpenCV auf dem STM32746G-Board zum Laufen zu bringen.<\/p>\n<p><\/p>\n<p>Gibt man im Suchfeld etwas ein wie \u201eOpenCV auf STM32-Board\u201c, findet man ziemlich viele, die sich f\u00fcr die Nutzung dieser Bibliothek auf STM32- oder anderen Mikrocontrollern interessieren.<br \/>\nEs gibt mehrere Videos, die, judging by the title, das demonstrieren sollen, was ben\u00f6tigt wird, aber normalerweise (in allen Videos, die ich gesehen habe) wurde auf dem STM32-Board nur der Empfang eines Bildes von der Kamera und die Ausgabe des Ergebnisses auf den Bildschirm gemacht, w\u00e4hrend die Bildverarbeitung entweder auf einem normalen Computer oder auf leistungsf\u00e4higeren Boards (zum Beispiel Raspberry Pi) stattfand.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"pochemu-eto-slozhno\">Warum ist das schwierig?<\/h1>\n<p><\/p>\n<p>Die Beliebtheit der Suchanfragen erkl\u00e4rt sich dadurch, dass OpenCV die beliebteste Bibliothek f\u00fcr Computer Vision ist, was bedeutet, dass mehr Entwickler damit vertraut sind, und die M\u00f6glichkeit, Desktop-f\u00e4higen Code auf einem Mikrocontroller auszuf\u00fchren, vereinfacht den Entwicklungsprozess erheblich. Aber warum gibt es bisher keine beliebten, fertig erstellten Rezepte zur L\u00f6sung dieses Problems?<\/p>\n<p><\/p>\n<p>Das Problem bei der Verwendung von OpenCV auf kleinen Boards h\u00e4ngt mit zwei Besonderheiten zusammen:<\/p>\n<p><\/p>\n<ul>\n<li>Selbst wenn man die Bibliothek mit einem minimalen Satz von Modulen kompiliert, passt sie einfach nicht in den Flash-Speicher des STM32F7Discovery (auch ohne Ber\u00fccksichtigung des Betriebssystems) aufgrund des sehr gro\u00dfen Codes (mehrere Megabyte an Anweisungen)<\/li>\n<li>Die Bibliothek ist in C++ geschrieben, was bedeutet,\n<ul>\n<li>Es wird Unterst\u00fctzung f\u00fcr den C++-Laufzeit ben\u00f6tigt (Ausnahmen usw.)<\/li>\n<li>Es fehlt an Unterst\u00fctzung f\u00fcr LibC\/Posix, die normalerweise in Betriebssystemen f\u00fcr eingebettete Systeme vorhanden sind - es wird eine Standardbibliothek f\u00fcr C++ und die Standard-Template-Bibliothek STL (vector usw.) ben\u00f6tigt.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"portirovanie-na-embox\">Portierung auf Embox<\/h1>\n<p><\/p>\n<p>Wie \u00fcblich, vor der Portierung von Programmen in ein Betriebssystem ist es ratsam, zu versuchen, es in der Form zusammenzustellen, in der es von den Entwicklern gedacht war. In unserem Fall treten dabei keine Probleme auf - der Quellcode ist auf <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opencv\/opencv\">GitHub<\/a><\/noindex>, die Bibliothek kann unter GNU\/Linux mit dem gew\u00f6hnlichen cmake erstellt werden.<\/p>\n<p><\/p>\n<p>Die gute Nachricht ist, dass OpenCV direkt als statische Bibliothek gebaut werden kann, was die Portierung erleichtert. Wir bauen die Bibliothek mit der Standardkonfiguration und schauen, wie viel Platz sie einnimmt. Jedes Modul wird in eine separate Bibliothek gebaut.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">&gt; Gr\u00f6\u00dfe lib\/*so --totals\n   text    data     bss     dec     hex dateiname\n1945822   15431     960 1962213  1df0e5 lib\/libopencv_calib3d.so\n17081885     170312   25640 17277837    107a38d lib\/libopencv_core.so\n10928229     137640   20192 11086061     a928ed lib\/libopencv_dnn.so\n 842311   25680    1968  869959   d4647 lib\/libopencv_features2d.so\n 423660    8552     184  432396   6990c lib\/libopencv_flann.so\n8034733   54872    1416 8091021  7b758d lib\/libopencv_gapi.so\n  90741    3452     304   94497   17121 lib\/libopencv_highgui.so\n6338414   53152     968 6392534  618ad6 lib\/libopencv_imgcodecs.so\n21323564     155912  652056 22131532    151b34c lib\/libopencv_imgproc.so\n 724323   12176     376  736875   b3e6b lib\/libopencv_ml.so\n 429036    6864     464  436364   6a88c lib\/libopencv_objdetect.so\n6866973   50176    1064 6918213  699045 lib\/libopencv_photo.so\n 698531   13640     160  712331   ade8b lib\/libopencv_stitching.so\n 466295    6688     168  473151   7383f lib\/libopencv_video.so\n 315858    6972   11576  334406   51a46 lib\/libopencv_videoio.so\n76510375     721519  717496 77949390    4a569ce (TOTALS)<\/code><\/pre>\n<p><\/p>\n<p>Wie aus der letzten Zeile ersichtlich, nehmen .bss und .data nicht viel Speicherplatz ein, w\u00e4hrend der Code \u00fcber 70 MiB betr\u00e4gt. Es ist klar, dass, wenn dies statisch mit einer bestimmten Anwendung verkn\u00fcpft wird, der Code geringer wird.<\/p>\n<p><\/p>\n<p>Versuchen wir, so viele Module wie m\u00f6glich wegzulassen, um ein minimales Beispiel zu erstellen (das zum Beispiel einfach die Version von OpenCV ausgibt), also schauen wir uns das an. <code>cmake .. -LA<\/code> und schalten in den Optionen alles ab, was abgeschaltet werden kann.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">        -DBUILD_opencv_java_bindings_generator=OFF \n        -DBUILD_opencv_stitching=OFF \n        -DWITH_PROTOBUF=OFF \n        -DWITH_PTHREADS_PF=OFF \n        -DWITH_QUIRC=OFF \n        -DWITH_TIFF=OFF \n        -DWITH_V4L=OFF \n        -DWITH_VTK=OFF \n        -DWITH_WEBP=OFF<\/code><\/pre>\n<p><\/p>\n<pre><code class=\"plaintext\">&gt; Gr\u00f6\u00dfe lib\/libopencv_core.a --totals\n   text    data     bss     dec     hex dateiname\n3317069   36425   17987 3371481  3371d9 (TOTALS)<\/code><\/pre>\n<p><\/p>\n<p>Einerseits ist das nur ein Modul der Bibliothek, andererseits ist das ohne den Compiler-Optimierungen f\u00fcr die Codegr\u00f6\u00dfe (<code>-Os<\/code>). ~3 MiB Code sind immer noch ziemlich viel, geben aber bereits Hoffnung auf Erfolg.<\/p>\n<p><\/p>\n<h2 id=\"zapusk-v-emulyatore\">Ausf\u00fchrung im Emulator<\/h2>\n<p><\/p>\n<p>Die Fehlersuche im Emulator ist viel einfacher, also stellen wir zun\u00e4chst sicher, dass die Bibliothek auf qemu funktioniert. Als emulierte Plattform habe ich Integrator\/CP gew\u00e4hlt, da es zum einen ebenfalls ARM ist und zum anderen Embox die grafische Ausgabe f\u00fcr diese Plattform unterst\u00fctzt.<\/p>\n<p><\/p>\n<p>In Embox gibt es einen Mechanismus zum Zusammenstellen externer Bibliotheken, mit dessen Hilfe wir OpenCV als Modul hinzuf\u00fcgen (indem wir alle die gleichen Optionen f\u00fcr den \u201eminimalen\u201c Build in Form von statischen Bibliotheken \u00fcbergeben), danach f\u00fcge ich eine einfachste Anwendung hinzu, die so aussieht:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">version.cpp:\n\n#include \n#include \n\nint main() {\n    printf(\"OpenCV: %s\", cv::getBuildInformation().c_str());\n\n    return 0;\n}<\/code><\/pre>\n<p><\/p>\n<p>Wir bauen das System, starten es \u2014 und erhalten die erwartete Ausgabe.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">root@embox:\\\/\\#opencv_version                                                     \nOpenCV: \nAllgemeine Konfiguration f\u00fcr OpenCV 4.0.1 =====================================\n  Versionskontrolle:               bd6927bdf-dirty\n\n  Plattform:\n    Zeitstempel:                   2019-06-21T10:02:18Z\n    Host:                        Linux 5.1.7-arch1-1-ARCH x86_64\n    Ziel:                      Generisch arm-unknown-none\n    CMake:                       3.14.5\n    CMake-Generator:             Unix Makefiles\n    CMake-Bauwerkzeug:            \\\/usr\\\/bin\\\/make\n    Konfiguration:               Debug\n\n  CPU\\\/HW-Funktionen:\n    Basislinie:\n      angefordert:                 DETECT\n      deaktiviert:                  VFPV3 NEON\n\n  C\\\/C++:\n    Als dynamische Bibliotheken erstellt?:      NEIN<\/code><\/pre>\n<p><\/p>\n<p>Der n\u00e4chste Schritt besteht darin, ein Beispiel zu starten, am besten eines der Standardbeispiele, die von den Entwicklern selbst angeboten werden. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/examples.html\">auf ihrer Website<\/a><\/noindex>. Ich habe mich f\u00fcr <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/d6\/d56\/samples_2cpp_2edge_8cpp-example.html\">den Canny-Kantendetektor<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Das Beispiel musste ein wenig umgeschrieben werden, um das Bild mit dem Ergebnis direkt im Framebuffer anzuzeigen. Das war n\u00f6tig, da die Funktion <code>imshow()<\/code> Bilder \u00fcber die Interfaces QT, GTK und Windows zeichnen kann, die im Konfigurationsfile f\u00fcr STM32 selbstverst\u00e4ndlich nicht vorhanden sind. Tats\u00e4chlich kann QT auch auf STM32F7Discovery ausgef\u00fchrt werden, aber dazu wird in einem anderen Artikel mehr erz\u00e4hlt \ud83d\ude42<\/p>\n<p><\/p>\n<p>Nach kurzer Kl\u00e4rung, in welchem Format die Ergebnisse der Kantendetektion gespeichert werden, erhalten wir das Bild.<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV auf STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/127f90ad8008340d73feb6ece02e52b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Das originale Bild<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV auf STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/da34b3ac2561ae9f223acc5c4fe2a597.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Ergebnis<\/em><\/p>\n<p><\/p>\n<h2 id=\"zapusk-na-stm32f7discovery\">Start auf STM32F7Discovery<\/h2>\n<p><\/p>\n<p>Auf dem 32F746GDISCOVERY gibt es mehrere Hardware-Speichersegmente, die wir mehr oder weniger nutzen k\u00f6nnen.<\/p>\n<p><\/p>\n<ol>\n<li>320KiB RAM<\/li>\n<li>1MiB Flash-Speicher f\u00fcr das Image<\/li>\n<li>8MiB SDRAM<\/li>\n<li>16MiB QSPI NAND-Flash<\/li>\n<li>Steckplatz f\u00fcr microSD-Karte<\/li>\n<\/ol>\n<p><\/p>\n<p>Die SD-Karte kann zur Speicherung von Bildern verwendet werden, ist im Kontext des minimalen Beispiels jedoch nicht besonders n\u00fctzlich.<br \/>\nDas Display hat eine Aufl\u00f6sung von 480\u00d7272, was bedeutet, dass der Speicher f\u00fcr den Framebuffer 522.240 Byte bei einer Tiefe von 32 Bit ben\u00f6tigt, d.h. das ist mehr als der Speicher des RAM, sodass wir den Framebuffer und den Heap (der auch f\u00fcr OpenCV erforderlich sein wird, um Daten f\u00fcr Bilder und Hilfsstrukturen zu speichern) im SDRAM unterbringen, w\u00e4hrend alles andere (Speicher f\u00fcr Stacks und andere Systembedarfe) in den RAM geht.<\/p>\n<p><\/p>\n<p>Wenn wir die minimale Konfiguration f\u00fcr STM32F7Discovery nehmen (das gesamte Netzwerk, alle Befehle entfernen, die Stacks so klein wie m\u00f6glich machen usw.) und OpenCV mit Beispielen hinzuf\u00fcgen, sieht der ben\u00f6tigte Speicher folgenderma\u00dfen aus:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">   text    data     bss     dec     hex filename\n2876890  459208  312736 3648834  37ad42 build\\\/base\\\/bin\\\/embox<\/code><\/pre>\n<p><\/p>\n<p>F\u00fcr diejenigen, die nicht genau wissen, welche Sektionen wohin geh\u00f6ren, erkl\u00e4re ich: in <code>.text<\/code> und <code>.rodata<\/code> liegen die Anweisungen und Konstanten (grob gesprochen, schreibgesch\u00fctzte Daten), in <code>.data<\/code> liegen die ver\u00e4nderbaren Daten, in <code>.bss<\/code> Es gibt \u201enullierte\u201c Variablen, die dennoch Platz brauchen (diese Sektion wird in den RAM gehen).<\/p>\n<p><\/p>\n<p>Die gute Nachricht ist, dass <code>.data<\/code>\/<code>.bss<\/code> untergebracht werden m\u00fcssen, aber die <code>.text<\/code> Schwierigkeit besteht darin, dass es nur 1MiB Speicher f\u00fcr das Image gibt. Man k\u00f6nnte das Bild aus dem Beispiel herausnehmen und es beispielsweise von einer SD-Karte in den Speicher beim Starten lesen, aber fruits.png belegt etwa 330KiB, sodass dies das Problem nicht l\u00f6st: der Gro\u00dfteil <code>.text<\/code> besteht tats\u00e4chlich aus OpenCV-Code. <code>.text<\/code> Im Gro\u00dfen und Ganzen bleibt nur eines \u00fcbrig \u2014 die Speicherung eines Teils des Codes im QSPI-Flash (es hat einen speziellen Betriebsmodus zum Mappen des Speichers auf den Systembus, sodass der Prozessor direkt auf diese Daten zugreifen kann). Dabei entsteht folgendes Problem: Erstens ist der Speicher des QSPI-Flashs nach dem Neustart des Ger\u00e4ts nicht sofort verf\u00fcgbar (der memory-mapped-Modus muss separat initialisiert werden), zweitens kann dieser Speicher nicht mit einem herk\u00f6mmlichen Bootloader \u201eprogrammiert\u201c werden.<\/p>\n<p><\/p>\n<p>Im Gro\u00dfen und Ganzen bleibt nur eines zu tun \u2013 einen Teil des Codes auf das QSPI-Flash zu laden (dieses hat einen speziellen Betriebsmodus f\u00fcr die Speicherabbildung auf den Systembus, sodass der Prozessor direkt auf diese Daten zugreifen kann). Dabei entsteht das Problem: Erstens ist der Speicher des QSPI-Flashs nach einem Neustart des Ger\u00e4ts nicht sofort verf\u00fcgbar (man muss den Memory-Mapped-Modus separat initialisieren), und zweitens kann man diesen Speicher nicht mit einem gewohnten Bootloader \u201eflashen\u201c.<\/p>\n<p><\/p>\n<p>Die Idee, diese Bibliothek auf Embox zu portieren, kam bereits vor etwa einem Jahr auf, wurde aber immer wieder aus verschiedenen Gr\u00fcnden verschoben. Einer davon ist die Unterst\u00fctzung von libstdc++ und der Standard Template Library. Das Problem der C++-Unterst\u00fctzung in Embox f\u00e4llt au\u00dferhalb dieses Artikels, daher sage ich hier nur, dass es uns gelungen ist, diese Unterst\u00fctzung im erforderlichen Umfang f\u00fcr die Arbeit dieser Bibliothek zu erreichen \ud83d\ude42<\/p>\n<p><\/p>\n<h1 id=\"rezultat\">Ergebnis<\/h1>\n<p><\/p>\n<p>Insgesamt wurden diese Probleme \u00fcberwunden (zumindest in ausreichendem Ma\u00dfe f\u00fcr die Ausf\u00fchrung des OpenCV-Beispiels), und das Beispiel lief. Die Platine ben\u00f6tigt 40 lange Sekunden, um mit dem Canny-Filter die Konturen zu suchen. Das ist nat\u00fcrlich viel zu lange (es gibt \u00dcberlegungen, wie man dies optimieren k\u00f6nnte, dar\u00fcber k\u00f6nnte man einen separaten Artikel schreiben, falls es Erfolg hat).<\/p>\n<p><\/p>\n<p>Nichtsdestotrotz war das Zwischenziel, einen Prototyp zu erstellen, der die grunds\u00e4tzliche M\u00f6glichkeit zeigt, OpenCV auf STM32 zu starten, und dieses Ziel wurde erreicht, hurra! <\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV auf STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a400c72865ec17094efc985908914463.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>tl;dr: Schritt-f\u00fcr-Schritt Anleitung<\/p>\n<h4 id=\"tldr-poshagovaya-instrukciya\">0: Wir laden die Embox-Quellen herunter, zum Beispiel so:<\/h4>\n<p><\/p>\n<p>git clone https:\/\/github.com\/embox\/embox &amp;&amp; cd .\/embox<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    1: Lassen Sie uns mit dem Kompilieren des Bootloaders beginnen, der den QSPI-Flash \u201eflashen\u201c wird.<\/code><\/pre>\n<p><\/p>\n<p>1: Lassen Sie uns mit dem Zusammenstellen des Bootloaders beginnen, der das QSPI-Flash \u201eflashen\u201c wird.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-arm\/stm32f7cube<\/code><\/pre>\n<p><\/p>\n<p>Jetzt muss das Netzwerk konfiguriert werden, da wir das Image \u00fcber TFTP laden werden. Um die IP-Adressen der Karte und des Hosts festzulegen, muss die Datei conf\/rootfs\/network ge\u00e4ndert werden.<\/p>\n<p><\/p>\n<p>Beispielkonfiguration:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">iface eth0 inet statisch\n    Adresse 192.168.2.2\n    Netzmaske 255.255.255.0\n    Gateway 192.168.2.1\n    hwaddress aa:bb:cc:dd:ee:02<\/code><\/pre>\n<p><\/p>\n<p><code>Gateway<\/code> \u2014 die Adresse des Hosts, von dem das Image geladen wird, <code>address<\/code> \u2014 die Adresse der Karte.<\/p>\n<p><\/p>\n<p>Danach kompilieren wir den Bootloader:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make<\/code><\/pre>\n<p><\/p>\n<p>2: Normales Laden des Bootloaders (Entschuldigung f\u00fcr das Wortspiel) auf die Karte \u2014 hier gibt es nichts Spezifisches, es muss wie bei jeder anderen Anwendung f\u00fcr STM32F7Discovery gemacht werden. Wenn Sie nicht wissen, wie das geht, k\u00f6nnen Sie dazu lesen <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/349034\/\">hier<\/a><\/noindex>.<br \/>\n3: Kompilierung des Images mit Konfiguration f\u00fcr OpenCV.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-platform\/opencv\/stm32f7discovery\n    make<\/code><\/pre>\n<p><\/p>\n<p>4: Extraktion der ELF-Sektionen, die in QSPI geschrieben werden m\u00fcssen, in qspi.bin<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    arm-none-eabi-objcopy -O binary build\/base\/bin\/embox build\/base\/bin\/qspi.bin \n        --only-section=.text --only-section=.rodata \n        --only-section='.ARM.ex*' \n        --only-section=.data<\/code><\/pre>\n<p><\/p>\n<p>Im Verzeichnis conf befindet sich ein Skript, das dies erledigt, also kann es gestartet werden<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    .\/conf\/qspi_objcopy.sh # Das ben\u00f6tigte Binary -- build\/base\/bin\/qspi.bin<\/code><\/pre>\n<p><\/p>\n<p>5: Laden Sie mit tftp qspi.bin auf den QSPI-Flash. Dazu muss qspi.bin in das Stammverzeichnis des tftp-Servers auf dem Host kopiert werden (in der Regel ist das \/srv\/tftp\/ oder \/var\/lib\/tftpboot\/; die Pakete f\u00fcr den entsprechenden Server sind in den meisten g\u00e4ngigen Distributionen erh\u00e4ltlich, normalerweise mit dem Namen tftpd oder tftp-hpa, manchmal muss man <code>systemctl start tftpd.service<\/code> zum Starten).<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    # \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f tftpd\n    sudo cp build\/base\/bin\/qspi.bin \/srv\/tftp\n    # \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f tftp-hpa\n    sudo cp build\/base\/bin\/qspi.bin \/var\/lib\/tftpboot<\/code><\/pre>\n<p><\/p>\n<p>Auf Embox (d.h. im Bootloader) muss der folgende Befehl ausgef\u00fchrt werden (wir gehen davon aus, dass die Serveradresse 192.168.2.1 ist):<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; qspi_loader qspi.bin 192.168.2.1<\/code><\/pre>\n<p><\/p>\n<p>6: Mit dem Befehl <code>goto<\/code> man muss in den QSPI-Speicher \u201espringen\u201c. Der spezifische Standort wird variieren, je nachdem, wie das Image verlinkt wird; diese Adresse kann mit dem Befehl angesehen werden. <code>mem 0x90000000<\/code> (die Startadresse liegt im zweiten 32-Bit-Wort des Images); au\u00dferdem muss der Stack mit der Flagge gesetzt werden <code>-s<\/code>, die Stack-Adresse liegt bei 0x90000000, Beispiel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt;mem 0x90000000\n    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275\n                      \u2191           \u2191\n              dies ist die Adresse    dies ist die Adresse \n                des Stacks        der ersten\n                           Anweisung\n\n    embox&gt;goto -i 0x9000c27f -s 0x20023200 # Das Flag -i ist erforderlich, um Interrupts w\u00e4hrend der Initialisierung des Systems zu deaktivieren<\/code><\/pre>\n<p><\/p>\n<p>7: Starten wir<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; edges 20<\/code><\/pre>\n<p><\/p>\n<p>und genie\u00dfen die 40-sek\u00fcndige Kantenfindung \ud83d\ude42<\/p>\n<p><\/p>\n<p>Falls etwas schiefgeht \u2014 schreiben Sie ein Problem in <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">unserem Repository<\/a><\/noindex>, oder in die Mailingliste embox-devel@googlegroups.com, oder in die Kommentare hier.<\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/457724\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042f \u043e\u0434\u0438\u043d \u0438\u0437 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Embox, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c OpenCV \u043d\u0430 \u043f\u043b\u0430\u0442\u0435 STM32746G. \u0415\u0441\u043b\u0438 \u0432\u0431\u0438\u0442\u044c \u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 &#171;OpenCV on STM32 board&#187;, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0445, \u043a\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0430 \u043f\u043b\u0430\u0442\u0430\u0445 STM32 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u0435\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0435, \u0441\u0443\u0434\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28450,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-37914","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042f \u043e\u0434\u0438\u043d \u0438\u0437 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47OpenCV \u043d\u0430 STM32F7-Discovery | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042f \u043e\u0434\u0438\u043d \u0438\u0437 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:20:31+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:20:31+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47OpenCV auf STM32F7-Discovery | ProHoster","description":"Ich bin einer der Entwickler des Betriebssystems","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47OpenCV \u043d\u0430 STM32F7-Discovery | ProHoster","og:description":"\u042f \u043e\u0434\u0438\u043d \u0438\u0437 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:20:31+00:00","article:modified_time":"2019-10-31T19:20:31+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"37914","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 19:45:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:18:22","updated":"2026-01-23 19:45:21","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/37914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=37914"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/37914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/28450"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=37914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=37914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=37914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}