Introduction aux mégadonnées en sciences sociales
Université de Montréal
“Comprendre que les images ne sont ni des vérités ni des mensonges absolus, mais des constructions qui sont simultanément des copies, des reconstitutions partielles, des simulations, des illusions et des fantaisies du réel”
(Slavkova 2017)
???
Source: (Buolamwini et Gebru 2018)
Ce cours contient une démonstration pratique basée sur une recherche réelle portant sur l’analyse d’images médiatiques concernant les réfugiés climatiques dans les médias québécois.
Source_Date_Numéro_Type.extension
Exemples:
JdeM_2023_02_27_01.png
→ Journal de Montréal, 27 février 2023, image 1LaPresse_2022_11_05_02_opinion.png
→ La Presse, 5 novembre 2022, image 2, article d’opiniondf_images <- df_images %>%
mutate(
# Extraire le média à partir du nom de fichier
media = case_when(
str_detect(chemin_image, "LeDevoir") ~ "LeDevoir",
str_detect(chemin_image, "LaPresse") ~ "LaPresse",
str_detect(chemin_image, "JdeM") ~ "JournalDeMontreal",
TRUE ~ str_extract(nom_fichier, "^[A-Za-z]+(?=_\\d{4}_)")
),
# Extraire la date au format YYYY_MM_DD
date_str = str_extract(nom_fichier, "\\d{4}_\\d{2}_\\d{2}"),
date = case_when(
!is.na(date_str) ~ ymd(gsub("_", "-", date_str)),
TRUE ~ as.Date(NA)
),
# Déterminer si c'est un article d'opinion
est_opinion = case_when(
str_detect(chemin_image, "_opinion") ~ TRUE,
str_detect(nom_fichier, "opinion") ~ TRUE,
TRUE ~ FALSE
)
)
# Définition du dossier d'images
dossier_images <- "images"
# Liste tous les fichiers d'images dans le dossier
chemins_images <- list.files(
path = dossier_images, # Dossier à scanner
pattern = "\\.(jpg|jpeg|png|PNG)$", # Filtrer uniquement les fichiers image
recursive = TRUE, # Inclure les sous-dossiers
full.names = TRUE # Obtenir les chemins complets
)
# Afficher le nombre d'images trouvées
cat("Nombre d'images trouvées:", length(chemins_images), "\n")
# Extraction du média, de la date et du type d'article
df_images <- df_images %>%
mutate(
# Extraction du nom de fichier
nom_fichier = basename(chemin_image),
# Extraction du média
media = case_when(
str_detect(chemin_image, "LeDevoir") ~ "LeDevoir",
str_detect(chemin_image, "LaPresse") ~ "LaPresse",
str_detect(chemin_image, "JdeM") ~ "JournalDeMontreal",
TRUE ~ str_extract(nom_fichier, "^[A-Za-z]+(?=_\\d{4}_)")
),
# Extraction de la date
date_str = str_extract(nom_fichier, "\\d{4}_\\d{2}_\\d{2}"),
date = case_when(
!is.na(date_str) ~ ymd(gsub("_", "-", date_str)),
TRUE ~ as.Date(NA)
),
# Détermination si c'est un article d'opinion
est_opinion = case_when(
str_detect(chemin_image, "_opinion") ~ TRUE,
str_detect(nom_fichier, "opinion") ~ TRUE,
TRUE ~ FALSE
)
) %>%
select(-nom_fichier, -date_str)
Type d’analyse | Exemple de prompt | Format de réponse |
---|---|---|
Justification image-texte | “Cette image et ce texte correspondent au contenu d’un article médiatique du Québec. La sélection de l’image est-elle justifiée par le texte?” | Binaire (1=oui, 0=non) |
Description générale | “Dans un contexte de migration, décrivez cette image provenant du contenu d’un article médiatique québécois. Portez une attention particulière aux détails.” | Paragraphe descriptif |
Identification géographique | “Cette image provient d’un article médiatique québécois. L’image semble-t-elle avoir été prise à la frontière entre le Québec et les États-Unis?” | Binaire (1=oui, 0=non) |
Analyse thématique | “Cette image provient d’un article médiatique québécois. Qu’est-ce qui semble être au cœur de cette image: les individus et leurs émotions, le mouvement des personnes, l’environnement, ou autre?” | Catégorisation + détails |
Caractéristiques culturelles | “Cette image provient d’un article médiatique québécois et peut fournir des informations liées à la migration. Quelles caractéristiques ou éléments discernables indiquent des origines culturelles ou ethniques?” | Description ou “NA” |
Identification d’éléments spécifiques | “Cette image provient d’un article médiatique québécois. Y a-t-il des symboles culturels ou religieux représentés dans l’image?” | Binaire (1=oui, 0=non) |
Analyse de représentation genrée | “Cette image provient d’un article médiatique québécois. Pensez-vous que l’image dépeint la vulnérabilité de manière genrée?” | Binaire (1=oui, 0=non) |
Analyse de problème/solution | “Cette image provient d’un article médiatique québécois. Si applicable, quel problème ou menace lié au thème de la migration est présenté, et quelle solution est suggérée dans l’image?” | Description analytique |
Catégorisation thématique multiple | “Cette image provient d’un article médiatique québécois. Quels thèmes sont représentés dans l’image?” [liste de thèmes fournie] | Énumération de thèmes |
#| echo: true
#| eval: false
# Fonction pour analyser une image avec GPT Vision
analyser_image <- function(chemin_image, prompt_texte) {
# Vérification que le fichier existe et est une image
if (file.exists(chemin_image) &&
tolower(tools::file_ext(chemin_image)) %in% c("jpg", "jpeg", "png")) {
cat("Analyse de l'image:", chemin_image, "\n")
# Dans un contexte réel, ici on ferait appel à l'API GPT Vision
# Via le package clellm::gpt_vision()
# Simulation de réponse pour démonstration
reponse <- paste("Analyse de l'image", basename(chemin_image),
"Cette image montre [description simulée pour démonstration]")
return(reponse)
} else {
return("ERREUR: Fichier introuvable ou format non pris en charge")
}
}
#| echo: true
#| eval: false
# Définition du tableau de prompts d'analyse
prompts_analyse <- data.frame(
question = c("description", "elements", "emotions", "symboles"),
prompt = c(
"Décrivez cette image en détail.",
"Quels éléments visuels sont présents dans cette image?",
"Quelles émotions semblent être exprimées dans cette image?",
"Y a-t-il des symboles culturels ou politiques dans cette image?"
),
stringsAsFactors = FALSE
)
# Sélection de quelques images pour démonstration
images_demo <- df_images %>% slice(1:3)
# Création d'un dataframe pour stocker les résultats
resultats_demo <- data.frame(
image_id = character(),
question = character(),
prompt = character(),
reponse = character(),
stringsAsFactors = FALSE
)
#| echo: true
#| eval: false
# Boucle principale pour analyser chaque image
for (i in 1:nrow(images_demo)) {
# Récupération des informations de l'image
image_id <- images_demo$image_id[i]
chemin_image <- images_demo$chemin_image[i]
# Information de progression
cat("Traitement de l'image", i, "/", nrow(images_demo), ":\n")
cat("ID:", image_id, "\n")
cat("Chemin:", chemin_image, "\n\n")
#| echo: true
#| eval: false
# Pour chaque prompt/question
for (j in 1:nrow(prompts_analyse)) {
# Récupération du prompt
question <- prompts_analyse$question[j]
prompt <- prompts_analyse$prompt[j]
# Information sur l'analyse en cours
cat("Question:", question, "\n")
cat("Prompt:", prompt, "\n")
# Analyse de l'image avec le prompt actuel
reponse <- analyser_image(chemin_image, prompt)
#| echo: true
#| eval: false
# Ajout du résultat au dataframe
resultats_demo <- rbind(resultats_demo, data.frame(
image_id = image_id,
question = question,
prompt = prompt,
reponse = reponse,
stringsAsFactors = FALSE
))
# Pause entre les appels API pour éviter de dépasser
# les limites de rate de l'API
cat("Pause entre les analyses...\n")
Sys.sleep(1)
}
# Afficher la progression
cat("Progression:", i, "/", nrow(images_demo), "images analysées\n")
}
#| echo: true
#| eval: false
# Créer le dossier resultats s'il n'existe pas
if (!dir.exists("resultats")) {
dir.create("resultats")
cat("Dossier 'resultats' créé.\n")
}
# Enregistrement des résultats
write.csv(resultats_demo, "resultats/resultats_analyse.csv", row.names = FALSE)
write_xlsx(resultats_demo, "resultats/resultats_analyse.xlsx")
cat("Les résultats ont été enregistrés!\n")
Avantages:
Limites:
Merci pour votre attention!
Comment fonctionne gpt_vision()
Le package
clellm
fournit la fonctiongpt_vision()
qui:image_path
)prompt
)max_tokens
)model="gpt-4o"
)