Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

My personal pipeline to species identification on camera trap pix using deep learning, detection/classification with MegaDetector and RetinaNet

NotificationsYou must be signed in to change notification settings

oliviergimenez/DLcamtrap

Repository files navigation

On va utiliser les méthodes de deep learning ou aprentissage profond pour faire l'identification automatique des espèces sur les images collectées via piégeages photographiques. Pour une introduction au deep learning (niveau lycée, d'après l'auteur), voirici. Pour une introduction avec R au deep learning qui permet aussi de comprendre les réseaux de neurones, voir. Je conseilleça pour une veille sur deep learning et piégeage photographique.

Passons à nos affaires. Comme exemple, j'ai assemblé un ensemble de 46 photos annotées à la main téléchargeableici. Attention, bien s'assurer qu'il n'y a pas d'espace dans le nom des fichiers, et que les étiquettes (tags) ne comportent pas d'erreurs (sous Mac, on peut utiliser Photo pour modifier ces tags). L'information sur ce qui a été détecté dans chaque photo apparait dans les métadonnées des photos. Sous Mac, il suffit de faire un Cmd + I pour avoir cette info. Les photos sont stockées dans un dossierpix/ dont le chemin absolu est/Users/oliviergimenez/Desktop/.

On souhaite utiliser un modèle déjà existant, et évalué les performances de ce modèle à reconnaître les espèces qui sont sur les 46 photos de mon échantillon, et en particulier lynx, chamois et chevreuils. Ce modèle a été entrainé à classifier les espèces sur un échantillon des photos du Jura annotées par Anna Chaine.

Pour évaluer ces performances, on va se concentrer sur :

  • lesvrais positifs ou TP : le modèle prédit que l'espèce d'intérêt est présente sur la photo quand celle-ci est effectivement présente sur cette photo ;
  • lesfaux positifs ou FP : le modèle prédit la présence de l'espèce d'intérêt, mais celle-ci n'est en fait pas présente sur la photo ;
  • lesfaux négatifs ou FN : le modèle prédit que l'espèce d'intérêt n'est pas présente sur la photo alors que celle-ci est bien présente ; on pourra séparer les FN en FN_void Fsi l'espèce n'a pas été détectée, et FN_false si l'espèce a été détectée mais mal classifiée.

Ci-dessous on trouvera les différentes étapes du pipeline. C'est un mix de scriptsR etPython. On applique une procédure en 2 étapes, détection puis classification. La même idée est appliquée par d'autres pour des projets (et avec des moyens) beaucoup plus ambitieux, voir par exemplecelui-ci.

Le gros du boulot (en particulier l'entrainement du modèle) a été fait par Gaspard Dussert en stage en 2019 avec Vincent Miele. Plus de détailssur le site dédié du GdR EcoStat.

Etape 0. Entrainement.

Cette étape est donc déjà faite, ça tombe bien car les temps de calculs sont conséquents même avec des moyens performantes (GPU plutôt que CPU). On décrit brièvement les différentes étapes pour en arriver au modèle entrainé (voirce tuto pour plus de détail sur l'entrainement d'un modèle). Au total, on a utilisé 8800 photos pour le training, divisées en 7992 pour l'entrainement/validation et 888 pour les tests.

a. Coup d'essai.

On a estimé un modèle RetinaNet (voir la publication originaleici et une introduction) avec 9 classes jugées intéressantes et avec suffisamment d'images pour le training. Il s'agit de blaireaux, chamois, chat forestier, chevreuil, lièvre, lynx, sanglier, renard et cerf. Le tout a pris 24h sur avec GPU. Des tests montrent qu'on s'en sort très bien pour trouver ces 9 espèces quand elles sont présentes, mais sur des images qui contiennent des objets de classes qu'on a pas intégrées dans le modèle (e.g., humain, véhicules, vaches), le modèle détecte trop de faux positifs.

b. C'est mieux mais pas encore ça.

La solution envisagée a été d'ajouter des exemples négatifs dans le training, c'est à dire des images où il n'y a pas d'annotations (des vrais négatifs), avec des photos d'humains, de véhicules, de chiens et de vaches (mais sans les inclure en tant que classes du modèle, juste du background varié). A noter aussi qu'on n'a pas ajouté des exemples négatifs de toutes les classes : on n'a pas mis les fouines, martres, écureuil, oiseaux, lapins et toutes les autres classes avec peu de photos, en espérant que le modèle puisse s'en sortir sans apprendre une classe par animal de la planète. On obtient ainsi beaucoup moins de faux négatifs sur les classes qu'on a ajouté sans annotations. En revanche, il y a toujours des faux positifs sur les espèces qu'on n'a pas mis dans les exemples négatifs et qui ressemblent à des espèces du modèle : lapin avec lièvre, chat domestique avec chat forestier, fouine ou martre avec renard et blaireaux. Avec des espèces qui ne se ressemblent pas comme oiseaux et écureuils, il n'y a pas de faux positifs mais il y aussi peu d'images pour le confirmer.

c. Voilàààààà.

La dernière étape a donc été d'ajouter dans le background les classes avec peu de photos, entre autres fouine, martre, vache, et léporidés. Ce faisant, on a grandement diminué le nombre de faux positifs du modèle tout en conservant un nombre de faux négatifs semblable.

Etape 1. Redimensionnement.

Passons maintenant au coeur de l'exercice, la classification automatique des 46 photos. On redimensionne d'abord les images. Pour ce faire, on applique ces quelques lignes de code dansR. On utilise le package magical qui appelle l'excellent petit logicielimagemagick. Les photos contenues dans le répertoire/Users/oliviergimenez/Desktop/pix sont redimensionnées en 1024x1024 dans le répertoire/Users/oliviergimenez/Desktop/pix_resized. Les chemins sont à modifier selon les goûts. Le nom de chaque photo est affublé d'un resized pour les différentier des photos originales. Le résultat est téléchargeableici.

# load package to make R talk to imagemagicklibrary(magick)# where the pix to resize arefolder <- "/Users/oliviergimenez/Desktop/pix/"# where the pix, once resized, should be storeddest_folder <- "/Users/oliviergimenez/Desktop/pix_resized/"# create directory to store resized pixdir.create(dest_folder)# list all files in the directory with pixfile_list <- list.files(path = folder)# resize them all !for (i in 1:length(file_list)){pix <- image_read(paste0(folder,file_list[i]))pixresized <- image_resize(pix, '1024x1024')namewoextension <- strsplit(file_list[i], "\\.JPG")[[1]]image_write(pixresized, paste0(dest_folder,namewoextension,'resized.JPG'))}

Si l'on inspecte les photos redimensionnées, on s'aperçoit que leur poids a été divisé par 5-10 en gros, d'1-1.5Mo en moyenne, à 200Ko en moyenne.

Etape 2. Détection.

On passe maintenant à la détection des objets dans les photos. Pour ce faire, on utiliseMegaDetector pour se faciliter la vie. Cet algorithme va détecter les objets sur les photos et leur associer un cadre, une boîte.

Pour ce faire, il faut d'abord télécharger depuisCameraTraps le fichier zippé, le dézipper, puis changer le nom du répertoire enCameraTraps. Puis, depuis un Terminal, se mettre dans le répertoireCameraTraps/ et suivreles instructions d'installation. En gros cela consiste à taper les deux lignes de commandeconda env create --file environment.ymletconda env create --file environment-detector.yml.Attention, si on n'a pas de GPU, il faut modifier le fichier dans le fichier environment-detector.yml en commentant la ligne

tensorflow-gpu>=1.9.0, <1.15.0

en

# tensorflow-gpu>=1.9.0, <1.15.0

et ajouter la ligne

tensorflow==1.14

Il se peut qu'il faille installer des modules, dans ce cas, utiliserpip install dans le Terminal.

Ensuite, dans le Terminal, faire

conda init

puis

conda activate cameratraps

Enfin, on met le cheminPython au répertoire racine :

export PYTHONPATH=/Users/oliviergimenez/Desktop/CameraTraps

Avant de se lancer, il faut récupérer le modèle megadetector_v3.pb pour la détectionici.

On est prêt à utiliser MegaDetector. Trois options s'offrent à nous.

a. On traite une seule photo.

On prend par exemple '1.3D(145)resized.JPG', et on lui met un cadre là où un objet est détecté. Taper dans le Terminal :

python /Users/oliviergimenez/Desktop/CameraTraps/detection/run_tf_detector.py /Users/oliviergimenez/Desktop/megadetector_v3.pb --image_file /Users/oliviergimenez/Desktop/pix_resized/1.3D\(145\)resized.JPG

Le traitement prend quelques secondes. Un cadre a été ajouté sur la photo traitée, ainsi que la catégorie de l'objet détecté et un degré de confiance :

detections

Ne pas oublier de supprimer la photo avec détection si l'on passe par cette étape, en l'occurrence1.3d(145)resized_detections.jpg, sinon elle serait traitée dans les étapes suivantes.

b. On traite toutes les photos du dossier pix_resized.

Il suffit de taper en prenant garder de spécifier les bons chemins :

python /Users/oliviergimenez/Desktop/CameraTraps/detection/run_tf_detector.py /Users/oliviergimenez/Desktop/megadetector_v3.pb --image_dir /Users/oliviergimenez/Desktop/pix_resized/

Les photos avec cadre sont ajoutées dans le même répertoire pix_resized, leur nom est modifié avec l'ajout de 'detections' pour signifier qu'elles ont été traitées. Les photos avec détections peuvent être récupéréesici. Si pour les animaux, le taux de succès est de 100%, pour les véhicules, il est de 0%, et pour les humains ce taux est élevé, mais pas de 100%. Pour les photos vides, pas de faux positifs, i.e. pas de cadre là où pas d'objets. Vu notre objectif, celui de travailler sur les interactions entre lynx, chamois, et chevreuils, le fait de détecter tous les animaux, et de ne pas mettre des cadres là où il n'y a pas d'animaux, nous semble prometteur. On continue.

c. On récupère l'info dans un fichier.

On ne touche pas aux photos, et on crée plutôt un fichier json dans lequel on récupère les coordonnées des cadres, ainsi que les catégories des objets détectés. Cette étape est indispensable pour passer à la suite.

python /Users/oliviergimenez/Desktop/CameraTraps/detection/run_tf_detector_batch.py /Users/oliviergimenez/Desktop/megadetector_v3.pb /Users/oliviergimenez/Desktop/pix_resized/ /Users/oliviergimenez/Desktop/box_pix.json

Attention, avant de lancer la commande au-dessus, transférer les 46 photos avec objets encadrés obtenus au point b. dans un autre répertoire, par exemple pix_resized_detections, sinon l'étape c. portera sur les 92 photos.

On peut ouvrir le fichier json ainsi créé avec un éditeur de texte. Ce fichier est téléchargeableici. On peut voir des blocs, chaque bloc correspondant au traitement d'une image. Par exemple :

   "file": "/Users/oliviergimenez/Desktop/pix_resized/I__00001(7)resized.JPG",   "max_detection_conf": 0.997,   "detections": [    {     "category": "2",     "conf": 0.997,     "bbox": [      0.3137,      0,      0.4563,      0.8849     ]    }   ]  },

On a le nom de l'image, la catégorie de l'objet détecté (0 = vide, 1 = animal, 2 = personne, 3 = groupe, 4 = véhicule), le degré de confiance (conf) ainsi que les caractéristiques de la boîte associée à l'objet (xmin, ymin, width, height) où l'origine de l'image est en haut à gauche à (xmin, ymin) (les coordonnées sont en coordonnées absolues). Il nous faudra la boîte sous la forme (ymin, xmin, ymax, xmax) pour plus tard ; si detection = (detection[0], detection[1], detection[2], detection[3]) = (xmin, ymin, width, height) est le format json, alors la correspondance est xmin = detection[0], ymin = detection[1], xmax = detection[0] + detection[2] et ymax = detection[1] + detection[3]. On arrangera ce fichier à l'étape d'après pour en extraire l'information pertinente.

Ne pas oublier de quitter l'environnementcameratraps en faisant :

conda deactivate

Etape 3. Métadonnées test.

Avant de passer à la classification des objet détectés, il nous faut créer un fichiertest.csv qui contient le nom du fichier photo, les coordonnées du cadre de l'objet détecté (données parMegaDetector à l'étape 2) et le nom de l'espèce détectée (tag manuel). Pour ce faire, il faut d'abord récupérer les tags manuels dans les métadonnées des photos, puis récupérer les coordonnées des boîtes créées à l'étape 2 de détection, assembler ces deux fichiers, puis on stocke le tout dans un fichier csv.

# load package to manipulate datalibrary(tidyverse)# load package to extract metadata from pixlibrary(exifr)# load package to process json fileslibrary(jsonlite)#-- first, get manual tags# where the resized pix arepix_folder <- "/Users/oliviergimenez/Desktop/pix_resized/"# list all files in the directory with pixfile_list <- list.files(pix_folder, recursive=TRUE, pattern = "*.JPG", full.names = TRUE)# get metadatamanual_tags <- read_exif(file_list) %>%  as_tibble() %>%  select(FileName, Keywords) %>%  unnest(Keywords)# displaymanual_tags# 46 pix manual_tags %>% count(FileName, sort = TRUE)#-- second, get box coordinates# where the json file isjson_folder <- "/Users/oliviergimenez/Desktop/"# read in the json filepixjson <- fromJSON(paste0(json_folder,'box_pix.json'), flatten = TRUE)# what structure?str(pixjson)# namesnames(pixjson)# categories are animal, human and vehiculespixjson$detection_categories# get pix onlypix <- pixjson$imagesnames(pix)# unlist detections and bboxbox_coord <- pix %>%   as_tibble() %>%  unnest(detections, keep_empty = TRUE) %>%  unnest_wider(bbox) %>%  rename(xmin = '...1',         ymin = '...2',         width = '...3',         height = '...4',         name = file,         max_det_conf = max_detection_conf,         confidence = conf) %>%  mutate(xmin = xmin,         xmax = xmin + width,         ymin = ymin,         ymax = ymin + height,         category = as.numeric(category)) %>%  select(name, category, max_det_conf, confidence, xmin, xmax, ymin, ymax) %>%  mutate(category = if_else(is.na(category), 0, category), # pix empty         confidence = if_else(is.na(confidence), 1, confidence))# displaybox_coord# several pix get more than one box, let's take those with max confidence in detectionbox_coord <- box_coord %>%   group_by(name) %>%  arrange(desc(confidence)) %>%   slice(1) %>%   ungroup()#-- third, join two files and build test.csvbox_coord %>%   rename(FileName = name) %>%  mutate(FileName = str_remove(FileName, '/Users/oliviergimenez/Desktop/pix_resized/')) %>%  left_join(manual_tags, by = 'FileName') %>%  mutate(FileName = paste0('/Users/oliviergimenez/Desktop/pix_resized/',FileName)) %>%  select(FileName, xmin, ymin, xmax, ymax, Keywords) %>%  filter(!is.na(xmin)) %>% # select only pix with a box  mutate(xmin = floor(1024 * xmin),         xmax = floor(1024 * xmax),         ymin = floor(1024 * ymin),         ymax = floor(1024 * ymax)) %>%  filter(! Keywords %in% c('cavalier','vehicule','humain','chien','vide','oiseaux','chat')) %>%  write_csv(paste0(json_folder,'test.csv'),             col_names = FALSE)

Le fichiertest.csv ainsi créé peut être récupéré. A noter qu'on a supprimé de ce fichier toutes les photos dans lesquelles aucun objet n'a été détecté (pas de boîte) et celles qui ne correspondent pas à une catégorie entrainée.

Etape 4. Classification.

Pour classifier nos photos avec le modèle entrainé sur les photos du Jura taggées par Anna Chaine, on suit les étapes donnéesici. Le modèle déjà entrainé est téléchargeableici, son petit nom estresnet50_csv_10.h5.

Il nous faut le fichierclass.csv qui contient les espèces sur lesquelles on a entrainé l'algorithme. On a déjà le fichiertest.csv créé à l'étape précédente.

Les étapes sont les suivantes pour la classification sont les suivantes :

  • On téléchargekeras-retinanetici, on dézippe et renomme le répertoirekeras-retinanet
  • On va dans le dossier keras-retinanet puis on fait :
pip install numpy --user

et

pip install . --user

On peut vérifier le fichier des annotations qu'on a créé à l'étape précédente. Se replacer dans le répertoire où se trouvent les fichierstest.csv,class.csv et le modèle entrainé, et faire :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/debug.py --annotations csv test.csv class.csv

Si on obtient ModuleNotFoundError: No module named 'keras_retinanet.utils.compute_overlap', on peut appliquer la commande suivante pour régler le problème dans le répertoire où se trouve setup.py :

cd keras-retinanetpython setup.py build_ext --inplace

On recommence :

cd ..python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/debug.py --annotations csv test.csv class.csv

On fait la classification sur les photos qui ont déjà le cadre de la détection :

/Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/evaluate.py --convert-model --save-path pix_pred/ --score-threshold 0.5 csv test.csv class.csv resnet50_csv_10.h5

On peut voir les photos classifiées dans le répertoirepix_pred/ avec le cadre en vert de l'étape détection parMegaDetector (qui est systématiquement trop bas, c'est un bug dans mon programmeR au-dessus que je suis en train de corriger) et celui en bleu de la classification parRetinaNet. Les photos peuvent être téléchargéesici.

On peut faire le même exercice, mais en ne supprimant aucune photo, en ne gardant que le tag manuel, et en voyant ce queRetinaNet donne. Dans le scriptR précédent, modifier la dernière partie pour avoir :

box_coord %>%   rename(FileName = name) %>%  mutate(FileName = str_remove(FileName, '/Users/oliviergimenez/Desktop/pix_resized/')) %>%  left_join(manual_tags, by = 'FileName') %>%  mutate(FileName = paste0('/Users/oliviergimenez/Desktop/pix_resized/',FileName)) %>%  mutate(colxmin = NA,         colymin = NA,         colxmax = NA,         colymax = NA,         colkeywords = NA) %>%  select(FileName, colxmin, colymin, colxmax, colymax, colkeywords) %>%  write_csv(paste0(json_folder,'test2.csv'),             col_names = FALSE,            na = '')

Le fichier test2.csv estici. Puis dans le Terminal, faire :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/evaluate.py --convert-model --save-path pix_pred2/ --score-threshold 0.5 csv test2.csv class.csv resnet50_csv_10.h5

Les résultats sont téléchargeables.

Un échantillon des photo avec le cadre, l'espèce prédite en haut à gauche du cadre et la confiance :

Avec qqs dizaines de photos, il est relativement facile d'évaluer les performances (étape suivante) de la classification. Maintenant si on a beaucoup de photos, on aimerait récupérer l'information brute. Pour afficher à l'écran (dans le Terminal) le nom de la photo, l'espèce détectée, la précision, et les coordonnées de la boîte, on utilise un scriptPythondetect2txt.py écrit par Vincent Miele, et téléchargeable viace lien. J'ai placé ce script dans le répertoire où se trouveevaluate.py à savoirkeras-retinanet/keras_retinanet/bin/. Pour utiliser ce script, il faut l'éditer avec un éditeur texte par exemple, et modifier les 3 lignes suivantes :

model_path = "retinanet_tutorial_best_weights.h5" # model file (must be based on RESNET50)test_dir = "test" # test directory with the target imagesclassfile = "class.csv" # list of class labels

pour préciser le nom de notre modèle entrainé, le répertoire avec les images à classifier et le fichier avec les catégories, soit :

model_path = "resnet50_csv_10.h5" # model file (must be based on RESNET50)test_dir = "pix_resized" # test directory with the target imagesclassfile = "class.csv" # list of class labels

Alors, dans le Terminal, on utilise une ligne de commandes similaires à celles utilisées précédemment :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/detect2txt.py

Les résultats s'affichent à l'écran, avec le nom de fichier, l'espèce identifiée, la confiance, et les coordonnées du cadre. Plus pratique, on peut utiliser la redirection dans un fichier texte :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/detect2txt.py >> classif_pix.txt

avec le fichier ainsi créé téléchargeableici.

Etape 5. Evaluation.

Pour évaluer la qualité de la classification, on compare les tags manuels au catégories prédites par l'algorithme. On fait ça dansR :

# read in classificationsclassif <- read_tsv('/Users/oliviergimenez/Desktop/classif_pix.txt', col_names = FALSE) %>%  mutate(X1 = str_replace(X1, 'chat forestier', 'chat_forestier')) %>%  filter(!str_detect(X1, 'tracking')) %>%  separate(X1,            into = c("name","species","confidence","x","y","z","t"),            sep = '\\s') %>%  mutate(species = str_replace(species, 'chat_forestier', 'chat forestier')) %>%  mutate(x = str_remove(x,'\\['),         x = str_remove(x,','),         y = str_remove(y,','),         z = str_remove(z,','),         t = str_remove(t,'\\]'),         t = str_remove(t,','),         x = as.numeric(x),         y = as.numeric(y),         z = as.numeric(z),         t = as.numeric(t)) %>%  rename(FileName = name) %>%  select(FileName, species, confidence, x, y , z, t) %>%  mutate(FileName = str_remove(FileName, 'pix_resized/'))print(classif, n = Inf)# comparisonmanual_tags %>% left_join(classif) %>% rename(ground_truth = Keywords, prediction = species) %>% print(n=Inf)Joining, by = "FileName"# A tibble: 51 x 8   FileName                                                                       ground_truth   prediction     confidence     x     y     z     t   <chr>                                                                          <chr>          <chr>          <chr>      <dbl> <dbl> <dbl> <dbl> 1 1.3D(145)resized.JPG                                                           chamois        chamois        0.99999046    96   190   833   638 2 1.3D(146)resized.JPG                                                           chamois        chamois        0.99999255     0   343   668   744 3 1.3D(189)resized.JPG                                                           chamois        chamois        0.99998736   200   122   849   658 4 1.3D(208)!!ATTENTION2017AULIEUDE2016!!resized.JPG                              cerf           cerf           0.9998793      6     0   973   576 5 Cdy00002(2)resized.JPG                                                         cavalier       NA             NA            NA    NA    NA    NA 6 Cdy00004(4)resized.JPG                                                         renard         renard         0.9731693    523   354   726   475 7 Cdy00005(4)resized.JPG                                                         chevreuil      chevreuil      0.9998088     64   263   576   583 8 Cdy00005(5)resized.JPG                                                         vehicule       NA             NA            NA    NA    NA    NA 9 Cdy00007(5)resized.JPG                                                         chat forestier chat forestier 0.9999943    402   325   636   48810 Cdy00008(5)resized.JPG                                                         vehicule       NA             NA            NA    NA    NA    NA11 Cdy00008resized.JPG                                                            chevreuil      chamois        0.9989721    508   207   614   36412 Cdy00008resized.JPG                                                            chevreuil      chevreuil      0.8156294    508   207   614   36413 Cdy00011(2)resized.JPG                                                         chevreuil      chamois        0.99987197   359   268   473   49214 Cdy00011(7)resized.JPG                                                         vehicule       NA             NA            NA    NA    NA    NA15 Cdy00013(5)resized.JPG                                                         vehicule       NA             NA            NA    NA    NA    NA16 Cdy00020resized.JPG                                                            renard         renard         1.0          666   397  1023   55817 FDC01_point_15-4a79b79d.2_corlier_montlier_2018_7_23_flanc_droit(3)resized.JPG lynx           lynx           0.9999405    705   429   923   56418 FDC01_point_36.2_evosges_le_col_2017_09_10_flanc_droitresized.JPG              lynx           lynx           0.99999857     0   318   310   56519 FDC01_point_36.2_evosges_le_col_2017_09_29_cuisse_gaucheresized.JPG            lynx           lynx           0.99994063     0   330   336   65220 FDC01_point_36.2_evosges_le_col_2017_10_10_flanc_droitresized.JPG              lynx           lynx           0.99994177   264   346   957   75521 I__00001(7)resized.JPG                                                         humain         NA             NA            NA    NA    NA    NA22 I__00002(7)resized.JPG                                                         vide           NA             NA            NA    NA    NA    NA23 I__00003(8)resized.JPG                                                         vide           NA             NA            NA    NA    NA    NA24 I__00007(8)resized.JPG                                                         renard         renard         0.9997709      1   392   527   69225 I__00009(8)resized.JPG                                                         sangliers      NA             NA            NA    NA    NA    NA26 I__0001(10)resized.JPG                                                         chien          NA             NA            NA    NA    NA    NA27 I__00010(8)resized.JPG                                                         sangliers      sangliers      0.8085136     11   244  1003   76228 I__00012(6)resized.JPG                                                         vide           NA             NA            NA    NA    NA    NA29 I__00012resized.JPG                                                            sangliers      sangliers      0.9999906    423     1  1018   47730 I__00015(3)-8907af1cresized.JPG                                                vide           NA             NA            NA    NA    NA    NA31 I__00015resized.JPG                                                            chevreuil      chevreuil      0.9947576    674   184   933   44732 I__00015resized.JPG                                                            chevreuil      chamois        0.8672855    694   186   948   44833 I__00016(6)resized.JPG                                                         vide           NA             NA            NA    NA    NA    NA34 I__00016resized.JPG                                                            vide           NA             NA            NA    NA    NA    NA35 I__00017(7)resized.JPG                                                         humain         NA             NA            NA    NA    NA    NA36 I__00020(6)resized.JPG                                                         chevreuil      chevreuil      0.9999998    208   128   863   71737 I__00021resized.JPG                                                            blaireaux      blaireaux      0.9999975    372   339   581   43438 I__00022(7)resized.JPG                                                         chien          NA             NA            NA    NA    NA    NA39 I__00023(7)resized.JPG                                                         chat           chat forestier 0.77948236   739   497  1022   75640 I__00024(8)resized.JPG                                                         chat           renard         0.96120846   546   387  1022   75641 I__00024(8)resized.JPG                                                         chat           chamois        0.7607192    555   382  1022   75542 I__00025(10)resized.JPG                                                        chevreuil      chevreuil      0.9999732    282   217  1020   75943 I__00026(11)resized.JPG                                                        sangliers      sangliers      0.9359536    473   303  1022   76244 I__00028resized.JPG                                                            lievre         lievre         0.990306     732   300  1022   62245 I__00028resized.JPG                                                            lievre         lynx           0.86009955   734   300  1022   62346 I__00033(6)resized.JPG                                                         oiseaux        NA             NA            NA    NA    NA    NA47 I__00033(9)resized.JPG                                                         humain         NA             NA            NA    NA    NA    NA48 I__00049(6)resized.JPG                                                         chat forestier lievre         0.9782964    145   355   508   68949 I__00049(6)resized.JPG                                                         chat forestier chat forestier 0.56414235   143   353   509   69050 I__00051(10)resized.JPG                                                        lievre         lievre         0.99998236   281   438   664   72551 I__00060(10)resized.JPG                                                        humain         NA             NA            NA    NA    NA    NA

Sur notre exemple, avec peu de photos, on peut regarder ce qui se passe. Pour les 4 premières photos, la prédiction coincide avec la vérité avec une grande confiance. Sur la photo 5, on a un cavalier, et cette photo a été écartée à l'étape de la détection puisque les coordonnées sont manquantes. Idem pour toutes les photos avec véhicules, humain, chien, oiseaux ou encore les photos vides. Très bien. La photo 11-12 montre qu'on confond chevreuil et chamois (c'est bien le même cadre, il suffit de regarder les coordonnées). Le message est encore plus clair avec la photo 13. Les photos 17 à 20 montrent que le lynx est bien classifié. La photo 40-41 montre qu'on confond le chat avec renard ou chamois, mais plutôt renard à en jugerpar le degré de confiance. Sur la photo 44-45, on hésite pour le lièvre entre lièvre et lynx, mais quand on regarde le degré de confiance, on penche pour le lièvre. Dans la photo 48-49 on hésite aussi pour le chat forestier entre lièvre et chat forestier, et on se plante si on regarde le degré de confiance puisqu'on prendrait le lièvre.

On peut formaliser ces calculs d'erreur en distinguant FN, TP et FP. On rappelle que :

  • un faux négatif FN correspond à une espèce présente sur la photo qui n'est pas détectée ; on peut redécouper en Void si animal pas détecté et False si animal détecté mais mal classifié ;
  • un vrai positif TP correspond à une espèce présente sur la photo qui est détectée et bien classifiée ;
  • un faux positif FP correspond à une espèce qui n'est pas sur une photo mais qui y est détectée.

Pas facile de faire ces calculs à la main quand on a beaucoup de photos. Heureusement, Gaspard Dussert fournit un scriptdetect.py téléchargeableici qui permet de faire ces calculs. Je mets ce script dans/Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/ et il ne manque plus qu'à modifier deux lignes du script.

Au début, modifier la ligne

model_path = "snapshots_all/resnet50_csv_10.h5"

en

model_path = "/Users/oliviergimenez/Desktop/resnet50_csv_10.h5"

pour dire où se trouve le modèle entrainé (chemin absolu, comme d'habitude).

A la fin du script, modifier la ligne

comp_exif("/beegfs/data/gdussert/projects/olivier_pipeline/all_classes/test/")

en

comp_exif("/Users/oliviergimenez/Desktop/pix_resized/")

pour dire où sont les photos à classifier.

Enfin, dans le Terminal, faire :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/detect.py

Sur le Terminal, on a aussi le détail comme suit :

          species  TP  FP  FN_false  FN_void0       blaireaux   1   0         0        01         chamois   3   2         0        02  chat forestier   1   1         1        03       chevreuil   4   0         2        04          lièvre   0   3         0        05            lynx   4   0         0        06          renard   3   1         0        07       sangliers   3   0         0        18            cerf   1   0         0        0Images source de FP par classe :chevreuil 2lievre 2chat forestier 1chat 2Nombre total d'image par classe:humain 4renard 3chat forestier 2chevreuil 6cavalier 1vehicule 4chamois 3cerf 1oiseaux 1vide 6lynx 4chien 2lievre 2sangliers 4chat 2blaireaux 1

On peut, comme précédemment, mettre tout ça dans un fichier texte via une redirection :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/detect.py >> perf.txt

On peut jeter un coup d'oeil au résultat.

On note que sur le lynx, on est tout bon. Sur chevreuil on a qqs faux négatifs, et sur chamois qqs faux positifs.

Si l'on n'est pas intéressé par le détail dans les faux négatifs, on peut utiliser un autre scriptPython,detect2.py, téléchargeableici, et qui permet de mettre sur les photos le cadre avec l'espèce vérité et le cadre avec l'espèce prédite, et de créer trois nouveaux répertoires qui contiennent les photos classées en TP, FN et FP, permettant ainsi d'aller regarder en détail les situations qui génèrent les faux négatifs et faux positifs. Ces répertoires se trouvent dans le répertoire qui contient les photos analysées, danspix_resized/.

Avant de lancer le script, il faut modifier les deux mêmes lignes que pour le scriptdetect.py. Puis on le lance via :

python /Users/oliviergimenez/Desktop/keras-retinanet/keras_retinanet/bin/detect2.py >> perf2.txt

On peut jeter un coup d'oeil àperf2.txt téléchargeableici :

          species  TP  FP  FN0       blaireaux   1   0   01         chamois   3   2   02  chat forestier   1   1   13       chevreuil   4   0   24          lièvre   0   3   05            lynx   4   0   06          renard   3   1   07       sangliers   4   0   08            cerf   1   0   0Images source de FP par classe :chevreuil 2lievre 2chat forestier 1chat 2Nombre total d'image par classe:humain 4renard 3chat forestier 2chevreuil 6cavalier 1vehicule 4chamois 3cerf 1oiseaux 1vide 6lynx 4chien 2lievre 2sangliers 4chat 2blaireaux 1

Au passage, ces scriptsdetect.py etdetect2.py font en un coup les étapes 2, 3 et 4.

La suite ?

  • Vérifier que l'algo déjà entrainé n'est pas à côté de la plaque dans l'Ain en comparant tous les tags manuels entrés par les collègues de l'OFB à la classification prédite par l'algo. Si on n'est pas trop dans les choux, alors faire le tagging automatique pour toutes les photos de l'Ain pour que Maëlis puisse se servir de ces données pour le stage.

  • A moyen terme, refaire l'entrainement du modèle avec toutes les photos du Jura annotées par Anna (plutôt que l'échantillon de 8800 photos utilisées par Gaspard) et toutes les photos de l'Ain annotées par les collègues de l'OFB.Plus on a de photos, mieux c'est. Ce modèle pourra alors être utilisé pour tagger les photos restantes dans l'Ain, et pour tagger à l'avenir les photos collectées dans le cadre du PPP Lynx.

About

My personal pipeline to species identification on camera trap pix using deep learning, detection/classification with MegaDetector and RetinaNet

Topics

Resources

Stars

Watchers

Forks


[8]ページ先頭

©2009-2025 Movatter.jp