{"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\/fr\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","title":{"rendered":"OpenCV sur STM32F7-Discovery","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenCV sur STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a2248ee685ee210ce8f7781435dd1d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/> Je suis l'un des d\u00e9veloppeurs du syst\u00e8me d'exploitation <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">Embox<\/a><\/noindex>, et dans cet article, je vais expliquer comment j'ai r\u00e9ussi \u00e0 faire fonctionner OpenCV sur la carte STM32746G.<\/p>\n<p><\/p>\n<p>Si vous tapez dans un moteur de recherche quelque chose comme \u00ab OpenCV sur carte STM32 \u00bb, vous pouvez trouver pas mal de personnes int\u00e9ress\u00e9es par l'utilisation de cette biblioth\u00e8que sur des cartes STM32 ou d'autres microcontr\u00f4leurs.<br \/>\nIl y a plusieurs vid\u00e9os qui, d'apr\u00e8s le titre, devraient d\u00e9montrer ce qui est n\u00e9cessaire, mais g\u00e9n\u00e9ralement (dans toutes les vid\u00e9os que j'ai vues), sur la carte STM32 il n'y avait que la capture d'image de la cam\u00e9ra et l'affichage du r\u00e9sultat sur l'\u00e9cran, tandis que le traitement de l'image se faisait soit sur un ordinateur ordinaire, soit sur des cartes plus puissantes (comme un Raspberry Pi).<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"pochemu-eto-slozhno\">Pourquoi est-ce compliqu\u00e9 ?<\/h1>\n<p><\/p>\n<p>La popularit\u00e9 des requ\u00eates de recherche s'explique par le fait qu'OpenCV est la biblioth\u00e8que de vision par ordinateur la plus populaire, ce qui signifie que plus de d\u00e9veloppeurs sont familiers avec elle, et la possibilit\u00e9 d'ex\u00e9cuter du code pr\u00eat \u00e0 l'emploi pour les ordinateurs de bureau sur un microcontr\u00f4leur simplifie consid\u00e9rablement le processus de d\u00e9veloppement. Mais pourquoi n'existe-t-il toujours pas de recettes populaires pr\u00eates \u00e0 l'emploi pour r\u00e9soudre ce probl\u00e8me ?<\/p>\n<p><\/p>\n<p>Le probl\u00e8me de l'utilisation d'OpenCV sur de petites cartes est li\u00e9 \u00e0 deux particularit\u00e9s :<\/p>\n<p><\/p>\n<ul>\n<li>Si l'on compile la biblioth\u00e8que m\u00eame avec un ensemble minimal de modules, elle ne tiendra tout simplement pas dans la m\u00e9moire flash de la STM32F7Discovery (m\u00eame sans tenir compte du syst\u00e8me d'exploitation) en raison d'un code tr\u00e8s volumineux (plusieurs m\u00e9gaoctets d'instructions).<\/li>\n<li>La biblioth\u00e8que elle-m\u00eame est \u00e9crite en C++, ce qui signifie\n<ul>\n<li>Un support pour le runtime C++ (exceptions, etc.) est n\u00e9cessaire.<\/li>\n<li>Peu de soutien pour LibC\/Posix, qui est g\u00e9n\u00e9ralement pr\u00e9sent dans les syst\u00e8mes d'exploitation pour syst\u00e8mes embarqu\u00e9s \u2014 il faut la biblioth\u00e8que standard C++ et la biblioth\u00e8que standard de mod\u00e8les STL (vector, etc.).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"portirovanie-na-embox\">Portage sur Embox<\/h1>\n<p><\/p>\n<p>Comme d'habitude, avant de porter des programmes sur un syst\u00e8me d'exploitation, il est bon d'essayer de les assembler dans la forme que les d\u00e9veloppeurs avaient pr\u00e9vue. Dans notre cas, cela ne pose aucun probl\u00e8me \u2014 les sources peuvent \u00eatre trouv\u00e9es sur <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opencv\/opencv\">GitHub<\/a><\/noindex>, la biblioth\u00e8que s'assemble sous GNU\/Linux avec un cmake ordinaire.<\/p>\n<p><\/p>\n<p>D'une bonne nouvelle \u2014 OpenCV peut \u00eatre construit en tant que biblioth\u00e8que statique d\u00e8s la sortie de la bo\u00eete, ce qui facilite le portage. Assemblons la biblioth\u00e8que avec la configuration standard et voyons combien d'espace elle occupe. Chaque module est assembl\u00e9 en une biblioth\u00e8que distincte.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">&gt; taille lib\/*so --totals\n   texte    donn\u00e9es     bss     d\u00e9c     hex fichier\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>Comme on peut le voir dans la derni\u00e8re ligne, .bss et .data occupent peu d'espace, mais le code d\u00e9passe 70 Mo. Il est \u00e9vident que si cela est li\u00e9 statiquement \u00e0 une application sp\u00e9cifique, la taille du code sera r\u00e9duite.<\/p>\n<p><\/p>\n<p>Tentrons d'\u00e9liminer le plus de modules possible pour cr\u00e9er un exemple minimal (qui, par exemple, affichera simplement la version d'OpenCV), donc observons <code>cmake .. -LA<\/code> et d\u00e9sactivons dans les options tout ce qui peut \u00eatre d\u00e9sactiv\u00e9.<\/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; taille lib\/libopencv_core.a --totals\n   texte    donn\u00e9es     bss     d\u00e9c     hex fichier\n3317069   36425   17987 3371481  3371d9 (TOTALS)<\/code><\/pre>\n<p><\/p>\n<p>D'un c\u00f4t\u00e9, c'est seulement un module de la biblioth\u00e8que, de l'autre c\u00f4t\u00e9, c'est sans optimisation du compilateur pour la taille du code (<code>-Os<\/code>). ~3 Mo de code \u2014 cela reste beaucoup, mais donne d\u00e9j\u00e0 de l'espoir pour le succ\u00e8s.<\/p>\n<p><\/p>\n<h2 id=\"zapusk-v-emulyatore\">Ex\u00e9cution dans un \u00e9mulateur<\/h2>\n<p><\/p>\n<p>Le d\u00e9bogage sur un \u00e9mulateur est beaucoup plus simple, donc commen\u00e7ons par v\u00e9rifier que la biblioth\u00e8que fonctionne sur qemu. J'ai choisi la plateforme \u00e9mul\u00e9e Integrator\/CP, car premi\u00e8rement, c'est aussi ARM, et deuxi\u00e8mement, Embox supporte l'affichage graphique pour cette plateforme.<\/p>\n<p><\/p>\n<p>Embobox dispose d'un m\u00e9canisme pour assembler des biblioth\u00e8ques externes, gr\u00e2ce auquel nous ajoutons OpenCV comme module (en passant toutes les m\u00eames options pour une construction \u00ab minimale \u00bb sous forme de biblioth\u00e8ques statiques), puis j'ajoute une application simple qui se pr\u00e9sente comme suit :<\/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>Nous compilons le syst\u00e8me, le d\u00e9marrons \u2014 nous obtenons la sortie attendue.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">root@embox:\\\/ #opencv_version\nOpenCV:\nConfiguration g\u00e9n\u00e9rale pour OpenCV 4.0.1 =====================================\n  Contr\u00f4le de version :               bd6927bdf-dirty\n\n  Plateforme:\n    Horodatage :                   2019-06-21T10:02:18Z\n    H\u00f4te :                        Linux 5.1.7-arch1-1-ARCH x86_64\n    Cible :                      Generic arm-unknown-none\n    CMake :                       3.14.5\n    G\u00e9n\u00e9rateur CMake :             Unix Makefiles\n    Outil de construction CMake :            \\\/usr\\\/bin\\\/make\n    Configuration :               Debug\n\n  Fonctionnalit\u00e9s CPU\/HW :\n    Baseline :\n      demand\u00e9 :                 DETECT\n      d\u00e9sactiv\u00e9 :                  VFPV3 NEON\n\n  C\/C++:\n    Construit comme des biblioth\u00e8ques dynamiques ? :      NON<\/code><\/pre>\n<p><\/p>\n<p>La prochaine \u00e9tape consiste \u00e0 ex\u00e9cuter un exemple, de pr\u00e9f\u00e9rence l'un des exemples standards propos\u00e9s par les d\u00e9veloppeurs eux-m\u00eames <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/examples.html\">sur leur site<\/a><\/noindex>. J'ai choisi <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/d6\/d56\/samples_2cpp_2edge_8cpp-example.html\">le d\u00e9tecteur de bords de Canny<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>L'exemple a d\u00fb \u00eatre l\u00e9g\u00e8rement modifi\u00e9 pour afficher l'image avec le r\u00e9sultat directement dans le buffer de trame. Cela a \u00e9t\u00e9 n\u00e9cessaire, car la fonction <code>imshow()<\/code> peut dessiner des images via les interfaces QT, GTK et Windows, qui, bien s\u00fbr, ne seront pas pr\u00e9sentes dans la configuration pour STM32. En r\u00e9alit\u00e9, QT peut effectivement \u00eatre ex\u00e9cut\u00e9 sur STM32F7Discovery, mais cela sera abord\u00e9 dans un autre article \ud83d\ude42<\/p>\n<p><\/p>\n<p>Apr\u00e8s avoir pass\u00e9 un certain temps \u00e0 d\u00e9terminer dans quel format le r\u00e9sultat du d\u00e9tecteur de bords est stock\u00e9, obtenons l'image.<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV sur STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/127f90ad8008340d73feb6ece02e52b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>L'image originale<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV sur STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/da34b3ac2561ae9f223acc5c4fe2a597.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>R\u00e9sultat<\/em><\/p>\n<p><\/p>\n<h2 id=\"zapusk-na-stm32f7discovery\">Lancement sur STM32F7Discovery<\/h2>\n<p><\/p>\n<p>Sur le 32F746GDISCOVERY, il y a plusieurs sections de m\u00e9moire mat\u00e9rielles que nous pouvons utiliser d'une mani\u00e8re ou d'une autre<\/p>\n<p><\/p>\n<ol>\n<li>320KiB de RAM<\/li>\n<li>1MiB de m\u00e9moire flash pour l'image<\/li>\n<li>8MiB de SDRAM<\/li>\n<li>16MiB de NAND-flash QSPI<\/li>\n<li>Connecteur pour carte microSD<\/li>\n<\/ol>\n<p><\/p>\n<p>La carte SD peut \u00eatre utilis\u00e9e pour stocker des images, mais dans le contexte de l'ex\u00e9cution d'un exemple minimal, ce n'est pas tr\u00e8s utile.<br \/>\nL'\u00e9cran a une r\u00e9solution de 480 \u00d7 272, ce qui signifie que la m\u00e9moire pour le framebuffer sera de 522 240 octets \u00e0 une profondeur de 32 bits, c'est-\u00e0-dire que cela d\u00e9passe la taille de la m\u00e9moire vive, donc le framebuffer et le tas (qui sera n\u00e9cessaire notamment pour OpenCV, afin de stocker les donn\u00e9es pour les images et les structures auxiliaires) seront plac\u00e9s dans la SDRAM, tout le reste (m\u00e9moire pour les piles et autres besoins syst\u00e8me) sera allou\u00e9 dans la RAM.<\/p>\n<p><\/p>\n<p>Si nous prenons une configuration minimale pour STM32F7Discovery (en enlevant tout le r\u00e9seau, toutes les commandes, en rendant les piles aussi petites que possible, etc.) et que nous ajoutons OpenCV avec des exemples, la m\u00e9moire requise sera la suivante :<\/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>Pour ceux qui ne sont pas tr\u00e8s familiers avec les sections, je vais expliquer : dans <code>.text<\/code> et <code>.rodata<\/code> se trouvent les instructions et les constantes (en gros, les donn\u00e9es en lecture seule), dans <code>.data<\/code> se trouvent les donn\u00e9es modifiables, dans <code>.bss<\/code> se trouvent des variables \u00ab annul\u00e9es \u00bb, qui, n\u00e9anmoins, ont besoin d'espace (cette section \u00ab ira \u00bb dans la RAM).<\/p>\n<p><\/p>\n<p>La bonne nouvelle est que <code>.data<\/code>\/<code>.bss<\/code> doivent tenir, mais le probl\u00e8me est que <code>.text<\/code> il n'y a qu'1MiB de m\u00e9moire disponible pour l'image. On pourrait supprimer l'image de l'exemple et la lire, par exemple, depuis une carte SD en m\u00e9moire au d\u00e9marrage, mais fruits.png p\u00e8se environ 330KiB, donc cela ne r\u00e9soudra pas le probl\u00e8me : la majeure partie <code>.text<\/code> est compos\u00e9e pr\u00e9cis\u00e9ment du code OpenCV. <code>.text<\/code> En gros, il ne reste qu'une solution : charger une partie du code sur une m\u00e9moire flash QSPI (elle a un mode de fonctionnement sp\u00e9cial pour le mappage de la m\u00e9moire sur le bus syst\u00e8me, donc le processeur pourra acc\u00e9der directement \u00e0 ces donn\u00e9es). Cependant, le probl\u00e8me se pose : d'une part, la m\u00e9moire de la flash QSPI n'est pas accessible imm\u00e9diatement apr\u00e8s le red\u00e9marrage de l'appareil (il faut initialiser s\u00e9par\u00e9ment le mode de m\u00e9moire mapp\u00e9e), d'autre part, nous ne pouvons pas \u00ab flasher \u00bb cette m\u00e9moire avec un chargeur classique.<\/p>\n<p><\/p>\n<p>En fin de compte, il ne reste plus qu'une chose : charger une partie du code sur la m\u00e9moire flash QSPI (elle dispose d'un mode de fonctionnement sp\u00e9cial pour le mappage m\u00e9moire sur le bus syst\u00e8me, de sorte que le processeur puisse acc\u00e9der directement \u00e0 ces donn\u00e9es). Cependant, un probl\u00e8me se pose : d'une part, la m\u00e9moire de la flash QSPI n'est pas accessible imm\u00e9diatement apr\u00e8s le red\u00e9marrage de l'appareil (il faut initialiser s\u00e9par\u00e9ment le mode de m\u00e9moire mapp\u00e9e), d'autre part, il n'est pas possible de \u00ab flasher \u00bb cette m\u00e9moire avec un chargeur de d\u00e9marrage classique.<\/p>\n<p><\/p>\n<p>L'id\u00e9e de porter cette biblioth\u00e8que sur Embox est n\u00e9e il y a environ un an, mais cela a \u00e9t\u00e9 repouss\u00e9 plusieurs fois pour diverses raisons. L'une des raisons est le support de libstdc++ et de la biblioth\u00e8que de mod\u00e8les standard. Le probl\u00e8me du support de C++ dans Embox d\u00e9passe le cadre de cet article, donc je dirai juste ici que nous avons r\u00e9ussi \u00e0 obtenir ce support dans l'ampleur n\u00e9cessaire pour faire fonctionner cette biblioth\u00e8que \ud83d\ude42<\/p>\n<p><\/p>\n<h1 id=\"rezultat\">R\u00e9sultat<\/h1>\n<p><\/p>\n<p>Finalement, ces probl\u00e8mes ont \u00e9t\u00e9 surmont\u00e9s (du moins, dans une mesure suffisante pour faire fonctionner l'exemple OpenCV), et l'exemple s'est lanc\u00e9. La carte met 40 secondes \u00e0 rechercher les contours avec le filtre de Canny. C'est, bien s\u00fbr, trop long (il y a des id\u00e9es pour optimiser cela, de quoi on pourra parler dans un article s\u00e9par\u00e9 en cas de succ\u00e8s).<\/p>\n<p><\/p>\n<p>N\u00e9anmoins, l'objectif interm\u00e9diaire \u00e9tait de cr\u00e9er un prototype qui montrera la possibilit\u00e9 fondamentale de faire fonctionner OpenCV sur STM32, donc cet objectif a \u00e9t\u00e9 atteint, hourra ! <\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV sur STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a400c72865ec17094efc985908914463.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>tl;dr : guide \u00e9tape par \u00e9tape<\/p>\n<h4 id=\"tldr-poshagovaya-instrukciya\">0 : T\u00e9l\u00e9chargez les sources d'Embox, par exemple comme ceci :<\/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 : Commen\u00e7ons par compiler le chargeur qui \u00ab flashera \u00bb la m\u00e9moire flash QSPI.<\/code><\/pre>\n<p><\/p>\n<p>1 : Commen\u00e7ons par assembler le chargeur qui va \u00ab flasher \u00bb la m\u00e9moire flash QSPI.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-arm\/stm32f7cube<\/code><\/pre>\n<p><\/p>\n<p>Il est maintenant n\u00e9cessaire de configurer le r\u00e9seau, car nous allons charger l'image via TFTP. Pour d\u00e9finir les adresses IP de la carte et de l'h\u00f4te, il faut modifier le fichier conf\/rootfs\/network.<\/p>\n<p><\/p>\n<p>Exemple de configuration :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">iface eth0 inet static\n    address 192.168.2.2\n    netmask 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>passerelle<\/code> \u2014 adresse de l'h\u00f4te \u00e0 partir duquel l'image sera charg\u00e9e, <code>address<\/code> \u2014 adresse de la carte.<\/p>\n<p><\/p>\n<p>Apr\u00e8s cela, nous construisons le chargeur :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make<\/code><\/pre>\n<p><\/p>\n<p>2 : Chargement classique du chargeur (d\u00e9sol\u00e9 pour le jeu de mots) sur la carte \u2014 il n'y a rien de sp\u00e9cifique ici, il faut le faire comme pour toute autre application pour STM32F7Discovery. Si vous ne savez pas comment proc\u00e9der, vous pouvez lire \u00e0 ce sujet. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/349034\/\">ici<\/a><\/noindex>.<br \/>\n3 : Compilation de l'image avec la configuration pour 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 : Extraction des sections ELF \u00e0 \u00e9crire dans le QSPI, dans 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>Dans le r\u00e9pertoire conf se trouve un script qui s'en occupe, vous pouvez donc l'ex\u00e9cuter.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    .\/conf\/qspi_objcopy.sh # Le binaire requis -- build\/base\/bin\/qspi.bin<\/code><\/pre>\n<p><\/p>\n<p>5 : Avec tftp, t\u00e9l\u00e9chargez qspi.bin.bin sur la cl\u00e9 QSPI. Sur l'h\u00f4te, il faut copier qspi.bin dans le r\u00e9pertoire racine du serveur tftp (g\u00e9n\u00e9ralement \/srv\/tftp\/ ou \/var\/lib\/tftpboot\/ ; les paquets correspondants pour le serveur se trouvent dans la plupart des distributions populaires, souvent appel\u00e9s tftpd ou tftp-hpa, il peut parfois \u00eatre n\u00e9cessaire de faire <code>systemctl start tftpd.service<\/code> pour d\u00e9marrer).<\/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>Sur Embox (c'est-\u00e0-dire dans le chargeur), il faut ex\u00e9cuter cette commande (en supposant que l'adresse du serveur est 192.168.2.1) :<\/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 : Avec la commande <code>goto<\/code> nous devons \u00ab sauter \u00bb dans la m\u00e9moire QSPI. L'emplacement sp\u00e9cifique variera en fonction de la mani\u00e8re dont l'image est li\u00e9e, cet adresse peut \u00eatre consult\u00e9e avec la commande <code>mem 0x90000000<\/code> (l'adresse de d\u00e9part est plac\u00e9e dans le deuxi\u00e8me mot de 32 bits de l'image) ; il faudra \u00e9galement d\u00e9finir le drapeau de pile <code>-s<\/code>, l'adresse de la pile se trouve \u00e0 l'adresse 0x90000000, exemple :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt;mem 0x90000000\n    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275\n                      \u2191           \u2191\n              c'est l'adresse    c'est  l'adresse \n                de la pile      de la premi\u00e8re\n                           instruction\n\n    embox&gt;goto -i 0x9000c27f -s 0x20023200 # Le drapeau -i est n\u00e9cessaire pour interdire les interruptions pendant l'initialisation du syst\u00e8me<\/code><\/pre>\n<p><\/p>\n<p>7 : D\u00e9marrez<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; edges 20<\/code><\/pre>\n<p><\/p>\n<p>et profitez d'une recherche des contours de 40 secondes \ud83d\ude42<\/p>\n<p><\/p>\n<p>Si quelque chose ne va pas, \u00e9crivez un probl\u00e8me dans <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">notre d\u00e9p\u00f4t<\/a><\/noindex>, ou dans la mailing list embox-devel@googlegroups.com, ou dans les commentaires ici.<\/p>\n<p>Source : <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.2.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\/fr\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\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\/fr\/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 sur STM32F7-Discovery | ProHoster","description":"Je suis l'un des d\u00e9veloppeurs du syst\u00e8me d'exploitation","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/37914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=37914"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/37914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/28450"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=37914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=37914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=37914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}