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

10. SimpleGrab_detectarvermell.cpp -> capturo una imatge i detecto el vermell. També puc detectar el verd i el blau. En canvi, no em detecta el groc.

11. tracking:

Buscant la manera de detectar el groc, trobo aquest tutorial, que està molt bé, i que mostra el moment d'un objecte, és a dir, el centre de gravetat:

12. SimpleGrab_detectargroc1.cpp -> detecto el groc. Genero la imatge amb punts blancs de les posicions del groc, i mostro els punts per pantalla.

13. SimpleGrab_detectargroc2.cpp -> detecto el groc. Calculo la posició (moment) de l'objecte groc.

14. Hough-transformation (carpeta hough-master). Serveix per detectar rectes.

C++ i Rasberry Pi Camera Module (RaspiCam)

Disposo de la càmera NoIR (infrarrojos). La manera com accedim a la càmera RaspiCam és diferent de les webcams USB. D'entrada, el dispositiu no apareix a /dev/video0, el dispositiu funciona de forma diferent.

I el codi que tinc fins ara de OpenCV que funciona amb webcams USB ara no funciona. El que volem fer ara és un exemple C++ per capturar una imatge. Però de fet, aquest exemple no entraria dins de OpenCV.

Segueixo l'article.

$ raspivid -t 10000

és una aplicació de consola que serveix per enviar el streaming de video. Efectivament, a la tele puc veure el video a temps real, encara que llenci l'aplicatiu des del portàtil via SSH.

$ wget https://github.com/raspberrypi/userland/archive/master.zip
$ sudo mv master.zip /opt/vc
$ sudo unzip master.zip

i tot el contingut del zip va a parar a la carpeta userland-master

Change to the /opt/vc/userland-master folder, then build it with the following commands:

$ cd /opt/vc/userland-master
$ sudo mkdir build
$ cd build
$ sudo cmake -DCMAKE_BUILD_TYPE=Release ..
$ sudo make
$ sudo make install

Test everything worked by running raspivid again. You may see some different messages pop up (I got some harmless errors probably due to the build being so recent), but the crucial thing is that you still get the video feed on screen.


The api and samples can all be downloaded here:

Extract them into a folder in your home directory called 'picamdemo' (ho fico a /home/pi/recreativa_dards/proves_opencv_cpp). You should have a few cpp files in there, plus a make file and some shaders.

$ cd /home/pi/recreativa_dards/proves_opencv_cpp
$ mkdir picamdemo
$ cd picamdemo
$ wget http://www.cheerfulprogrammer.com/downloads/picamtutorial/picamdemo.zip
$ unzip picamdemo.zip

Change to the folder and build the application with:

$ cmake .
$ make

Explicació i adaptació: SimpleGrab_raspicam.cpp

(TBD) Then run the sample with

$ ./picamdemo

Ha compilat bé i funciona correctament.

I aleshores ve l'eplicació de tot el codi, i jo podré fer la meva adaptació del SimpleGrab.cpp a SimpleGrab_raspicam.cpp.

Ara bé, abans de continuar, s'ha de dir que de fet hi ha una solució més senzilla. Jo des de C++ puc obtenir una imatge fent una crida del sistema que em permeti capturar un frame. Per exemple:

system(raspistill -o image.png)

i un cop obtinguda la imatge, de fet ja puc processar-la amb OpenCV. De fet, aquesta seria la manera més senzilla.

NOTA. Totes aquestes proves les estic fent perquè necessito OpenCV per la recreativa de dards.

Aplicatiu cercle perfecte, recta perfecta (todo)

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