{"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\/en\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","title":{"rendered":"OpenCV on STM32F7-Discovery","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenCV on STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a2248ee685ee210ce8f7781435dd1d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/> I am one of the developers of the operating system <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">Embox<\/a><\/noindex>, and in this article, I will explain how I managed to run OpenCV on the STM32746G board.<\/p>\n<p><\/p>\n<p>If you search for something like 'OpenCV on STM32 board', you can find quite a lot of people interested in using this library on STM32 boards or other microcontrollers.<br \/>\nThere are several videos that, judging by their titles, should demonstrate what is needed, but usually (in all the videos I've seen), the STM32 board was only used to capture an image from a camera and display the result on the screen, while the actual image processing was done either on a regular computer or on more powerful boards (like the Raspberry Pi).<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"pochemu-eto-slozhno\">Why is this difficult?<\/h1>\n<p><\/p>\n<p>The popularity of search queries is explained by the fact that OpenCV is the most popular computer vision library, meaning that more developers are familiar with it, and the ability to run desktop-ready code on a microcontroller significantly simplifies the development process. But why are there still no popular ready-made solutions for this problem?<\/p>\n<p><\/p>\n<p>The challenge of using OpenCV on small boards is associated with two peculiarities:<\/p>\n<p><\/p>\n<ul>\n<li>Even compiling the library with the minimal set of modules, it simply won't fit in the flash memory of the STM32F7Discovery (even without taking the OS into account) due to its very large code size (several megabytes of instructions).<\/li>\n<li>The library itself is written in C++, which means\n<ul>\n<li>Support for C++ runtime (exceptions, etc.) is needed.<\/li>\n<li>There is little support for LibC\/Posix, which is usually found in operating systems for embedded systems\u2014 a standard C++ library and standard template library STL (vector, etc.) are required.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"portirovanie-na-embox\">Porting to Embox<\/h1>\n<p><\/p>\n<p>As usual, before porting any programs to an operating system, it\u2019s a good idea to try building it in the form intended by the developers. In our case, there are no issues with this\u2014 the source code can be found at <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opencv\/opencv\">GitHub<\/a><\/noindex>, the library can be built under GNU\/Linux using a regular cmake.<\/p>\n<p><\/p>\n<p>The good news is that OpenCV can be built as a static library right out of the box, which makes porting easier. We build the library with the standard configuration and check how much space it occupies. Each module is built into a separate library.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">&gt; size lib\/*so --totals\n   text    data     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 (TOTALS)<\/code><\/pre>\n<p><\/p>\n<p>As seen from the last line, .bss and .data take up not much space, but the code exceeds 70 MiB. It is clear that if this is statically linked with a specific application, the code size will decrease.<\/p>\n<p><\/p>\n<p>Let's try to eliminate as many modules as possible to assemble a minimal example (which, for instance, will simply output the version of OpenCV), so let's take a look. <code>cmake .. -LA<\/code> and disable everything that can be disabled in the options.<\/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; size lib\/libopencv_core.a --totals\n   text    data     bss     dec     hex filename\n3317069   36425   17987 3371481  3371d9 (TOTALS)<\/code><\/pre>\n<p><\/p>\n<p>On one hand, this is just one module of the library; on the other hand, this is without compiler optimization for code size (<code>-Os<\/code>). ~3 MiB of code is still quite a lot, but it gives hope for success.<\/p>\n<p><\/p>\n<h2 id=\"zapusk-v-emulyatore\">Running in the emulator<\/h2>\n<p><\/p>\n<p>It\u2019s much easier to debug in the emulator, so first, let's ensure that the library works on qemu. As the emulated platform, I've chosen Integrator\/CP because, firstly, it\u2019s also ARM, and secondly, Embox supports graphical output for this platform.<\/p>\n<p><\/p>\n<p>In Embox, there is a mechanism for building external libraries, and using it, I add OpenCV as a module (passing all the same options for a 'minimal' build in the form of static libraries). After that, I add a simple application that looks like this:<\/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>Building the system, launching \u2014 we get the expected output.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">root@embox:\/#opencv_version                                                     \nOpenCV: \nGeneral configuration for OpenCV 4.0.1 =====================================\n  Version control:               bd6927bdf-dirty\n\n  Platform:\n    Timestamp:                   2019-06-21T10:02:18Z\n    Host:                        Linux 5.1.7-arch1-1-ARCH x86_64\n    Target:                      Generic arm-unknown-none\n    CMake:                       3.14.5\n    CMake generator:             Unix Makefiles\n    CMake build tool:            \/usr\/bin\/make\n    Configuration:               Debug\n\n  CPU\/HW features:\n    Baseline:\n      requested:                 DETECT\n      disabled:                  VFPV3 NEON\n\n  C\/C++:\n    Built as dynamic libs?:      NO<\/code><\/pre>\n<p><\/p>\n<p>The next step is to run an example, preferably a standard one from those provided by the developers themselves. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/examples.html\">on their website.<\/a><\/noindex>I chose the <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/d6\/d56\/samples_2cpp_2edge_8cpp-example.html\">Canny edge detector.<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>The example had to be rewritten a bit to display the image with the results directly in the frame buffer. This was necessary because the function <code>imshow()<\/code> can render images through QT, GTK, and Windows interfaces, which, of course, will not be in the STM32 configuration. In fact, QT can also be run on STM32F7Discovery, but this will be covered in another article \ud83d\ude42<\/p>\n<p><\/p>\n<p>After a brief investigation into the format in which the edge detector's output is stored, we receive the image.<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV on STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/127f90ad8008340d73feb6ece02e52b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Original image<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV on STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/da34b3ac2561ae9f223acc5c4fe2a597.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Result<\/em><\/p>\n<p><\/p>\n<h2 id=\"zapusk-na-stm32f7discovery\">Running on STM32F7Discovery<\/h2>\n<p><\/p>\n<p>The 32F746GDISCOVERY has several hardware memory sections that we can use in one way or another.<\/p>\n<p><\/p>\n<ol>\n<li>320KiB of RAM<\/li>\n<li>1MiB of flash memory for the image<\/li>\n<li>8MiB of SDRAM<\/li>\n<li>16MiB QSPI NAND flash drive<\/li>\n<li>Connector for microSD card<\/li>\n<\/ol>\n<p><\/p>\n<p>The SD card can be used to store images, but in the context of running a minimal example this is not very useful.<br \/>\nThe display has a resolution of 480\u00d7272, which means the memory for the frame buffer will be 522,240 bytes at a depth of 32 bits. This is more than the size of the RAM, so the frame buffer and heap (which will also be needed for OpenCV to store data for images and auxiliary structures) will be located in SDRAM, while everything else (memory for stacks and other system needs) will go to RAM.<\/p>\n<p><\/p>\n<p>If we take a minimal configuration for STM32F7Discovery (removing the entire network, all commands, making the stacks as small as possible, etc.) and add OpenCV with examples, the required memory will be as follows:<\/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>For those who are not very familiar with where sections are allocated, let me explain: in <code>.text<\/code> and <code>.rodata<\/code> lie the instructions and constants (roughly speaking, readonly data), in <code>.data<\/code> lie the mutable data, in <code>.bss<\/code> There are 'nullified' variables that still need space (this section will 'go' to RAM).<\/p>\n<p><\/p>\n<p>The good news is that <code>.data<\/code>\/<code>.bss<\/code> should fit, but the problem is that <code>.text<\/code> there's only 1MiB of memory for the image. You could remove the image from the example and read it, for instance, from an SD card into memory at startup, but fruits.png weighs about 330KiB, so this won't solve the problem: most of it <code>.text<\/code> consists of OpenCV code. <code>.text<\/code> Essentially, there\u2019s only one option left \u2014 load part of the code onto the QSPI flash (it has a special mode for mapping memory onto the system bus, so the processor can access this data directly). However, this presents a problem: firstly, the memory of the QSPI flash is not accessible immediately after the device reboot (you need to separately initialize the memory-mapped mode); secondly, you cannot 'flash' this memory with a conventional bootloader.<\/p>\n<p><\/p>\n<p>Essentially, there is only one thing left - loading part of the code onto the QSPI flash (it has a special operating mode for mapping memory to the system bus, allowing the processor to access this data directly). However, there is a problem: first, the QSPI flash memory is not accessible immediately after rebooting the device (it requires separate initialization of the memory-mapped mode); secondly, you cannot 'program' this memory with the usual bootloader.<\/p>\n<p><\/p>\n<p>The idea of porting this library to Embox appeared about a year ago, but it was repeatedly postponed for various reasons. One of them was support for libstdc++ and the standard template library. The issue of C++ support in Embox is beyond the scope of this article, so I will only say here that we managed to achieve this support to the extent needed for this library \ud83d\ude42<\/p>\n<p><\/p>\n<h1 id=\"rezultat\">Result<\/h1>\n<p><\/p>\n<p>In the end, these issues were overcome (at least to a sufficient degree for the OpenCV example to work), and the example ran. The board takes 40 long seconds to find edges using the Canny filter. This is, of course, too long (there are ideas on how to optimize this, and a separate article can be written about this in case of success).<\/p>\n<p><\/p>\n<p>Nevertheless, the intermediate goal was to create a prototype that would demonstrate the fundamental capability to run OpenCV on STM32; consequently, this goal was achieved, hooray! <\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV on STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a400c72865ec17094efc985908914463.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>tl;dr: step-by-step instructions<\/p>\n<h4 id=\"tldr-poshagovaya-instrukciya\">0: Download the Embox sources, for example, like this:<\/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: Let's start with building the bootloader which will 'flash' the QSPI flash.<\/code><\/pre>\n<p><\/p>\n<p>1: Let's start with building the bootloader that will 'program' the QSPI flash.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-arm\/stm32f7cube<\/code><\/pre>\n<p><\/p>\n<p>Now it's necessary to configure the network since we will load the image via TFTP. To set the IP addresses for the board and the host, the conf\/rootfs\/network file needs to be modified.<\/p>\n<p><\/p>\n<p>Configuration example:<\/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 the address of the host from which the image will be loaded, <code>address<\/code> \u2014 the address of the board.<\/p>\n<p><\/p>\n<p>After this, we compile the bootloader:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make<\/code><\/pre>\n<p><\/p>\n<p>2: Regular boot of the bootloader (pardon the pun) to the board \u2014 there\u2019s nothing specific here, it should be done like any other application for STM32F7Discovery. If you\u2019re not sure how to do this, you can read about it. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/349034\/\">here<\/a><\/noindex>.<br \/>\n3: Compiling the image with the configuration for 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: Extracting from ELF the sections that need to be written to QSPI into 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>In the conf directory, there is a script that does this, so we can run it.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    .\/conf\/qspi_objcopy.sh # Required binary -- build\/base\/bin\/qspi.bin<\/code><\/pre>\n<p><\/p>\n<p>5: Using tftp, we upload qspi.bin to the QSPI flash. On the host, you need to copy qspi.bin to the root folder of the tftp server (usually this is \/srv\/tftp\/ or \/var\/lib\/tftpboot\/; packages for the respective server are available in most popular distributions, usually called tftpd or tftp-hpa, sometimes you need to run <code>systemctl start tftpd.service<\/code> to start it).<\/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>On Embox (i.e. in the bootloader), you need to execute the following command (assuming the server address is 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: Using the command <code>goto<\/code> You need to 'jump' into the QSPI memory. The specific location will vary depending on how the image is linked; you can check this address using a command. <code>mem 0x90000000<\/code> (the start address is stored in the second 32-bit word of the image); you will also need to set the stack with the flag <code>-s<\/code>, the stack address is located at 0x90000000, for example:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt;mem 0x90000000\n    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275\n                      \u2191           \u2191\n              this is the address    this is the address \n                of the stack        of the first\n                           instruction\n\n    embox&gt;goto -i 0x9000c27f -s 0x20023200 # The flag -i is needed to disable interrupts during system initialization<\/code><\/pre>\n<p><\/p>\n<p>7: We launch<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; edges 20<\/code><\/pre>\n<p><\/p>\n<p>and enjoy a 40-second edge detection \ud83d\ude42<\/p>\n<p><\/p>\n<p>If something goes wrong \u2014 report an issue in <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">our repository<\/a><\/noindex>, or in the mailing list embox-devel@googlegroups.com, or in the comments here.<\/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 - 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\/en\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\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\/en\/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 on STM32F7-Discovery | ProHoster","description":"I am one of the developers of the operating system","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","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\/en\/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\/en\/wp-json\/wp\/v2\/posts\/37914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=37914"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/37914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/28450"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=37914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=37914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=37914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}