6.3.2025
Pro Dioflex stále vyvíjíme nové a nové aplikace a usnadňujeme, zpřehledňujeme a urychlujeme jim tak práci. Zatím posledním dílem je aplikace pro evidenci reklamací. V podstatě jde o jednoduchou aplikaci, která snímačem čárových kódů načte identifikaci reklamovaného výrobku a na speciální tiskárně vytiskne štítek s QR kódem a popisem závady. Celé je to pochopitelně složitější, protože informace o výrobku jsou uložené v několika různých informačních systémech, reklamovaný výrobek je nutné vyfotit (celkový pohled plus mikroskopický snímek), zaevidovat a poslat zákazníkovi zprávu o přijaté reklamaci. Čas potřebný k zavedení reklamace do systému se díky naší aplikaci zkrátil z deseti minut na méně než minutu.
Kvůli fotografiím je celá aplikace vytvořená pro Raspberry Pi 5, ke kterému lze připojit dvě HQ kamery. A právě kamery se ukázaly jako zatraceně tvrdý oříšek. I přes velkou rozšířenost Raspberry Pi není použití kamer jednoduché a v potřebných knihovnách se vyskytují nepříjemné chyby.
Kamera v Rpi se do Qt + QML aplikace připojuje pomocí GStreameru (dále GST). To je systém pro zpracování obrazu a zvuku, který umožňuje řadit za sebe různé filtry a manipulátory s obrazovou informací a dosáhnout postupnými kroky požadované funkčnosti. Tím může být například prosté zobrazení výstupu z „nějaké“ kamery na obrazovce:
gst-launch-1.0 v4l2src ! videoconvert ! autovideosink
Tuto GST rouru můžete použít na obyčejném linuxovém PC s připojenou USB (či jinou) kamerou. Raspberry Pi je mírně odlišné. Kamera HQ není připojená přes standardní linuxový V4L2 systém, používá knihovnu libcamera:
gst-launch-1.0 libcamerasrc ! videoconvert ! autovideosink
Na Raspberry Pi bez grafické nadstavby se tímto zobrazí výstup z kamery přímo na konzole (pohodlnější je proto pracovat na Raspberry přes síť). Chceme-li poslat výstup do Qt aplikace, je nutné změnit výstupní element ve frontě:
libcamerasrc ! videoconvert ! qtvideosink
Takovou GST rouru už pochopitelně nelze spustit na povelové řádce, musí se použít jednoduchá QML aplikace, například:
import QtQuick 2.7 import QtMultimedia 5.15 Item { width: 800; height: 600; MediaPlayer { id: player; autoLoad: true; autoPlay: true; source: "gst-pipeline: libcamerasrc ! videoconvert ! qtvideosink" } VideoOutput { source: player; anchors.fill: parent; } }
Potíž je s rozlišením. Libcamerasrc zvolí nejmenší dostupné rozlišení. GST na to samozřejmě pamatuje a umožňuje rozlišení zvětšit. Dostupná rozlišení a kamery si lze vypsat:
root@raspberrypi:~# libcamera-vid --list-cameras Available cameras ----------------- 0 : imx477 [4056x3040 12-bit RGGB] (/base/soc/i2c0mux/i2c@1/imx477@1a) Modes: 'SRGGB10_CSI2P' : 1332x990 [120.05 fps - (696, 528)/2664x1980 crop] 'SRGGB12_CSI2P' : 2028x1080 [50.03 fps - (0, 440)/4056x2160 crop] 2028x1520 [40.01 fps - (0, 0)/4056x3040 crop] 4056x3040 [10.00 fps - (0, 0)/4056x3040 crop]
GST rouru jsem požádal o větší rozlišení (vypisuji pouze jeden řádek s parametrem source v QML aplikaci):
gst-pipeline: libcamerasrc ! video/x-raw,width=4056,height=3040 ! videoconvert ! qtvideosink
Při pokusu zvolit větší rozlišení jsem ale dostal místo obrazu šikmé pruhy s nabouranou barevnou informací. Vlevo požadovaný obrázek, vpravo rozbitý obrázek:
Šikmé pruhy naznačují, že někde v průběhu zpracovaní GST roury došlo ke špatné interpretaci délky řádku. Za touto jednoduchou větou se ukrývá týden práce a ladění, stovky megabajtů hexadecimálních výpisů a spousta frustrace a ztracených nervů.
Nebudu vás unavovat technickými detaily, zde je přímo výsledek pro Raspberry Pi 4 i pro Rasbperry Pi 5:
// Rpi 4: gst-pipeline: libcamerasrc ! video/x-raw,width=4056,height=3040,format=NV12 ! rawvideoparse format=nv12 width=4056 height=3040 plane-strides=<4064,4064> plane-offsets=<0,12354560> frame-size=37063680 ! qtvideosink sync=false // Rpi 5: gst-pipeline: libcamerasrc ! video/x-raw,width=4056,height=3040,format=NV12 ! rawvideoparse format=nv12 width=4056 height=3040 plane-strides=<4096,4096> plane-offsets=<0,12451840> frame-size=37355520 ! qtvideosink sync=false
Užitečné může být ještě využití názvů kamer, pokud je jich k Raspberry Pi připojeno více.
Identifikaci kamer lze zjistit pomocí libcamera-vid --list-camera
(popsáno výše)
a mezi různými HQ kamerami zvolit takto:
gst-pipeline: libcamerasrc camera-name=/base/soc/i2c0mux/i2c@1/imx477@1a ! ...
Na mém Raspberry Pi 5 jsou kamery pojmenovány takto: /base/axi/pcie@120000/rp1/i2c@80000/imx477@1a
a /base/axi/pcie@120000/rp1/i2c@88000/imx477@1a
.
Jméno se liší jediným písmenkem, rozpoznat, že se jména skutečně liší, taktéž zabralo obrovskou spoustu času!
Po příčině chyb jsem nepátral. Chyba může být v GST, stejně tak i v libcamera. Budete-li zkoušet spustit GST ve vyšším rozlišení na konsoli Raspberry Pi, narazíte ještě na další chybu: obrázek je barevně zcela mimo. Na Qt aplikaci to nemá žádný vliv, může vás to však svést na scestí ve snaze ladit GST rouru na povelové řádce.
Raspberry Pi je levný počítač, který zvládne za málo peněz obrovské množství práce. Nízká cena, vysoká míra přizpůsobitelnosti a rozličné způsoby komunikace se světem umožňují použít Raspberry Pi na místech, kde použití normálního PC není vhodné. Náš software pečlivě vytvořený podle vysoce specifických požadavků zákazníků běží na stovkách instalací: Dioflex, Náš nový vrátný, Vacushape, Robe.