{"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\/sv\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","title":{"rendered":"OpenCV p\u00e5 STM32F7-Discovery","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenCV p\u00e5 STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a2248ee685ee210ce8f7781435dd1d5a.jpg\" style=\"display:block;margin: 0 auto;\" \/> Jag \u00e4r en av utvecklarna av operativsystemet <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">Embox<\/a><\/noindex>, och i den h\u00e4r artikeln ska jag ber\u00e4tta om hur jag lyckades k\u00f6ra OpenCV p\u00e5 STM32746G-kortet.<\/p>\n<p><\/p>\n<p>\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.<br \/>\nDet finns flera videor som, utifr\u00e5n namnet, borde demonstrera det som beh\u00f6vs, men vanligtvis (i alla videor jag har sett) s\u00e5 utf\u00f6rdes bara bildtagning fr\u00e5n kameran p\u00e5 STM32-kortet och resultatet visades p\u00e5 sk\u00e4rmen, medan sj\u00e4lva bildbehandlingen gjordes antingen p\u00e5 en vanlig dator eller p\u00e5 kraftfullare plattor (till exempel Raspberry Pi).<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"pochemu-eto-slozhno\">Varf\u00f6r \u00e4r detta sv\u00e5rt?<\/h1>\n<p><\/p>\n<p>Populariteten av s\u00f6kfr\u00e5gor f\u00f6rklaras av det faktum att OpenCV \u00e4r det mest popul\u00e4ra biblioteket f\u00f6r datorseende, vilket betyder att fler utvecklare \u00e4r bekanta med det, och m\u00f6jligheten att k\u00f6ra f\u00e4rdig kod f\u00f6r dator p\u00e5 en mikrokontroller f\u00f6renklar utvecklingsprocessen avsev\u00e4rt. Men varf\u00f6r finns det fortfarande inga popul\u00e4ra f\u00e4rdiga l\u00f6sningar p\u00e5 detta problem?<\/p>\n<p><\/p>\n<p>Problemet med att anv\u00e4nda OpenCV p\u00e5 sm\u00e5 enheter \u00e4r relaterat till tv\u00e5 egenskaper:<\/p>\n<p><\/p>\n<ul>\n<li>Om man kompilerar biblioteket \u00e4ven med det minsta antalet moduler s\u00e5 f\u00e5r man helt enkelt inte plats med det i flashminnet p\u00e5 samma STM32F7Discovery (\u00e4ven utan att r\u00e4kna med OS) p\u00e5 grund av den mycket stora koden (flera megabyte instruktioner)<\/li>\n<li>Biblioteket \u00e4r skrivet i C++, vilket inneb\u00e4r\n<ul>\n<li>Att det beh\u00f6vs st\u00f6d f\u00f6r C++ runtime (undantag osv.)<\/li>\n<li>Lite st\u00f6d f\u00f6r LibC\/Posix, som vanligtvis finns i operativsystem f\u00f6r inb\u00e4ddade system \u2013 det beh\u00f6vs standardbibliotek f\u00f6r C++ och STL-standardbibliotek (vector osv.)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"portirovanie-na-embox\">Portering till Embox<\/h1>\n<p><\/p>\n<p>Som vanligt, innan man porterar n\u00e5gra program till operativsystemet, \u00e4r det bra att f\u00f6rs\u00f6ka bygga det i den form som utvecklarna avs\u00e5g. I v\u00e5rt fall finns det inga problem med detta \u2013 k\u00e4llkoden kan hittas p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opencv\/opencv\">GitHub<\/a><\/noindex>, biblioteket kan byggas under GNU\/Linux med vanlig cmake.<\/p>\n<p><\/p>\n<p>Av de goda nyheterna \u00e4r att OpenCV kan byggas som ett statiskt bibliotek direkt, vilket g\u00f6r porteringen enklare. Vi bygger biblioteket med standardkonfigurationen och ser hur mycket utrymme de tar. Varje modul byggs i ett separat bibliotek.<\/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>Som det framg\u00e5r av sista raden tar .bss och .data inte s\u00e5 mycket utrymme, men koden \u00e4r mer \u00e4n 70 MiB. Det \u00e4r klart att om detta statiskt sammanl\u00e4nkas med en specifik applikation kommer koden att bli mindre.<\/p>\n<p><\/p>\n<p>L\u00e5t oss f\u00f6rs\u00f6ka ta bort s\u00e5 m\u00e5nga moduler som m\u00f6jligt f\u00f6r att skapa ett minimalt exempel (som till exempel bara skriver ut versionen av OpenCV), s\u00e5 vi kollar p\u00e5 <code>cmake .. -LA<\/code> och st\u00e4nger av allt som kan st\u00e4ngas av i alternativen.<\/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>\u00c5 ena sidan \u00e4r detta bara en modul av biblioteket, \u00e5 andra sidan \u00e4r detta utan kompilatoroptimering f\u00f6r storleken p\u00e5 koden (<code>-Os<\/code>). ~3 MiB kod \u00e4r fortfarande ganska mycket, men ger redan hopp om framg\u00e5ng.<\/p>\n<p><\/p>\n<h2 id=\"zapusk-v-emulyatore\">K\u00f6rning i emulator<\/h2>\n<p><\/p>\n<p>Det \u00e4r mycket l\u00e4ttare att debugga i emulatorn, s\u00e5 l\u00e5t oss f\u00f6rst s\u00e4kerst\u00e4lla att biblioteket fungerar p\u00e5 qemu. Jag valde Integrator\/CP som emulerad plattform, eftersom det dels ocks\u00e5 \u00e4r ARM, och dels st\u00f6djer Embox grafikutmatning f\u00f6r denna plattform.<\/p>\n<p><\/p>\n<p>\u0412 Embox \u0435\u0441\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c OpenCV \u043a\u0430\u043a \u043c\u043e\u0434\u0443\u043b\u044c (\u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0432\u0441\u0435 \u0442\u0435 \u0436\u0435 \u043e\u043f\u0446\u0438\u0438 \u0434\u043b\u044f &#171;\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439&#187; \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a), \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/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>Vi bygger systemet, k\u00f6r det \u2014 och f\u00e5r f\u00f6rv\u00e4ntad output.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">root@embox:\\\/ #opencv_version                                                     \nOpenCV: \nAllm\u00e4n konfiguration f\u00f6r OpenCV 4.0.1 =====================================\n  Versionskontroll:               bd6927bdf-dirty\n\n  Plattform:\n    Tidsst\u00e4mpel:                   2019-06-21T10:02:18Z\n    V\u00e4rd:                        Linux 5.1.7-arch1-1-ARCH x86_64\n    M\u00e5l:                      Generic arm-unknown-none\n    CMake:                       3.14.5\n    CMake-generator:             Unix Makefiles\n    CMake-byggverktyg:            \\\/usr\\\/bin\\\/make\n    Konfiguration:               Debug\n\n  CPU\\\/HW-funktioner:\n    Baslinje:\n      beg\u00e4rt:                 DETECT\n      inaktiverad:                  VFPV3 NEON\n\n  C\\\/C++:\n    Byggd som dynamiska bibliotek?:      NEJ\n&lt; Fler byggparameter f\u00f6ljer -- vilka flaggor som anv\u00e4ndes vid kompilering,\n  vilka OpenCV-moduler som ing\u00e5r i byggnaden osv.&gt;<\/code><\/pre>\n<p><\/p>\n<p>N\u00e4sta steg \u00e4r att k\u00f6ra ett exempel, helst ett standardexempel fr\u00e5n utvecklarna sj\u00e4lva. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/examples.html\">p\u00e5 deras webbplats.<\/a><\/noindex>. Jag valde <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.opencv.org\/4.1.0\/d6\/d56\/samples_2cpp_2edge_8cpp-example.html\">Canny-kantdetektorn.<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Exemplet fick skrivas om lite f\u00f6r att visa bilden med resultatet direkt i framebuffer. Det h\u00e4r var n\u00f6dv\u00e4ndigt eftersom funktionen <code>imshow()<\/code> kan rita bilder genom QT, GTK och Windows-gr\u00e4nssnitt, vilka sj\u00e4lvklart inte finns i konfigurationen f\u00f6r STM32. Egentligen \u00e4r QT ocks\u00e5 m\u00f6jligt att k\u00f6ra p\u00e5 STM32F7Discovery, men det kommer att beskrivas i en annan artikel \ud83d\ude42<\/p>\n<p><\/p>\n<p>Efter en kort unders\u00f6kning av vilket format resultatet fr\u00e5n kantdetektorn lagras i, f\u00e5r vi bilden.<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV p\u00e5 STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/127f90ad8008340d73feb6ece02e52b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Den ursprungliga bilden<\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV p\u00e5 STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/da34b3ac2561ae9f223acc5c4fe2a597.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Resultat<\/em><\/p>\n<p><\/p>\n<h2 id=\"zapusk-na-stm32f7discovery\">K\u00f6rning p\u00e5 STM32F7Discovery.<\/h2>\n<p><\/p>\n<p>P\u00e5 32F746GDISCOVERY finns det flera h\u00e5rdvaru minnessektioner som vi kan anv\u00e4nda p\u00e5 olika s\u00e4tt.<\/p>\n<p><\/p>\n<ol>\n<li>320KiB RAM-minne.<\/li>\n<li>1MiB flashminne f\u00f6r avbildning.<\/li>\n<li>8MiB SDRAM.<\/li>\n<li>16MiB QSPI NAND-flash.<\/li>\n<li>Anslutning f\u00f6r microSD-kort.<\/li>\n<\/ol>\n<p><\/p>\n<p>SD-kortet kan anv\u00e4ndas f\u00f6r att lagra bilder, men i sammanhanget av att k\u00f6ra ett minimalt exempel \u00e4r det inte s\u00e4rskilt anv\u00e4ndbart.<br \/>\n\u0414\u0438\u0441\u043f\u043b\u0435\u0439 \u0438\u043c\u0435\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 480&#215;272, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0444\u0435\u0440 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 522 240 \u0431\u0430\u0439\u0442 \u043f\u0440\u0438 \u0433\u043b\u0443\u0431\u0438\u043d\u0435 32 \u0431\u0438\u0442\u0430, \u0442.\u0435. \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0444\u0435\u0440 \u0438 \u043a\u0443\u0447\u0443 (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0434\u043b\u044f OpenCV, \u0447\u0442\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440) \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c \u0432 SDRAM, \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 (\u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0441\u0442\u044d\u043a\u0438 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043d\u0443\u0436\u0434\u044b) \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0432 RAM.<\/p>\n<p><\/p>\n<p>Om vi tar en minimal konfiguration f\u00f6r STM32F7Discovery (tar bort allt n\u00e4tverk, alla kommandon, g\u00f6r stackarna s\u00e5 sm\u00e5 som m\u00f6jligt, osv.) och l\u00e4gger till OpenCV med exempel, ser den n\u00f6dv\u00e4ndiga minnesf\u00f6rdelningen ut som f\u00f6ljer:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">   text    data     bss     dec     hex filnamn\n2876890  459208  312736 3648834  37ad42 build\\\/base\\\/bin\\\/embox<\/code><\/pre>\n<p><\/p>\n<p>F\u00f6r dem som inte \u00e4r s\u00e5 bekanta med vilka sektioner som h\u00f6r till vad, l\u00e5t mig f\u00f6rklara: i <code>.text<\/code> och <code>.rodata<\/code> ligger instruktioner och konstanter (grovt sagt read-only-data), i <code>.data<\/code> ligger f\u00f6r\u00e4nderliga data, i <code>.bss<\/code> \u043b\u0435\u0436\u0438\u0442 &#171;\u0437\u0430\u043d\u0443\u043b\u0451\u043d\u043d\u044b\u0435&#187; \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043d\u0443\u0436\u043d\u043e \u043c\u0435\u0441\u0442\u043e (\u044d\u0442\u0430 \u0441\u0435\u043a\u0446\u0438\u044f &#171;\u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f&#187; \u0432 RAM).<\/p>\n<p><\/p>\n<p>Den goda nyheten \u00e4r att <code>.data<\/code>\/<code>.bss<\/code> m\u00e5ste rymmas, men problemet \u00e4r att <code>.text<\/code> underlaget \u00e4r endast 1MiB minne. Man kan ta bort bilden fr\u00e5n exemplet och l\u00e4sa den, till exempel fr\u00e5n ett SD-kort till minnet vid start, men fruits.png v\u00e4ger cirka 330KiB, s\u00e5 det l\u00f6ser inte problemet: st\u00f6rsta delen <code>.text<\/code> best\u00e5r faktiskt av kod fr\u00e5n OpenCV. <code>.text<\/code> Stort sett kvarst\u00e5r bara en sak \u2013 att ladda en del av koden p\u00e5 QSPI-flashminnet (det har ett speciellt driftsl\u00e4ge f\u00f6r minnesmappning p\u00e5 systembussen s\u00e5 att processorn kan komma \u00e5t dessa data direkt). Men det uppst\u00e5r ett problem: f\u00f6r det f\u00f6rsta \u00e4r QSPI-flashminnets minne inte tillg\u00e4ngligt direkt efter omstart av enheten (det m\u00e5ste initieras separat i memory-mapped-l\u00e4get), f\u00f6r det andra kan man inte \"flasha\" detta minne med en vanlig bootloader.<\/p>\n<p><\/p>\n<p>\u041f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0451\u0442\u0443, \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u043d\u0430 QSPI-\u0444\u043b\u044d\u0448\u043a\u0443 (\u0443 \u043d\u0435\u0451 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446. \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u043b\u044f \u043c\u044d\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0443\u044e \u0448\u0438\u043d\u0443, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u043c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e). \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0430\u043c\u044f\u0442\u044c QSPI-\u0444\u043b\u044d\u0448\u043a\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 (\u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c memory-mapped-\u0440\u0435\u0436\u0438\u043c), \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0435\u043b\u044c\u0437\u044f &#171;\u043f\u0440\u043e\u0448\u0438\u0442\u044c&#187; \u044d\u0442\u0443 \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u043c.<\/p>\n<p><\/p>\n<p>Id\u00e9n att portera detta bibliotek till Embox kom upp f\u00f6r ungef\u00e4r ett \u00e5r sedan, men det har g\u00e5ng p\u00e5 g\u00e5ng skjutits upp av olika anledningar. En av dem \u00e4r st\u00f6det f\u00f6r libstdc++ och standard template library. Problemet med C++-st\u00f6det i Embox ligger utanf\u00f6r ramen f\u00f6r denna artikel, s\u00e5 h\u00e4r ska jag bara n\u00e4mna att vi lyckades uppn\u00e5 detta st\u00f6d i den utstr\u00e4ckning som kr\u00e4vs f\u00f6r att anv\u00e4nda detta bibliotek \ud83d\ude42<\/p>\n<p><\/p>\n<h1 id=\"rezultat\">Resultat<\/h1>\n<p><\/p>\n<p>I slut\u00e4ndan \u00f6vervanns dessa problem (\u00e5tminstone i tillr\u00e4cklig utstr\u00e4ckning f\u00f6r att exemplet med OpenCV skulle fungera), och exemplet k\u00f6rdes. Kortl\u00e4ggningen av kanter med Canny-filter tar 40 l\u00e5ngsamma sekunder f\u00f6r styrenheten. Det \u00e4r, naturligtvis, f\u00f6r l\u00e5ngsamt (det finns id\u00e9er om hur man kan optimera detta, och detta kan bli f\u00f6rem\u00e5l f\u00f6r en separat artikel om det lyckas).<\/p>\n<p><\/p>\n<p>Trots detta var den mellanliggande m\u00e5ls\u00e4ttningen att skapa en prototyp som skulle visa den grundl\u00e4ggande m\u00f6jligheten att k\u00f6ra OpenCV p\u00e5 STM32, och den m\u00e5let har uppn\u00e5tts, hurra! <\/p>\n<p>\n<img decoding=\"async\" alt=\"OpenCV p\u00e5 STM32F7-Discovery\" src=\"\/wp-content\/uploads\/2019\/09\/a400c72865ec17094efc985908914463.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>tl;dr: steg-f\u00f6r-steg-instruktioner<\/p>\n<h4 id=\"tldr-poshagovaya-instrukciya\">0: Ladda ner k\u00e4llkoden till Embox, till exempel s\u00e5 h\u00e4r:<\/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: Vi b\u00f6rjar med att bygga bootloadern som \"flashar\" QSPI-flashminnet.<\/code><\/pre>\n<p><\/p>\n<p>1: \u041d\u0430\u0447\u043d\u0451\u043c \u0441\u043e \u0441\u0431\u043e\u0440\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 &#171;\u043f\u0440\u043e\u0448\u044c\u0451\u0442&#187; QSPI-\u0444\u043b\u044d\u0448\u043a\u0443.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make confload-arm\/stm32f7cube<\/code><\/pre>\n<p><\/p>\n<p>Nu beh\u00f6ver vi konfigurera n\u00e4tverket, eftersom vi ska ladda bilden via TFTP. F\u00f6r att ange IP-adresser f\u00f6r kortet och v\u00e4rdena m\u00e5ste filen conf\/rootfs\/network \u00e4ndras.<\/p>\n<p><\/p>\n<p>Exempelkonfiguration:<\/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 v\u00e4rdens adress som bilden kommer att laddas fr\u00e5n, <code>address<\/code> \u2014 kortets adress.<\/p>\n<p><\/p>\n<p>Efter detta samlar vi in startprogrammet:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    make<\/code><\/pre>\n<p><\/p>\n<p>2: Vanlig laddning av startprogrammet (urs\u00e4kta ordleken) till kortet \u2014 h\u00e4r beh\u00f6vs inget specifikt, det g\u00f6rs som f\u00f6r alla andra program f\u00f6r STM32F7Discovery. Om du inte vet hur man g\u00f6r det kan du l\u00e4sa om det <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/embox\/blog\/349034\/\">). Ett typiskt exempel p\u00e5 anv\u00e4ndning:<\/a><\/noindex>.<br \/>\n3: Kompilera bilden med konfigurationen f\u00f6r 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: Utdragning av sektioner fr\u00e5n ELF som ska skrivas till QSPI, i 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>I katalogen conf finns ett skript som g\u00f6r detta, s\u00e5 det g\u00e5r att k\u00f6ra det<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    .\/conf\/qspi_objcopy.sh # Den beh\u00f6vda bin\u00e4ren -- build\/base\/bin\/qspi.bin<\/code><\/pre>\n<p><\/p>\n<p>5: Med hj\u00e4lp av tftp laddar vi qspi.bin.fill i QSPI-flashminnet. P\u00e5 v\u00e4rden m\u00e5ste vi kopiera qspi.bin till rotmappen f\u00f6r tftp-servern (vanligtvis \u00e4r det \/srv\/tftp\/ eller \/var\/lib\/tftpboot\/; paketen f\u00f6r motsvarande server finns i de flesta popul\u00e4ra distributioner, som vanligtvis kallas tftpd eller tftp-hpa, ibland beh\u00f6vs <code>systemctl start tftpd.service<\/code> f\u00f6r att starta).<\/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>P\u00e5 Embox (dvs. i startprogrammet) m\u00e5ste vi k\u00f6ra f\u00f6ljande kommando (vi f\u00f6ruts\u00e4tter att serverns adress \u00e4r 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: Med hj\u00e4lp av kommandot <code>goto<\/code> \u043d\u0443\u0436\u043d\u043e &#171;\u043f\u0440\u044b\u0433\u043d\u0443\u0442\u044c&#187; \u0432 QSPI-\u043f\u0430\u043c\u044f\u0442\u044c. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u043b\u043e\u043a\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u0430\u0440\u044c\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0437 \u0441\u043b\u0438\u043d\u043a\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u044d\u0442\u043e\u0442 \u0430\u0434\u0440\u0435\u0441 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>mem 0x90000000<\/code> (startadressen ligger i den andra 32-bitars ordet av bilden); du beh\u00f6ver ocks\u00e5 st\u00e4lla in stacken med flaggan <code>-s<\/code>, stackens adress ligger vid adress 0x90000000, exempel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt;mem 0x90000000\n    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275\n                      \u2191           \u2191\n              detta \u00e4r adressen    detta \u00e4r adressen \n                f\u00f6r stacken        f\u00f6r f\u00f6rsta\n                           instruktionen\n\n    embox&gt;goto -i 0x9000c27f -s 0x20023200 # Flaggan -i beh\u00f6vs f\u00f6r att f\u00f6rhindra avbrott under systeminitiering<\/code><\/pre>\n<p><\/p>\n<p>7: Vi startar<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">    embox&gt; edges 20<\/code><\/pre>\n<p><\/p>\n<p>och njuter av en 40 sekunder l\u00e5ng kantdetektering \ud83d\ude42<\/p>\n<p><\/p>\n<p>Om n\u00e5got g\u00e5r fel \u2014 skriv en issue i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/embox\/embox\">v\u00e5r repo<\/a><\/noindex>, eller till e-postlistan embox-devel@googlegroups.com, eller i kommentarerna h\u00e4r.<\/p>\n<p>K\u00e4lla: <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.4 - 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\/sv\/blog\/administrirovanie\/opencv-na-stm32f7-discovery\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\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\/sv\/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 p\u00e5 STM32F7-Discovery | ProHoster","description":"Jag \u00e4r en av utvecklarna av operativsystemet","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/opencv-na-stm32f7-discovery","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/37914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=37914"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/37914\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/28450"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=37914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=37914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=37914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}