{"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\/pt\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","title":{"rendered":"OpenCV no STM32F7-Discovery","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenCV no STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a2248ee685ee210ce8f7781435dd1d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/> Sou um dos desenvolvedores do sistema operacional <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">Embox<\/a><\/noindex>, e neste artigo, vou contar como consegui rodar o OpenCV na placa STM32746G.<\/p>\n<p><\/p>\n<p>Se voc\u00ea pesquisar algo como \u00abOpenCV na placa STM32\u00bb, encontrar\u00e1 muitas pessoas interessadas em usar essa biblioteca em placas STM32 ou outros microcontroladores.<br \/>\nExistem v\u00e1rios v\u00eddeos que, pelo t\u00edtulo, devem demonstrar o que \u00e9 necess\u00e1rio, mas geralmente (em todos os v\u00eddeos que vi) na placa STM32 apenas a captura de imagem da c\u00e2mera e a exibi\u00e7\u00e3o do resultado na tela foram realizadas, e o processamento da imagem era feito em um computador comum ou em placas mais robustas (como um Raspberry Pi).<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"pochemu-eto-slozhno\">Por que isso \u00e9 dif\u00edcil?<\/h1>\n<p><\/p>\n<p>A popularidade das pesquisas se deve ao fato de que o OpenCV \u00e9 a biblioteca de vis\u00e3o computacional mais popular, o que significa que mais desenvolvedores est\u00e3o familiarizados com ela, al\u00e9m de que a possibilidade de executar c\u00f3digo destinado a desktop em um microcontrolador torna o processo de desenvolvimento muito mais f\u00e1cil. Mas por que ainda n\u00e3o existem receitas prontas populares para resolver esse problema?<\/p>\n<p><\/p>\n<p>O problema de usar o OpenCV em placas pequenas est\u00e1 relacionado a duas caracter\u00edsticas:<\/p>\n<p><\/p>\n<ul>\n<li>Se voc\u00ea compilar a biblioteca mesmo com o conjunto m\u00ednimo de m\u00f3dulos, ela simplesmente n\u00e3o caber\u00e1 na mem\u00f3ria flash da mesma STM32F7Discovery (mesmo sem considerar o sistema operacional) devido ao tamanho do c\u00f3digo (v\u00e1rios megabytes de instru\u00e7\u00f5es)<\/li>\n<li>A pr\u00f3pria biblioteca \u00e9 escrita em C++, o que significa\n<ul>\n<li>\u00c9 necess\u00e1ria a compatibilidade com tempo de execu\u00e7\u00e3o C++ (exce\u00e7\u00f5es, etc.)<\/li>\n<li>Houve pouca compatibilidade com LibC\/Posix, que normalmente est\u00e1 presente em sistemas operacionais para sistemas embarcados \u2014 uma biblioteca padr\u00e3o C++ e uma biblioteca padr\u00e3o de templates STL (vector, etc.) s\u00e3o necess\u00e1rias.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"portirovanie-na-embox\">Portando para o Embox<\/h1>\n<p><\/p>\n<p>Como de costume, antes de portar qualquer programa para um sistema operacional, \u00e9 bom tentar compil\u00e1-lo da forma como os desenvolvedores o imaginaram. No nosso caso, n\u00e3o h\u00e1 problemas com isso \u2014 os arquivos-fonte podem ser encontrados em <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opencv\/opencv\">github<\/a><\/noindex>, a biblioteca \u00e9 compilada sob GNU\/Linux com o cmake regular.<\/p>\n<p><\/p>\n<p>Das boas not\u00edcias \u2014 o OpenCV pode ser compilado como uma biblioteca est\u00e1tica, o que torna o port para outras plataformas mais simples. Compilamos a biblioteca com a configura\u00e7\u00e3o padr\u00e3o e verificamos quanto espa\u00e7o ela ocupa. Cada m\u00f3dulo \u00e9 compilado em uma biblioteca separada.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">&gt; tamanho lib\/*so --totais\n   texto    dados     bss     dec     hex filename\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 (TOTAIS)<\/code><\/pre>\n<p><\/p>\n<p>Como podemos ver na \u00faltima linha, .bss e .data n\u00e3o ocupam muito espa\u00e7o, mas o c\u00f3digo ultrapassa 70 MiB. \u00c9 claro que, se isso for vinculado estaticamente a um aplicativo espec\u00edfico, o c\u00f3digo ser\u00e1 reduzido.<\/p>\n<p><\/p>\n<p>Vamos tentar eliminar o m\u00e1ximo poss\u00edvel de m\u00f3dulos para conseguir um exemplo m\u00ednimo (que, por exemplo, simplesmente mostrar\u00e1 a vers\u00e3o do OpenCV), ent\u00e3o vamos l\u00e1: <code>cmake .. -LA<\/code> e desativamos nas op\u00e7\u00f5es tudo que pode ser desativado.<\/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; tamanho lib\/libopencv_core.a --totais\n   texto    dados     bss     dec     hex filename\n3317069   36425   17987 3371481  3371d9 (TOTAIS)<\/code><\/pre>\n<p><\/p>\n<p>Por um lado, este \u00e9 apenas um m\u00f3dulo da biblioteca, por outro lado, isso \u00e9 sem a otimiza\u00e7\u00e3o do compilador para o tamanho do c\u00f3digo (<code>-Os<\/code>). ~3 MiB de c\u00f3digo ainda \u00e9 uma quantidade consider\u00e1vel, mas j\u00e1 traz esperan\u00e7a de sucesso.<\/p>\n<p><\/p>\n<h2 id=\"zapusk-v-emulyatore\">Execu\u00e7\u00e3o no emulador<\/h2>\n<p><\/p>\n<p>Depurar no emulador \u00e9 muito mais f\u00e1cil, ent\u00e3o primeiro vamos garantir que a biblioteca funcione no qemu. Para a plataforma emulada, escolhi Integrator\/CP, pois, em primeiro lugar, \u00e9 tamb\u00e9m ARM, e em segundo lugar, a Embox suporta a sa\u00edda gr\u00e1fica para essa plataforma.<\/p>\n<p><\/p>\n<p>No Embox, h\u00e1 um mecanismo para compilar bibliotecas externas, com o qual adicionamos o OpenCV como um m\u00f3dulo (passando todas as mesmas op\u00e7\u00f5es para uma compila\u00e7\u00e3o \u00abm\u00ednima\u00bb na forma de bibliotecas est\u00e1ticas). Em seguida, adiciono um aplicativo simples que se parece com isso:<\/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>Compilamos o sistema, executamos \u2014 obtemos a sa\u00edda esperada.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">root@embox: \/#opencv_version                                                     \nOpenCV: \nConfigura\u00e7\u00e3o geral para OpenCV 4.0.1 =====================================\n  Controle de vers\u00e3o:               bd6927bdf-dirty\n\n  Plataforma:\n    Data e hora:                   2019-06-21T10:02:18Z\n    Host:                        Linux 5.1.7-arch1-1-ARCH x86_64\n    Alvo:                      Gen\u00e9rico arm-unknown-none\n    CMake:                       3.14.5\n    Gerador CMake:             Unix Makefiles\n    Ferramenta de constru\u00e7\u00e3o CMake:            \/usr\/bin\/make\n    Configura\u00e7\u00e3o:               Debug\n\n  Recursos de CPU\/HW:\n    Base:\n      solicitado:                 DETECT\n      desativado:                  VFPV3 NEON\n\n  C\/C++:\n    Compilado como bibliotecas din\u00e2micas?:      N\u00c3O<\/code><\/pre>\n<p><\/p>\n<p>O pr\u00f3ximo passo \u00e9 executar algum exemplo, de prefer\u00eancia um padr\u00e3o dos que os pr\u00f3prios desenvolvedores oferecem <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/examples.html\">em seu site<\/a><\/noindex>. Eu escolhi <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/d6\/d56\/samples_2cpp_2edge_8cpp-example.html\">o detector de bordas de Canny<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Tive que reescrever um pouco o exemplo para exibir a imagem com o resultado diretamente no framebuffer. Isso foi necess\u00e1rio, pois a fun\u00e7\u00e3o <code>imshow()<\/code> consegue renderizar imagens por meio das interfaces QT, GTK e Windows, que, claro, n\u00e3o estar\u00e3o no config para STM32. Na verdade, o QT tamb\u00e9m pode ser executado no STM32F7Discovery, mas isso ser\u00e1 abordado em outro artigo \ud83d\ude42<\/p>\n<p><\/p>\n<p>Ap\u00f3s alguma investiga\u00e7\u00e3o sobre qual formato \u00e9 usado para armazenar o resultado do detector de bordas, obtemos a imagem.<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV no STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/127f90ad8008340d73feb6ece02e52b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Imagem original<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV no STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/da34b3ac2561ae9f223acc5c4fe2a597.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Resultado<\/em><\/p>\n<p><\/p>\n<h2 id=\"zapusk-na-stm32f7discovery\">Execu\u00e7\u00e3o no STM32F7Discovery<\/h2>\n<p><\/p>\n<p>No 32F746GDISCOVERY existem v\u00e1rias se\u00e7\u00f5es de mem\u00f3ria que podemos utilizar de alguma forma<\/p>\n<p><\/p>\n<ol>\n<li>320KiB de mem\u00f3ria RAM<\/li>\n<li>1MiB de mem\u00f3ria flash para a imagem<\/li>\n<li>8MiB de SDRAM<\/li>\n<li>16MiB de flash NAND QSPI<\/li>\n<li>Conector para cart\u00e3o microSD<\/li>\n<\/ol>\n<p><\/p>\n<p>O cart\u00e3o SD pode ser utilizado para armazenar imagens, mas no contexto de executar um exemplo m\u00ednimo, isso n\u00e3o \u00e9 muito \u00fatil.<br \/>\nO display tem uma resolu\u00e7\u00e3o de 480\u00d7272, o que significa que a mem\u00f3ria para o framebuffer ser\u00e1 de 522240 bytes a uma profundidade de 32 bits, ou seja, isso \u00e9 maior do que a quantidade de mem\u00f3ria RAM, ent\u00e3o o framebuffer e a heap (que ser\u00e1 necess\u00e1ria, entre outras coisas, para o OpenCV, para armazenar dados de imagens e estruturas auxiliares) ser\u00e3o alocados na SDRAM, enquanto todo o resto (mem\u00f3ria para pilhas e outras necessidades do sistema) ir\u00e1 para a RAM.<\/p>\n<p><\/p>\n<p>Se pegarmos a configura\u00e7\u00e3o m\u00ednima para o STM32F7Discovery (remover toda a rede, todos os comandos, minimizar as pilhas, etc.) e adicionar o OpenCV com exemplos, a mem\u00f3ria necess\u00e1ria ser\u00e1 a seguinte:<\/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>Para aqueles que n\u00e3o est\u00e3o muito familiarizados com quais se\u00e7\u00f5es v\u00e3o para onde, explico: <code>.text<\/code> e <code>.rodata<\/code> cont\u00e9m instru\u00e7\u00f5es e constantes (grosso modo, dados somente para leitura), <code>.data<\/code> onde ficam os dados mut\u00e1veis, <code>.bss<\/code> h\u00e1 vari\u00e1veis \u00abzeradas\u00bb que, no entanto, precisam de espa\u00e7o (essa se\u00e7\u00e3o ir\u00e1 para a RAM).<\/p>\n<p><\/p>\n<p>A boa not\u00edcia \u00e9 que <code>.data<\/code>\/<code>.bss<\/code> devem ser alocados, mas o problema \u00e9 que <code>.text<\/code> s\u00f3 h\u00e1 1MiB de mem\u00f3ria dispon\u00edvel para a imagem. Podemos descartar a <code>.text<\/code> imagem do exemplo e l\u00ea-la, por exemplo, de um cart\u00e3o SD para a mem\u00f3ria durante a inicializa\u00e7\u00e3o, mas fruits.png pesa cerca de 330KiB, ent\u00e3o isso n\u00e3o resolve o problema: a maior parte <code>.text<\/code> consiste exatamente no c\u00f3digo do OpenCV.<\/p>\n<p><\/p>\n<p>Basicamente, s\u00f3 resta uma coisa \u2014 carregar uma parte do c\u00f3digo na mem\u00f3ria flash QSPI (ela tem um modo de opera\u00e7\u00e3o especial para mapeamento de mem\u00f3ria no barramento do sistema, de modo que o processador possa acessar esses dados diretamente). No entanto, surge um problema: primeiro, a mem\u00f3ria da flash QSPI n\u00e3o est\u00e1 dispon\u00edvel imediatamente ap\u00f3s a reinicializa\u00e7\u00e3o do dispositivo (\u00e9 necess\u00e1rio inicializar separadamente o modo mapeado na mem\u00f3ria) e, em segundo lugar, n\u00e3o se pode \u00abprogramar\u00bb essa mem\u00f3ria com o carregador habitual.<\/p>\n<p><\/p>\n<p>No final, foi decidido linkar todo o c\u00f3digo na QSPI e grav\u00e1-lo com um carregador espec\u00edfico, que ir\u00e1 receber o bin\u00e1rio necess\u00e1rio via TFTP.<\/p>\n<p><\/p>\n<h1 id=\"rezultat\">Resultado<\/h1>\n<p><\/p>\n<p>A ideia de portar essa biblioteca para o Embox surgiu h\u00e1 cerca de um ano, mas foi adiada repetidamente por v\u00e1rias raz\u00f5es. Uma delas \u00e9 o suporte ao libstdc++ e \u00e0 biblioteca de templates padr\u00e3o. O problema do suporte ao C++ no Embox vai al\u00e9m do escopo deste artigo, portanto, direi aqui apenas que conseguimos obter esse suporte na medida necess\u00e1ria para o funcionamento desta biblioteca \ud83d\ude42<\/p>\n<p><\/p>\n<p>No final, esses problemas foram superados (pelo menos, em um grau suficiente para o funcionamento do exemplo OpenCV), e o exemplo foi executado. A placa leva 40 longos segundos para encontrar bordas com o filtro de Canny. Isso \u00e9, claro, tempo demais (h\u00e1 maneiras de otimizar isso, e podemos escrever um artigo separado sobre isso, caso o sucesso aconte\u00e7a). <\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV no STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a400c72865ec17094efc985908914463.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>No entanto, o objetivo intermedi\u00e1rio era criar um prot\u00f3tipo que mostrasse a viabilidade de executar o OpenCV no STM32, e esse objetivo foi alcan\u00e7ado, viva!<\/p>\n<h4 id=\"tldr-poshagovaya-instrukciya\">tl;dr: instru\u00e7\u00f5es passo a passo<\/h4>\n<p><\/p>\n<p>0: Baixe os fontes do Embox, por exemplo assim:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    git clone https:\/\/github.com\/embox\/embox &amp;&amp; cd .\/embox<\/code><\/pre>\n<p><\/p>\n<p>1: Vamos come\u00e7ar compilando o carregador que \u00abprogramar\u00e1\u00bb a mem\u00f3ria flash QSPI.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-arm\/stm32f7cube<\/code><\/pre>\n<p><\/p>\n<p>Agora \u00e9 necess\u00e1rio configurar a rede, pois vamos carregar a imagem via TFTP. Para definir os endere\u00e7os IP da placa e do host, \u00e9 preciso alterar o arquivo conf\/rootfs\/network.<\/p>\n<p><\/p>\n<p>Exemplo de configura\u00e7\u00e3o:<\/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>gateway<\/code> \u2014 endere\u00e7o do host de onde a imagem ser\u00e1 carregada, <code>address<\/code> \u2014 endere\u00e7o da placa.<\/p>\n<p><\/p>\n<p>Ap\u00f3s isso, compilamos o carregador:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make<\/code><\/pre>\n<p><\/p>\n<p>2: Carregamento normal do carregador (desculpe pelo trocadilho) na placa \u2014 aqui n\u00e3o h\u00e1 nada espec\u00edfico, deve ser feito como para qualquer outro aplicativo para STM32F7Discovery. Se voc\u00ea n\u00e3o sabe como fazer isso, pode ler sobre. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/349034\/\">aqui<\/a><\/noindex>.<br \/>\n3: Compila\u00e7\u00e3o da imagem com a configura\u00e7\u00e3o para 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: Extraindo se\u00e7\u00f5es do ELF que precisam ser gravadas no QSPI, em 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>No diret\u00f3rio conf, h\u00e1 um script que faz isso, portanto, voc\u00ea pode execut\u00e1-lo<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    .\/conf\/qspi_objcopy.sh # O bin\u00e1rio necess\u00e1rio -- build\/base\/bin\/qspi.bin<\/code><\/pre>\n<p><\/p>\n<p>5: Com tftp, carregue qspi.bin.bin no flash QSPI. No host, \u00e9 necess\u00e1rio copiar qspi.bin para a pasta raiz do servidor tftp (normalmente \u00e9 \/srv\/tftp\/ ou \/var\/lib\/tftpboot\/; pacotes para o servidor correspondente est\u00e3o dispon\u00edveis na maioria das distribui\u00e7\u00f5es populares, geralmente chamado tftpd ou tftp-hpa, \u00e0s vezes \u00e9 necess\u00e1rio executar <code>systemctl start tftpd.service<\/code> para iniciar).<\/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>No Embox (ou seja, no carregador), voc\u00ea deve executar o seguinte comando (supondo que o endere\u00e7o do servidor seja 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: Usando o comando <code>goto<\/code> \u00e9 necess\u00e1rio \u00abpular\u00bb para a mem\u00f3ria QSPI. A localiza\u00e7\u00e3o exata variar\u00e1 dependendo de como a imagem \u00e9 vinculada, esse endere\u00e7o pode ser verificado com o comando <code>mem 0x90000000<\/code> (o endere\u00e7o de in\u00edcio est\u00e1 no segundo palavra de 32 bits da imagem); voc\u00ea tamb\u00e9m precisar\u00e1 definir a pilha com o sinalizador <code>-s<\/code>, o endere\u00e7o da pilha est\u00e1 em 0x90000000, exemplo:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt;mem 0x90000000\n    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275\n                      \u2191           \u2191\n              este \u00e9 o endere\u00e7o    este \u00e9 o endere\u00e7o \n                da pilha        da primeira\n                           instru\u00e7\u00e3o\n\n    embox&gt;goto -i 0x9000c27f -s 0x20023200 # O sinalizador -i \u00e9 necess\u00e1rio para proibir interrup\u00e7\u00f5es durante a inicializa\u00e7\u00e3o do sistema\n\n    <A><\/code><\/pre>\n<p><\/p>\n<p>7: Iniciamos<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; edges 20<\/code><\/pre>\n<p><\/p>\n<p>e aproveitamos 40 segundos de busca de bordas \ud83d\ude42<\/p>\n<p><\/p>\n<p>Se algo n\u00e3o der certo, escreva uma issue em <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">nosso reposit\u00f3rio<\/a><\/noindex>, ou na lista de discuss\u00e3o em embox-devel@googlegroups.com, ou nos coment\u00e1rios aqui.<\/p>\n<p>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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 no STM32F7-Discovery | ProHoster","description":"Sou um dos desenvolvedores do sistema operacional","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/37914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=37914"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/37914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/28450"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=37914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=37914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=37914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}