OpenCV pour Python

De Centre de Ressources Numériques - Labomedia
Aller à : navigation, rechercher

L'installation d'OpenCV pour Python se fait assez simplement sur GNU/Linux (testé et fonctionnel sur Raspberry Pi):

sudo apt-get install python-opencv

Un grand nombre d'exemples sont disponibles dans le dossier samples>python2 de l'archive d'OpenCV téléchargeable sur le site du projet.

De même, l'ouvrage Programming Computer Vision with Python (pdf disponible), offre des explications utiles dans la section consacrée à la librairie.

Le code ci-dessous suffit à afficher le flux d'une webcam :

import cv2

cap = cv2.VideoCapture(0)

while True:
    ret,im = cap.read()
    cv2.imshow('video test',im)
    key = cv2.waitKey(10)

Les informations qui suivent sont issues d'une démarche empirique visant à trouver un moyen de traiter de la vidéo en temps-réel avec Python. Ce n'est donc pas un tutoriel pour apprendre à utiliser OpenCV.

En s'appuyant sur cette image de 3*2 (agrandi pour le besoin du wiki), il est possible de comprendre comment sont stockées les informations relatives à celle-ci, comment y avoir accès et comment les modifier.

3x2.png

Ainsi, ce script...

import cv2
im = cv2.imread('3x2.png')

print im

donne-t-il:

[[[  0   0   0]
  [  0 255   0]
  [  0   0   0]]

 [[  0   0 255]
  [255 255 255]
  [255   0   0]]]

Les informations relative au pixel en bas à droite de notre image sont donc accessibles de cette façon. (À noter que le stockage des couleurs est fait dans l'ordre BLEU-VERT-ROUGE, inverse d'un intuitif RVB)

# pour le niveau de Bleu
print im[1][2][0]
# pour le niveau de Vert
print im[1][2][1]
# pour le niveau de Rouge
print im[1][2][2]

De même , le script suivant remplacera le pixel blanc (au milieu, en bas) par un pixel jaune :

import cv2
im = cv2.imread('3x2.png')

im[1][1] = [0, 255, 255]

# sauvegarde du resultat
cv2.imwrite('resultat.png',im)

Ces manipulations sont, bien évidemment, aussi possibles en vidéo. Par exemple, le script ci-dessous trace une ligne rouge horizontale puis une ligne bleue verticale, en temps-réel, sur un flux vidéo capturé par une webcam.

import cv2

# setup video capture
cap = cv2.VideoCapture(0)

ret,im = cap.read()
height, width = im.shape[:2]

while True:
    ret,im = cap.read()

    # trait horizontal
    for i in range(width):
        im[height/2][i] = [0, 0, 255]

    # trait vertical
    for i in range(height):
        im[i][width/2] = [255, 0, 0]

    cv2.imshow('video test',im)
    key = cv2.waitKey(10)


Axe.jpg

Remarque:

La fonction pour ajouter une ligne horizontale sans calcul:

cv2.line(img,  point1,  point2,      couleur,  épaisseur)
cv2.line(img, (0, 270), (960, 270), (0, 0, 0), 1)

Pour information, pour peu que les scripts n'aient pas a afficher d'image, les traitements sont possibles sur une Raspberry Pi sans avoir besoin de lancer de session graphique.

Taille des sources vidéo

La taille des flux vidéos capturés se définie avec .set(ID, valeur), où ID=3 pour la largeur et ID=4 pour la hauteur.

Le script ci-dessous attribue une taille de 320*240 à cap0 et 160*120 à cap1

import cv2

cap0 = cv2.VideoCapture(0)
cap0.set(3,320)
cap0.set(4,240)

cap1 = cv2.VideoCapture(1)
cap1.set(3,160)
cap1.set(4,120)

while True:

    ret0,im0 = cap0.read()
    ret1,im1 = cap1.read()    

    cv2.imshow("vid-0",im0)
    cv2.imshow("vid-1",im1)

    key = cv2.waitKey(10)


Size-Video-OpenCV.jpg


Pour info, voici la liste de ID des propriétés existante pour .set() (et pour .get(), par ailleurs).

  • 0 - CV_CAP_PROP_POS_MSEC Current position of the video file in milliseconds.
  • 1 - CV_CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
  • 2 - CV_CAP_PROP_POS_AVI_RATIO Relative position of the video file
  • 3 - CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
  • 4 - CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
  • 5 - CV_CAP_PROP_FPS Frame rate.
  • 6 - CV_CAP_PROP_FOURCC 4-character code of codec.
  • 7 - CV_CAP_PROP_FRAME_COUNT Number of frames in the video file.
  • 8 - CV_CAP_PROP_FORMAT Format of the Mat objects returned by retrieve() .
  • 9 - CV_CAP_PROP_MODE Backend-specific value indicating the current capture mode.
  • 10 - CV_CAP_PROP_BRIGHTNESS Brightness of the image (only for cameras).
  • 11 - CV_CAP_PROP_CONTRAST Contrast of the image (only for cameras).
  • 12 - CV_CAP_PROP_SATURATION Saturation of the image (only for cameras).
  • 13 - CV_CAP_PROP_HUE Hue of the image (only for cameras).
  • 14 - CV_CAP_PROP_GAIN Gain of the image (only for cameras).
  • 15 - CV_CAP_PROP_EXPOSURE Exposure (only for cameras).
  • 16 - CV_CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB.
  • 17 - CV_CAP_PROP_WHITE_BALANCE Currently unsupported
  • 18 - CV_CAP_PROP_RECTIFICATION Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently)

Déplacement des fenêtres et multiplication des sources

Il est possible de choisir sa source avec cv2.VideoCapture(0).

  • cv2.VideoCapture(0) ouvre /dev/video0
  • cv2.VideoCapture(1) ouvre /dev/video1
  • ...

Il est possible choisir la position de chaque fenêtre de rendu, ainsi que de les déplacer avec cv2.moveWindow(video_name, posX, posY)

Le script ci-dessous ouvre deux flux, affiche 14 fenêtres et les déplacent sur l'écran :

import cv2

# setup video capture
cap0 = cv2.VideoCapture(0)
cap1 = cv2.VideoCapture(1)

posV, posH = 0, 0

while True:

    ret0,im0 = cap0.read()
    ret1,im1 = cap1.read()
    
    if (posV == 200):
        posV = 0

    if (posH > 900):
        posH = 0

    for i in range (6):

        video_name = 'test2-{0}'.format(i)
        cv2.imshow(video_name.format(i),im0)
        cv2.moveWindow(video_name, posH+i*80, i*50)

    for i in range (8):

        video_name = 'test-{0}'.format(i)
        cv2.imshow(video_name.format(i),im1)
        cv2.moveWindow(video_name, 160*i+40, posV+i*50)

    key = cv2.waitKey(10)

    posV += 10
    posH += 8


Mosaic.jpg


Infos utiles dans ce contexte

Liste des paramètres accessibles sur v4l2

sudo apt-get install uvcdynctrl

puis

uvcdynctrl -d video0 -c

pour avoir le détail des valeurs possibles

uvcdynctrl -c -v

Réglage du focus en python

import os
os.system(uvcdynctrl -d video0 -s "Focus (absolute)" 10) # 0 to 40

Autoriser l'ouverture de fenêtres sur X en root

En cas de :

Client is not authorized to connect to Server
(video test:2420): Gtk-WARNING **: cannot open display: :1.0

Taper en console

xhost +

référence : Ruru