ImageMagick, R et bash pour filtrer des images

Canon Camera from Pixabay

Introduction

J’ai un disque sur lequel je garde des images que j’enregistre depuis les réseaux sociaux, souvent des infographies. Dans ce tutoriel, nous allons utiliser bash, ImageMagick et R pour effectuer le ménage dans ce répertoire.

Il y a souvent des pages que j’enregistre au complet, mais seulement pour garder les photos qu’elles contiennent. Celles-ci contiennent souvent des miniatures et des images utilisées pour le thème de la page.

Bref, au fil des années, le répertoire devenait un fouillis.

Détecter la résolution des images avec ImageMagick

Logo de ImageMagick
Logo de ImageMagick

Je cherchais donc un moyen de conserver seulement les grandes images, celles avec une résolution de 720×720 minimum.

Donc, ma première étape a été de trouver un moyen de lister la résolution de toutes les images du répertoire.

J’ai fait ceci en utilisant identify, un outil de la suite ImageMagick.

identify InvertedIndex.jpg

La sortie de ce logiciel ressemble à ceci:

InvertedIndex.jpg JPEG 588x447 588x447+0+0 8-bit sRGB 36166B 0.000u 0:00.000

Ensuite, en utilisant awk, je conserve le premier élément de la sortie, qui est le nom de fichier, ainsi que le 3e élément, qui est la résolution, sous la forme AxB.

identify InvertedIndex.jpg | awk '{print $1, $3}'

En sortie, on obtient

InvertedIndex.jpg 588x447

Je veux exécuter cette commande récursivement pour tous les sous-répertoires courants. Pour ce faire, find permet de lister tous les fichiers. Le programme complet ressemble donc à ceci, prenant en entrée deux arguments:

  • le répertoire
  • le fichier de sortie
#!/bin/bash
find "$1" -type f -exec identify \{\} \; | awk '{print $1, $3}' > "$2"

Identifier les fichiers à supprimer avec R

Pour la suite des choses, je vais utiliser le langage de programmation R, qui va me permettre de manipuler le fichier de sortie et de générer la liste des fichiers à supprimer

Je charge tidyverse (parce que je suis un peu lâche et ça comprend tout, comme Hélix de Vidéotron 🙃)

library("tidyverse")

Ensuite, définition de mon répertoire et du fichier de sortie

my_dir <- "/something/something/"
output_file <- "somefile.txt"
  • Appel de mon programme bash écrit ci-haut avec la fonction system, j’utilise paste0 pour construire la commande à exécuter:
system(paste0("bash liste_dimensions.sh ",my_dir," ",output_file))
  • Positionner dans le répertoire de travail
setwd(my_dir)
  • Lecture du fichier généré
files.txt <- read_table(paste0(my_dir,output_file), col_names = "nom")
  • Séparation de mes deux colonnes
files.txt$nom %>% 
  str_split_fixed(pattern = " ",n = 2) -> 
  files_split
  • Conversion en tibble
files_split %>% 
  as.tibble() -> 
  files_tibble

J’utilise ensuite separate et transmute pour obtenir 3 colonnes, une avec le nom de fichier, une avec la largeur et une avec la hauteur au format numérique

files_tibble %>%
 separate(col = V2, sep = "x", into = c("width","height")) %>%
  transmute(
    path=V1,
    width = width %>% as.numeric(),
    height = height %>% as.numeric(),
  ) -> files_attr

Je filtre ensuite les fichiers à supprimer

files_attr %>% 
  filter(width <= 720 & height <= 720) -> to_delete

J’exporte la liste de fichiers à supprimer

to_delete$path %>% write_lines("to_delete.txt")

Supprimer les fichiers avec bash

De retour au terminal bash, je supprime les fichiers en utilisant xargs pour éviter un dépassement de capacité.

cat to_delete.txt | xargs -0 -I {} rm "{}"

Conclusion

Dans ce billet, j’ai montré comment faire le tri dans un répertoire de photos à l’aide d’un script qui permettra de sauver beaucoup de temps à un utilisateur averti.

Crédit photo

Image by S. Hermann & F. Richter from Pixabay