Explorer OpenCV sur StereoPi: carte de profondeur à partir de la vidéo



Aujourd'hui, nous voulons partager une série d'exemples sur Python pour les apprenants OpenCV sur le Raspberry Pi, à savoir la carte StereoPi à double chambre. Le code fini (plus l'image Raspbian) vous aidera à passer par toutes les étapes, en commençant par la capture d'une image et en terminant par l'obtention d'une carte de profondeur de la vidéo capturée.

Introduction


Je dois souligner tout de suite que ces exemples sont pour une immersion confortable dans le sujet, et non pour une solution de production. Si vous êtes un utilisateur avancé d'OpenCV et que vous avez eu affaire à des framboises, alors vous savez que pour un travail à part entière, il est conseillé de coder une bouchée, et même d'utiliser un GPU framboise. À la fin de l'article, j'aborderai plus en détail les «goulots d'étranglement» de la solution python et les performances globales.

Avec quoi travaillons-nous


Nous avons une configuration telle que le fer:



Carte StereoPi à bord du Raspberry Pi Compute Module 3+. Les deux caméras les plus simples sont connectées pour la version Raspberry Pi V1 (sur le capteur ov5647).

Ce qui est installé:

  • Raspbian Stretch (noyau 4.14.98-v7 +)
  • Python 3.5.3
  • OpenCV 3.4.4 (précompilé, «pip» de Python Wheels)
  • Picamera 1.13
  • StereoVision lib 1.0.3 (https://github.com/erget/StereoVision)

Le processus d'installation de tous les logiciels dépasse le cadre de cet article, et nous vous suggérons simplement de télécharger l'image Raspbian finie (liens vers le github à la fin de l'article).

Première étape: capturer une image


Pour ce faire, utilisez le script 1_test.py

Ouvrez la console, allez du dossier d'accueil au dossier avec des exemples:

cd stereopi-tutorial 

Exécutez le script:

 python 1_test.py 

Après le démarrage, un aperçu de notre image stéréo s'affiche à l'écran. Le processus peut être interrompu en appuyant sur le bouton Q. Cela enregistrera la dernière image capturée, qui sera utilisée dans l'un des scripts suivants pour configurer la carte de profondeur.

Ce script vous permet de vous assurer que tout le matériel fonctionne correctement, ainsi que d'obtenir la première image pour une utilisation future.

Voici à quoi ressemble le premier script:


Deuxième étape: collecter des images pour l'étalonnage


Si nous parlons d'un cheval sphérique dans le vide, pour obtenir une carte de profondeur de bonne qualité, nous devons avoir deux caméras absolument identiques, dont les axes vertical et optique sont parfaitement parallèles et les axes horizontaux coïncident. Mais dans le monde réel, toutes les caméras sont légèrement différentes et il n'est pas possible de les organiser parfaitement. Par conséquent, une astuce d'étalonnage logiciel a été inventée. À l'aide de deux caméras du monde réel, un grand nombre de photos d'un objet précédemment connu sont prises (nous avons une photo avec un échiquier), puis un algorithme spécial calcule toutes les «imperfections» et essaie de corriger les photos afin qu'elles soient proches de l'idéal.

Ce script fait la première étape du travail, à savoir qu'il aide à faire une série de photos pour l'étalonnage.

Avant chaque photo, le script démarre un compte à rebours de 5 secondes. Cette fois, en règle générale, il suffit de déplacer la carte dans une nouvelle position, pour s'assurer que sur les deux caméras, elle ne rampe pas sur les bords et ne fixe pas sa position (afin qu'il n'y ait pas de flou sur la photo). Par défaut, la taille de la série est définie sur 30 photos.

Lancement:

 python 2_chess_cycle.py 

Processus:


En conséquence, nous avons une série de photos dans le dossier / scènes.

Nous coupons les images en paires


Le troisième script 3_pairs_cut.py coupe les photos prises en images «gauche» et «droite» et les enregistre dans le dossier / pairs. En fait, nous pourrions exclure ce script et faire la découpe à la volée, mais il est très utile dans d'autres expériences. Par exemple, vous pouvez enregistrer des tranches de différentes séries, utiliser vos scripts pour travailler avec ces paires, ou même supprimer les photos prises sur d'autres caméras stéréo par paires.

De plus, avant de couper chaque image, le script affiche son image, ce qui vous permet souvent de voir les photos ayant échoué avant la prochaine étape de calibrage et de simplement les supprimer.

Exécutez le script:

 python 3_pairs_cut.py 

Petite vidéo:


Dans l'image finale, il y a un ensemble de photographies et de paires de coupes que nous avons utilisées pour nos expériences.

Calibration


Le script 4_calibration.py dessine toutes les paires avec les échiquiers et calcule les corrections nécessaires pour corriger les images. Dans le scénario, un rejet automatique des photographies sur lesquelles aucun échiquier n'a été trouvé a été effectué, de sorte qu'en cas de photographies infructueuses, le travail ne s'arrête pas. Une fois les 30 paires d'images téléchargées, le calcul démarre. Cela nous prend environ une minute et demie. Une fois terminé, le script prend l'une des paires stéréo et, sur la base des paramètres d'étalonnage calculés, les «corrige», affichant une image rectifiée à l'écran. À ce stade, vous pouvez évaluer la qualité de l'étalonnage.

Exécuté par la commande:

 python 4_calibration.py 

Script d'étalonnage en cours:


Configuration de la carte de profondeur


Le script 5_dm_tune.py charge l'image prise par le premier script et les résultats de l'étalonnage. Ensuite, une interface s'affiche qui vous permet de modifier les paramètres de la carte de profondeur et de voir ce qui change. Astuce: avant de régler les paramètres, prenez un cadre dans lequel vous aurez simultanément des objets à différentes distances: proche (30-40 centimètres), à une distance moyenne (mètre ou deux) et à distance. Cela vous permettra de choisir les paramètres dans lesquels les objets proches seront rouges et les objets distants seront bleu foncé.

L'image contient un fichier avec nos paramètres de carte de profondeur. Vous pouvez charger nos paramètres dans un script en cliquant simplement sur le bouton «Charger les paramètres»

Nous lançons:

 python 5_dm_tune.py 

Voici à quoi ressemble le processus de configuration:


Carte de profondeur en temps réel


Le dernier script 6_dm_video.py construit une carte de profondeur à partir de la vidéo en utilisant les résultats des scripts précédents (calibration et paramétrage de la carte de profondeur).

Lancement:

 python 6_dm_video.py 

En fait, le résultat:


Nous espérons que nos scripts vous seront utiles dans vos expériences!

Juste au cas où, j'ajouterai que tous les scripts ont un traitement de frappe, et vous pouvez interrompre le travail en appuyant sur le bouton Q. Si vous arrêtez "grossièrement", par exemple, Ctrl + C, le processus d'interaction de Python avec la caméra peut se casser et un redémarrage de la framboise sera nécessaire.

Pour avancé


  • Le premier script du processus affiche le temps moyen entre les captures d'image et, à la fin, le FPS moyen. Il s'agit d'un outil simple et pratique pour sélectionner de tels paramètres d'image dans lesquels le python ne "s'étouffe" toujours pas. Avec lui, nous avons ramassé 1280x480 à 20 FPS, dans lequel la vidéo est rendue sans délai.
  • Vous remarquerez peut-être que nous capturons une paire stéréo en résolution 1280x480, puis la redimensionnons à 640x240.

    Une question raisonnable: pourquoi tout cela, et pourquoi ne pas saisir immédiatement la vignette et ne pas charger notre python en le réduisant?

    Réponse: avec la capture directe à très basse résolution, il y a toujours des problèmes dans le cœur de framboise (l'image se casse). Par conséquent, nous prenons une résolution plus grande, puis réduisons l'image. Ici, nous utilisons une petite astuce: l'image n'est pas mise à l'échelle avec python, mais avec l'aide du GPU, donc il n'y a pas de charge sur le noyau du bras.
  • Pourquoi capturer une vidéo au format BGRA, pas BGR?
    Nous utilisons des ressources GPU pour réduire la taille de l'image, et le natif du module de redimensionnement est le format BGRA. Si nous utilisons BGR au lieu de BGRA, nous aurons deux inconvénients. Le premier est légèrement inférieur au FPS final (dans nos tests - 20%). Le second est le portage constant dans la console "PiCameraAlfaStripping: utiliser l'alpha-stripping pour convertir au format non alpha; vous pouvez trouver un format alpha équivalent plus rapidement ». La recherche sur Google a conduit à la section de documentation de Picamera, qui décrit cette astuce.
  • Où est le PiRGBArray?

    C'est comme la classe native Picamera pour travailler avec l'appareil photo, mais ici, elle n'est pas utilisée. Il s'est déjà avéré que dans nos tests, travailler avec un tableau numpy «fait à la main» est beaucoup plus rapide (une fois et demie) que d'utiliser PiRGBArray. Cela ne signifie pas que PiRGBArray est mauvais, ce sont probablement nos mains tordues.
  • Quel est le pourcentage chargé dans le calcul de la carte de profondeur?
    Répondons avec une photo:



    On voit que sur les 4 cœurs du processeur, en fait, un seul est chargé, soit 70%. Et cela malgré le fait que nous travaillons avec une interface graphique et que nous fournissons des images et des cartes de profondeur à l'utilisateur. Cela signifie qu'il y a une bonne marge de performance, et un réglage fin d'OpenCV avec OpenMP et d'autres goodies en C, ainsi qu'un mode «combat» sans interface graphique peuvent donner des résultats très intéressants.
  • Quelle est la carte de profondeur FPS maximale obtenue avec ces paramètres?

    Le maximum atteint par nous était de 17 FPS, lors de la capture de 20 images par seconde de la caméra. Les paramètres de vitesse les plus «réactifs» dans les paramètres de la carte de profondeur sont MinDisparity et NumOfDisparities. Ceci est logique, car ils déterminent le nombre "d'étapes" effectuées au sein de l'algorithme par la fenêtre de recherche pour comparer les trames. Le deuxième plus réactif est preFilterCap, il affecte, en particulier, la «fluidité» de la carte de profondeur.
  • Qu'en est-il de la température du processeur?

    Sur Compute Module 3+ Lite (une nouvelle série, avec un «cap» de fer sur le processus), il montre à peu près les résultats suivants:

  • Comment utiliser le GPU?

    Au minimum, il peut être utilisé pour l'istorisation et la rectification d'images en temps réel, car il existe des exemples ( ici sur WebGL ), Python Pi3d , ainsi que le projet Processing ( exemples pour les framboises ).

    Il y a un autre développement intéressant de Koichi Nakamura, appelé py-videocore . Dans notre correspondance avec lui, il a exprimé l'idée que pour accélérer StereoBM, vous pouvez utiliser ses tris core et OpenCV avec le support Cuda . En général, pour l'optimisation - un bord intact, comme on dit.

Merci de votre attention et voici le lien promis vers la source .

Source: https://habr.com/ru/post/fr446872/


All Articles