Ceci est une ancienne révision du document !
Table des matières
Panorama
Introduction
Le but de ce tutoriel sera d'effectuer un panorama utilisant le raspberry pi et sa camera.
On aurrait pu pour cela tourner la camera du raspberry pi à la main, ou utiliser plusieurs raspberry pi avec
leurs camera pour pouvoir avoir une vue panoramique, mais c'est asser contraignant soit en temp ou en ressource.
La seule solution possible étant d'utiliser un support avec double servo moteurs qu'on peut trouver généralement avec des kit du raspberry pi.
En premier lieu on montrera comment fussionner 2 images sous python.
Puis je présenterais le code python nomméservo.py permettant de bouger la camera dans toutes les directions, j'expliquerais aussi le montage électrique asser simple à faire car il faut utiliser une source 5v externe et non celle du raspberry pi car l'utilisation des
servo moteurs peuvent tirer beaucoup d'ampere et risquerais de terminer le raspberry pi.
Puis apres ça je présenterais un petit code shell nommé fishEye.sh qui utiliserera la commande python faite précedement et qui prendra plusieurs photo avec une vue 360 degré voir panorama
Vous pouvez télécharger le code source directement avec wget en console, exemple avec le fichier fishEye.sh
wget https://github.com/hiergaut/unix/blob/master/raspbian/bin/fishEye.sh
lire aussi le README.md sur github
Commencement avec python et explication
Le principe même du panorama entre deux photo est de reperer les similitudes entres elles comme des coins ou autres formes facilement reperables. Prenons ces deux photos pour entrainement
on peut visionner ces formes de cette façon en python
img =cv2.imread('panorama_0.jpg') img_gray =cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sift_obj =cv2.xfeatures2d.SIFT_create() kp, _ =sift_obj.detectAndCompute(img_gray, None) img =cv2.drawKeypoints(img_gray, kp, img) # img =cv2.drawKeypoints(img_gray, kp, img, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv2.imshow('w', img) while cv2.waitKey(10) != 27: continue
avant de faire la fusion il faut trouver les points qui se trouve sur les 2 images, on peut visionner cela avec ce code
img1c =cv2.imread('panorama_0.jpg') img2c =cv2.imread('panorama_1.jpg') sift_obj =cv2.xfeatures2d.SIFT_create() kp1, des1 =sift_obj.detectAndCompute(img1c, None) kp2, des2 =sift_obj.detectAndCompute(img2c, None) # FLANN parameters FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks=50) # or pass empty dictionary flann = cv2.FlannBasedMatcher(index_params,search_params) matches = flann.knnMatch(des1,des2,k=2) img3 = cv2.drawMatchesKnn(img1c,kp1,img2c,kp2,matches,None) cv2.imshow("correspondences", img3) cv2.waitKey()
on visionne les points repere entres les 2 images, on peut voir qu'il y en a beaucoup
puis on peut utiliser le code decrit dans ce tuto https://www.pyimagesearch.com/2016/01/11/opencv-panorama-stitching/ pour fusionner les deux parties.
Le programme python etant lent je décide dans la suite de ce tuto d'utiliser du code cpp, un programme deja ecrit qui permettra de créer des panorama cylindrique et stéréographique.
./stitching --features orb --warp stereographic picture*.jpg ./stitching --features orb --warp cylindric picture*.jpg
on souhaite faire un panorama 360° avec des photos prise par la camera du rpi, on aurrait pu utiliser plusieurs rpi cote à cote, avec des inclinaisons differentes, mais l'option d'utiliser 2 servomoteurs permettra d'avoir une vue spherique de l'ensemble de l'environnement juste avec qu'un camera pi.
Presentation du montage maison avec le support double servo attaché sur le boitier du raspberry pi avec des tyraps.
Presentation du montage électrique
avant de lancer le panorama, il faut preparer un programme python pour diriger la camera selon n'importe quel inclinaison je décide de créer une fonction prenant 2 argument [-180..180] pour autour de l'axe vertical, [0..90] autour de l'axe horizontal. voici le code python
import RPi.GPIO as GPIO import time def angle(vAngle, hAngle): hPin=21 vPin=16 GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(hPin, GPIO.OUT) GPIO.setup(vPin, GPIO.OUT) f=50 hPwm =GPIO.PWM(hPin, f) vPwm =GPIO.PWM(vPin, f) assert (-180 <= vAngle and vAngle <= 180) assert (0 <= hAngle and hAngle <= 90) if -90 <= vAngle and vAngle <= 90: vPwm.start(11 -(vAngle +90) *8 /180.0) hPwm.start(hAngle *4 /90.0 +2) elif vAngle < -90: vPwm.start(7 -(vAngle +180) *4 /90.0) hPwm.start(10 -hAngle *4 /90.0) else: vPwm.start(11 -(vAngle -90) *4 /90.0) hPwm.start(10 -hAngle *4 /90.0) time.sleep(1) hPwm.stop vPwm.stop
on peut prendre des photos avec une inclinaisons autours de l'axe horizontal de 0 et 45 degre tout autour de l'axe vertical d'un pas de 45 degre avec le code suivant, en n'oubliant pas d'importer le code precedent
from servo import angle import os #cap = cv2.VideoCapture(0) #cap.set(3, 1920) #cap.set(4, 1080) #cap.set(6, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G')) #angle(0, 0) #_, frame =cap.read() #cv2.imwrite('photo_0_0.jpg', frame) for i in (0, 45): for j in (0, 45, 90, 135, 180, -135, -90, -45): angle(j, i) if -90 <= j and j <= 90: os.system('raspistill -t 1 -vf -hf -o photo_' +str(j) +'_' +str(i) +'.jpg') else: os.system('raspistill -t 1 -o photo_' +str(j) +'_' +str(i) +'.jpg')
j'utilise raspistill au lieu d'utiliser VideoCapture de opencv, en n'oubliant pas de tourner l'image avec l'option vf et hf de raspistill
tout cela résumer dans cette video
maintenant reste plus qu'a fusionner les images recement capturées, pour cela telechargeons le code cpp sur github https://github.com/opencv/opencv/blob/master/samples/cpp/stitching.cpp
g++ stitching.cpp `pkg-config --cflags --libs opencv` -o stitching
prise de vue salle de cours, team be traitement d'image sous rpi:
mode cylindrique:
./stitching --features orb --warp cylindric *.jpg
mode stereographique:
./stitching --features orb --warp stereographic *.jpg