Faire de la reconnaissance d'un chat parmi un autre avec OpenCV
Sources
Le but est de nourrir chacun des chats en leur donnant leur ration de croquette journalière.
Pour ne pas que Chat1 (qui est un gros morfal) ne mange les croquettes de Chat2 (qui mange en plusieurs fois), on va apprendre à notre Raspberry a faire une reconnaissance faciale de chacun des chats.
Lorsque Chat1 s'approche, le matin, on lui donne la moitié de sa ration journalière, lorsqu'il s'approche le soir, on lui donne l'autre moitié.
Lorsque Chat2 s'approche, on lui donne une petite portion de sa ration journalière. On recommence tant qu'il lui reste des croquettes à manger pour la journée.
Nous allons utiliser le langage Python sur une Raspberry Pi munie d'une caméra. La librairie OpenCV ( Open Source Computer Vision ) permet de reconnaitre des formes dans un flux vidéo. Grace à des classifiers ( haarcascades ), il est possible de faire la différence entre un chat, un humain ou un objet.
Afin de distinguer Chat1 et Chat2, il est nécessaire d'apprendre à les reconnaitre. Pour cela nous allons prendre des photos et les stocker dans un répertoire. Un trie manuel sera nécessaire afin de définir celles qui représentent Chat1. On apprendra ensuite à notre algorithme à faire la distinction entre Chat1 et Chat2.
Télécharger la dernière version de Raspian en allant sur le site officiel :
https://www.raspberrypi.org/downloads/raspbian/
Dans notre cas, nous n'avons pas besoin de la version Desktop car nous utiliserons la Raspberry par une conection distante, une connection SSH. Nous avons donc besoin de la version allégée de Raspbian, la version " Lite "
Téléchargez et décompressez le fichier dans un répertoire temporaire, on obtient une image du système d'exploitation.
Le fichier au format img n'est pas copiable en tant que tel sur la carte SD, il faut utiliser un utilitaire comme par exemple Etcher (sous windows).
Une fois Etcher installé :
Le système d'exploitation est prêt, mais il faut encore configurer l'accès distant.
Par défaut, SSH est installé sur la Raspberry Pi, mais est désactivé pour des raisons de sécurité. La première chose à faire sera donc d’activer SSH sur votre Raspberry Pi.
Pour cela, il vous suffit de brancher la carte MicroSD de votre Raspberry Pi sur votre ordinateur, de vous rendre sur la carte, et de créer un fichier vide nommé ssh dans la partition boot.
Au prochain boot sur la carte SD, il sera possible de faire une connexion SSH en utilisant un client comme Putty (sous windows) par exemple.
Veillez à bien changer le mot de passe par défaut de l'utilisateur pi ("raspberry" par défaut) quand vous vous logez pour la première fois.
Voila, la carte SD est maintenant prête à être insérée dans la Raspberry.
La commande ifconfig vous permet de connaitre l'adresse IP que votre Raspberry vient d'avoir en se connectant sur votre réseau.
pi@raspberrypi:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet
192.168.0.102
netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::d9f:c7ba:c902:d0c prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:83:ec:c2 txqueuelen 1000 (Ethernet)
RX packets 284 bytes 39200 (38.2 KiB)
RX errors 0 dropped 10 overruns 0 frame 0
TX packets 110 bytes 16465 (16.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Nous allons ensuite configurer la Raspberry en lançant la commande : raspi-config
Changer le mot de passe par défaut (de l'utilisateur "pi") en choisissant :
1 - Change User Password
4 - Localisation Options
I1 - Change Locale (Supprimer : UK et cocher : fr_FR.UTF-8 UTF-8 )
5 - Interfacing options
P4 - SPI
7 - Advanced options
A1 - Expand Filesystem
Finish, Reboot = yes
J'ai remarqué que l'installation d'OpenCV en passant par l'utilitaire PIP de Python ne fonctionnait pas très bien avec une Raspberry Pi. Voici comment compiler OpenCV pour notre Raspberry Pi 4.
Nous allons configurer une Raspberry Pi 4 pour pouvoir compiler OpenCV 4.1.1, puis nous lancerons la compilation.
Finalement nous testerons que la bibliothèque OpenCV est bien installée pour Python3
Il se peut que l'EEPROM ne soit pas à jour juste après une installation de Raspbian sur une Raspberry Pi 4. Pour le vérifier, dans un terminal de commande, taper :
sudo rpi-eeprom-update -a
Si une mise à jour est nécessaire, elle se fera automatiquement.
Ne pas oublier de rebooter la Raspberry après la mise à jour.
sudo raspi-config
Et choisir :6 (Advanced options) > A1 (Expand Filesystem)
sudo apt-get update && sudo apt-get upgrade
Outils pour la compilation :
sudo apt-get install -y cmake gfortran libjpeg-dev libtiff-dev libgif-dev libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install -y libgtk2.0-dev libcanberra-gtk* libxvidcore-dev libx264-dev libgtk-3-dev libtbb2 libtbb-dev libdc1394-22-dev libv4l-dev libopenblas-dev libatlas-base-dev libblas-dev libjasper-dev liblapack-dev libhdf5-dev protobuf-compiler
Afin d'installer OpenCV, nous avons besoin de OpenCV et de opencv-contrib. Pour récupérer les version 4.5.0 de chacun à partir de leur dépôt officiel, taper les commandes :
cd ~
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.0.zip
unzip opencv.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.0.zip
unzip opencv_contrib.zip
mv opencv-4.5.0 opencv
mv opencv_contrib-4.5.0 opencv_contrib
rm opencv.zip opencv_contrib.zip
Vérification de la version de Python, la commande ...
python3 --version
... doit renvoyer quelque chose comme : Python 3.7.3
Nous pouvons ajouter le chemin de l'exécutable de python3.7 dans une variable d'environnement stockée dans le profil de l'utilisateur "pi" avec la commande :
echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3.7" >> ~/.bashrc
Rechargement du profile :
source ~/.bashrc
Installation de l'environnement virtuel :
sudo pip3 install virtualenv virtualenvwrapper
Création de l'environnement virtuel :
echo "export WORKON_HOME=$HOME/.virtualenvs" >> ~/.bashrc
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrcsource ~/.bashrc
mkvirtualenv cv450
Installation de Numpy (processeur numérique) dans l'environnement virtuel (bien faire attention de na pas faire l'installation en sudo):
pip3 install numpy
Pour sortir de l'environnement virtuel, il faut faire :
deactivate
Afin de faciliter la compilation, nous allons augmenter la taille du fichier de swap utilisé par le système. Pour cela :
sudo vi /etc/dphys-swapfile
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
# CONF_SWAPSIZE=100
CONF_SWAPSIZE=1024
Mise à jour du fichier de swap :
sudo /etc/init.d/dphys-swapfile stop
sudo /etc/init.d/dphys-swapfile start
Attention ! il faudra remettre le fichier de swap dans son état initial après la compilation d'OpenCV car un trop grand fichier de swap peut détruire rapidement les cartes SD.
Préparation de la compilation :
cd ~/opencv/
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
-D ENABLE_NEON=ON \ -D ENABLE_VFPV3=ON \
-D WITH_OPENMP=ON \ -D BUILD_TIFF=ON \
-D WITH_FFMPEG=ON \ -D WITH_TBB=ON \
-D BUILD_TBB=ON \ -D BUILD_TESTS=OFF \
-D WITH_EIGEN=OFF \
-D WITH_V4L=ON \ -D WITH_LIBV4L=ON \
-D WITH_VTK=OFF \ -D WITH_QT=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
-D BUILD_opencv_python3=TRUE \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=OFF ..
Compilation (C'est TRES long, il faut compter environ 1h40 sur une Raspberry Pi 4 (1500 MHz - 2 MB) ):
make -j4
Installation d'OpenCV :
sudo make install
sudo ldconfig
sudo apt-get update
On remet le fichier de swap comme avant la compilation :
sudo vi /etc/dphys-swapfile
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
CONF_SWAPSIZE=100
Mise à jour du fichier de swap :
sudo /etc/init.d/dphys-swapfile stop
sudo /etc/init.d/dphys-swapfile start
Vérification de l'installation de OpenCV avec la commande :
ls -l /usr/local/lib/python3.7/dist-packages/
... doit afficher un message du style :
-rw-r--r-- 1 root staff 1895772 Mar 20 20:00 cv2.so
Comme nous allons utiliser OpenCV dans un environnements virtuel Python (nommé cv450) , il nous faut construire un lien symbolique de la librairie OpenCV dans notre environnement :
cd ~/.virtualenvs/cv450/lib/python3.7/site-packages
ln -s /usr/local/lib/python3.7/dist-packages/cv2/python-3.7/cv2.cpython-37m-arm-linux-gnueabihf.so
On se met dans l'environnement virtuel prévu précédemment :
cd ~
mkvirtualenv cv450
Lancement de Python3 :
(cv450) pi@RPI-Camera:~ $ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44)[GCC 8.3.0] on linuxType "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.5.0'
>>> exit()
On a bien la version 4.5.0 installée pour python3 dans notre environnement virtuel cv2 !
Tout les fichiers ayant servi à la compilation ne sont plus nécessaire pour l'utilisation de OpenCV, on peut maintenant les supprimer.
Pour cela faire :
cd ~
sudo rm -rf ~/opencv
sudo rm -rf ~/opencv_contrib
sudo pip uninstall pil
sudo apt-get install -y libjpeg-dev zlib1g-dev libfreetype6-dev liblcms1-dev libopenjp2-7 libtiff5
En fait la librairie PIL s'appel pillow pour Raspbberry PI.
pip install pillow
Référence : Techcoil.com
OpenCV est disponible avec des fichiers XML de reconnaissances déjà calculées : des classifiers ou haarcascades . Il en existe un certain nombre disponible sur le repo officiel github d'OpenCV . Nous allons voir comment utiliser ces fichiers.
Nous verrons également comment faire des captures d'image avec OpenCV afin d'apprendre en machine-learning à notre programme à faire la distinction entre Chat1 et Chat2.
Comme nous voulons avoir le plus possible d'images de Chat1 et Chat2 afin d'apprendre à notre algorithme à les distinguer, voici un programme qui capture les images des chats passant devant l'objectif. Les images sont sauvées sur la Raspberry dans un répertoire.
Le fichier catPicturesCapture.p y est disponible sur mon dépôt Gihub.
Une fois le fichier téléchargé, il ne reste plus qu'à l'executer dans notre environnement virtuel Python.
Chargement de l'environnent :
mkvirtualenv cv450
Exécution du programme
python3 catPicturesCapture.py
Les images vont être sauvegardées au fur et à mesure dans le répertoire "pictures"
Nous allons utiliser les images enregistrées précédemment pour apprendre à faire la distinction entre Chat1 et Chat2.
Pour cela il est nécessaire de faire 2 répertoires pour y trier manuellement les photos.
A finir.
A faire
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project
Ceci est la vue non overridée de l'objet project en mode listitem
Code à rajouter dans l'override.ini.append.php :
[line_project] Source=node/view/listitem.tpl MatchFile=listitem/project.tpl Subdir=templates Match[class_identifier]=project