OpenCV a la RPi

De Wikijoan
Dreceres ràpides: navegació, cerca

Contingut

Introducció

La idea és utilitzar OpenCV per al reconeixement d'imatges en una recreativa de dards. L'objectiu es detectar amb dues webcams la posició exacta on s'ha tirat el dard. S'ha descartat la possibilitat de fer-ho amb alguna xarxa resistiva. Sembla ser que el mètode més net (i que ja ha fet algú altra) és utilitzar visió artificial.

L'objectiu és instal.lar OpenCV a la RPi 3, i fer totes les proves que em condueixin a detectar la posició dels dards. Primer es discuteix la instal.lació, i després les primeres proves de programació amb l'API de C++.

Instal.lació OpenCV 3 a la RPi 3 (Raspbian Jessie) (desembre 2016)

En una RPi B+ tenia instal.lat OpenCV:

sudo apt-get install libopencv-dev python-opencv

Quedava instal.lat el OpenCV 2.4.1. La funció findNonZero() no està implementada en aquesta versió. Decideixo migrar a la RPi 3, i instal.lar OpenCV des de les fonts.

Primer vull instal.lar OpenCV 3 a la RPi B+ seguint el següent tutorial: Installing OpenCV 3 on Raspbian Jessie (ell ho ha fet amb la Rpi2)

i m'ha donat problemes quan faig el sudo apt-get upgrade.

Instal.lo OpenCV3 a la RPi 3 seguin la següent versió del tutorial:

Aquest tutorial està orientat a utilitzar Python com a entorn de programació. I jo el que vull és utilitzar C++, que de fet és l'entorn nadiu. Per tant, el que he de fer és deixar de fer bastantes coses que es comenta en el tutorial.

Pas a pas, la manera de procedir que a mi m'ha funcionat, seguint el tutorial, és:

$ sudo raspi-config
$ sudo reboot
$ sudo apt-get purge wolfram-engine
$ sudo apt-get update

Em sembla que no he fet el upgrade

Coses meves:

$ sudo apt-get install joe
$ sudo apt-get install build-essential git cmake pkg-config

$ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
$ sudo apt-get install libxvidcore-dev libx264-dev
$ sudo apt-get install libgtk2.0-dev
$ sudo apt-get install libatlas-base-dev gfortran

Jo no instal.lo python2.7-dev ni python3-dev. Tampoc no instal.lo el pip (python package manager), ni tampoc instal.lo virtualenv ni virtualenvwrapper, perquè a mi no em caldrà cap Python virtual environment (jo programaré directament amb C++).

Descarrego el codi font de OpenCV:

$ cd ~
$ wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.1.0.zip
$ unzip opencv.zip

$ wget -O opencv_contrib.zip https://github.com/Itseez/opencv_contrib/archive/3.1.0.zip
$ unzip opencv_contrib.zip

Ja podem compilar des de les fonts:

$ cd ~/opencv-3.1.0/
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.1.0/modules \
    -D BUILD_EXAMPLES=ON ..

(em carrego la línia -D INSTALL_PYTHON_EXAMPLES=ON \ que posa en el tutorial).

Quan acaba de fer el build, fixem-nos el resultat que tenim en pantalla, per saber quins seran els directoris importants i què estem a punt de compilar/instal.lar. Compilació:

$ make

Faig un make normal perquè el que proposa el tutorial és fer

$ make -j4

per tal d'aprofitar els 4 cores de la RPi3. Però a mi se'm penja (com es comenta que pot passar...). Per tant, faig la compilació normal, encara que triga molt més.

Instal.lació:

$ sudo make install
$ sudo ldconfig

I per comprovar que tot funciona correctament, el millor és provar els exemples que es fan en el següent punt.

Primeres proves a la RPi. Historial de proves

Els exemples que estic provant estan a /home/joan/recreativa_dards/proves_opencv.

Algunes proves utilitzen la webcam. De moment estic utilitzant una Logitech QuickCam Express. S'haurà de veure si aquesta webcam tindrà prou resolució, i també si en puc connectar dues alhora de forma viable. També tinc una RaspiCAM IR que es pot fer servir, però de moment no doncs sembre serà més barato utilitzar una d'aquestes webcams que es poden trobar barates.

1. color2grey.cpp: primera prova. Converteixo una imatge a escala de gris.

2. camera_capture1.cpp. Tinc la webcam (Logitche QuickCam Express) connectada, i ja puc llegir frames de la càmera

3. Simplegrab.cpp. Una altra manera de fer-ho. Obrim un dispositiu de video captura.

Amb les primeres proves que vaig fer amb la Rpi B+ i OpenCV 2.4.1, la resolució del frame és 176x144 (fa servir SBRG8 perquè S561 no funciona)

Amb les proves que faig amb la Rpi3 i OpenCV 3.0.1, la resolució del frame és 352x288 (fa servir S561, que ara funciona correctament)

Ara que ja sé generar imatges a partir de la càmera, començo a fer proves per detectar formes i colors.

4. detectar_vermell.cpp. Només em quedo amb el quadrat vermell

5. detectar_vermell2.cpp

6. detectar_vermell3.cpp -> no funciona. He d'instal.lar OpenCV 2.4.4 mínim -> he instal.lat OpenCV 3.0.1 i ja funciona

dpkg -l | grep libopencv
ii  libopencv-calib3d-dev                 2.4.1+dfsg-0exp2rpi2
...

Tinc instal.lada la versió 2.4.1, i per utilitzar findNonZero necessito com a mínim la versió OpenCV 2.4.4 (http://stackoverflow.com/questions/19242662/opencv-find-all-non-zero-coordinates-of-a-binary-mat-image)

7. findnonzero.cpp -> no funciona. He d'instal.lar OpenCV 2.4.4 mínim -> ja funciona amb OpenCV 3.0.1

8. contour.cpp -> detecta el contorn. Funciona molt bé.

9. diferencia1.cpp -> detecto correctament la diferència entre dues imatges.

$ pkg-config opencv --cflags --libs
-I/usr/include/opencv  -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_ts -lopencv_video -lopencv_videostab

he instal.lat OpenCV 3.0.1 a partir de

$ pkg-config --libs --cflags opencv
-I/usr/local/include/opencv -I/usr/local/include -L/usr/local/lib -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn -lopencv_dpm -lopencv_fuzzy -lopencv_line_descriptor -lopencv_optflow -lopencv_plot -lopencv_reg -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_rgbd -lopencv_surface_matching -lopencv_tracking -lopencv_da
tasets -lopencv_text -lopencv_face -lopencv_xfeatures2d -lopencv_shape -lopencv_video -lopencv_ximgproc -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_xobjdetect -lopencv_objdetect -lopencv_ml -lopencv_xphoto -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_photo -lopencv_imgproc -lopencv_core

Aplicatiu cercle perfecte, recta perfecta

La idea ve de lluny, s'ha de fer un petit aplicatiu que analitzi un cercle/recta, o conjunt de cercles/rectes, i que et doni una puntuació.

Del segon link obtenim el contours_poly[i], que és el polígon del contorn de cada cercle. El polígon és un vector de punts. Aleshores podem fer una fórmula en què comparem cada punt del vector amb el centre del cercle que hem obtingut. Ho fem per tots els valors del poligon, promitgem, i aleshores obtenim un valor que ens diu quant de cercle és el nostre dibuix d'un cercle.

En definitiva és trobar la desviació estàndar

En la regressió linial, tenim el coeficient de correlació r. r=1 vol dir molt bona correlació. r=0 vol dir molt dolenta.

Recta perfecte

Donada una sèrie de línies, determinem els contorns d'aquestes línies. Els contours_poly[i] és un vector dels punts. Donats una sèrie de punts (x,y), puc calcular la mitjana de les x i y, la desviació típica (o estàndar), i la covariança.

La correlació és r=covariancia/(desv_tip_x*desv_tip_y)

Si r=1, vol dir que és una recta perfecte.

desv_tip_x = sqrt(1/N * sumatori((xi - xm)^2) ), on xm és la mitjana
desv_tip_y = sqrt(1/N * sumatori((yi - ym)^2) ), on ym és la mitjana
covariancia = 1/N * sumatori ((xi-xm)*(yi-ym))

r = covariancia / (desv_tip_x*desv_tip_y)

Cercle perfecte

A partir del segon link obtinc el cercle que s'ajusta al meu cercle dibuixat. El meu cercle dibuixat és un contours_poly[i] (vector de punts). N'hi ha prou en calcular la distància d'aquests punts al centre, fer un sumatori i la mitjana, és a dir, una desviació típica.

S'ha de dividir per R per normalitzar, doncs poden haver-hi cercles més grans i d'altres més petits.

sqrt(1/N * (sumatori(di^2))) té dimensions de distància
ho hem de normalitzar dividint per R per tal de què no tingui dimensions.

di = (xi-x0)^2 + (yi-y0)^2

r = 1/R0 * sqrt(1/N * (sumatori(di^2)))

En aquest cas, per al cercle perfecte r=0.


creat per Joan Quintana Compte, desembre 2016

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
IES Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines