Utilisation d’un module (os) pour interagir avec le système.

import os
import random
import csv
random.seed()

Lister les fichier et sous-dossiers d’un dossier

os.listdir("images")
['NF-1001.jpg',
 'NF-1002.jpg',
 'NF-1003.jpg',
 'SF-1001.jpg',
 'SF-1002.jpg',
 'SF-1003.jpg',
 'NM-1007.jpg',
 'NM-1010.jpg',
 'SM-1007.jpg',
 'SM-1010.jpg',
 '.ipynb_checkpoints']

Mettre les fichiers d’images dans un tableau images

images = []
for fichier in os.listdir("images"):
    if fichier[-4:] == ".jpg" :   # c'est une image
        images.append(fichier)
images
['NF-1001.jpg',
 'NF-1002.jpg',
 'NF-1003.jpg',
 'SF-1001.jpg',
 'SF-1002.jpg',
 'SF-1003.jpg',
 'NM-1007.jpg',
 'NM-1010.jpg',
 'SM-1007.jpg',
 'SM-1010.jpg']

Mélanger le tableau images

random.shuffle(images)
images1 = images[:len(images)//2]
images2 = images[len(images)//2:]
print(images1)
print(images2)
['SM-1010.jpg', 'NM-1010.jpg', 'NF-1002.jpg', 'NF-1003.jpg', 'NM-1007.jpg']
['SF-1003.jpg', 'SF-1002.jpg', 'NF-1001.jpg', 'SF-1001.jpg', 'SM-1007.jpg']

Tester si un élément est dans un tableau

print(images)
print("'SM-1007.jpg' dans images: "+str('SM-1007.jpg' in images))
print("'KM-1007.jpg' dans images: "+str('KM-1007.jpg' in images))
['SM-1010.jpg', 'NM-1010.jpg', 'NF-1002.jpg', 'NF-1003.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 'NF-1001.jpg', 'SF-1001.jpg', 'SM-1007.jpg']
'SM-1007.jpg' dans images: True
'KM-1007.jpg' dans images: False

Génération de deux blocs d’images respectant la contrainte “pas deux fois la même personne dans un bloc”

images1 = []
images2 = []
random.shuffle(images)

for img in images:
    if img[0] == 'S':
        img_a_trouver = 'N'+img[1:]
    else:
        img_a_trouver = 'S'+img[1:]
    if img_a_trouver in images1:
        images2.append(img)
    else:
        images1.append(img)
        
print(images1)
print(images2)
['SF-1001.jpg', 'SM-1007.jpg', 'SF-1002.jpg', 'SM-1010.jpg', 'NF-1003.jpg']
['NF-1002.jpg', 'NM-1010.jpg', 'NF-1001.jpg', 'SF-1003.jpg', 'NM-1007.jpg']

On réarrange l’ordre dans chaque bloc pour respecter la contrainte “pas k images de suite de la même catégorie”

images1 = ['NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg']
images1b = []
k = 3 # max 2 images de suites dans la même catégorie
m = 0 # nombre d'images de la catégories de l'image regardée
cat = '' # catégorie des dernières images

mises_de_cote = []

for img in images1:
    if cat == img[:2]: # est-on dans la même catégorie qu'avant ?
        if m >= k-1: # si on est déjà au max
            # on met l'image de côté
            mises_de_cote.append(img)
        else:
            images1b.append(img)
            m = m + 1
    else: # on change de catégorie
        images1b.append(img)
        cat = img[:2] # on change la catégorie
        m = 1
print(images1b)
print(mises_de_cote)
['NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 'SF-1003.jpg']
['SF-1002.jpg']

On place ce code dans une fonction

def force_contrainte_categorie(images, k):
    """
    Cette fonction prend en argument un tableau d'images 
    et renvoie deux tableaux:
    - un premier tableau comportant une suite d'images trouves 
      dans `images`, en conservant l'ordre et de façon à ce 
      que la contrainte de catégorie soit respectée
    - un deuxième tableau contenant les images restantes
    
    k est le nombre d'images maximum qu'on peut trouver 
    de suite dans une même catégorie
    """
    # La catégorie d'une image est donnée par 
    # les 2 premières lettres du nom du fichier
    
    images_resultat = []
    m = 0 # nombre d'images de la catégories de l'image regardée
    cat = '' # catégorie des dernières images

    mises_de_cote = []

    for img in images:
        if cat == img[:2]: # est-on dans la même catégorie qu'avant ?
            if m >= k: # si on est déjà au max
                # on met l'image de côté
                mises_de_cote.append(img)
            else:
                images_resultat.append(img)
                m = m + 1
        else: # on change de catégorie
            images_resultat.append(img)
            cat = img[:2] # on change la catégorie
            m = 1
    # renvoyer le résultat, i.e. les deux tableaux
    return (images_resultat, mises_de_cote)
force_contrainte_categorie(
    ['NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 
     'SF-1003.jpg', 'SF-1002.jpg'],
    2)
(['NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 'SF-1003.jpg'], ['SF-1002.jpg'])
force_contrainte_categorie(
    ['NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 
     'SF-1003.jpg', 'SF-1002.jpg'],
    1)
(['NM-1007.jpg', 'SF-1001.jpg'], ['NM-1010.jpg', 'SF-1003.jpg', 'SF-1002.jpg'])
force_contrainte_categorie(
    ['SF-1003.jpg', 'NM-1007.jpg', 
     'NM-1010.jpg', 'SF-1001.jpg', 
     'SF-1002.jpg'],
    2)
(['SF-1003.jpg', 'NM-1007.jpg', 'NM-1010.jpg', 'SF-1001.jpg', 'SF-1002.jpg'],
 [])
force_contrainte_categorie([],2)
([], [])
force_contrainte_categorie(['NM-1010.jpg'],2)
(['NM-1010.jpg'], [])
imgs = ['SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
        'NM-1007.jpg', 'NM-1010.jpg']
taille = len(imgs)

imgs_ok = []
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
imgs = imgs_ok + reste
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
imgs = imgs_ok + reste
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
['SF-1001.jpg', 'NM-1007.jpg']
['SF-1003.jpg', 'SF-1002.jpg', 'NM-1010.jpg']
['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'NM-1010.jpg']
['SF-1002.jpg']
['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'NM-1010.jpg', 'SF-1002.jpg']
[]
imgs = ['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
        'NM-1010.jpg']
taille = len(imgs)

imgs_ok = []
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
imgs = imgs_ok + reste
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
imgs = imgs_ok + reste
(imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
print(imgs_ok)
print(reste)
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg']
['SF-1003.jpg', 'SF-1002.jpg']
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg', 'SF-1003.jpg']
['SF-1002.jpg']
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg', 'SF-1003.jpg']
['SF-1002.jpg']
imgs = ['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
        'NM-1010.jpg']

imgs_ok = [] # au début aucune image n'est bien rangée
reste = imgs # et donc toutes les images sont à ranger
longueur_precedente = -1 # pour entrer au moins une fois dans la boucle
taille_fin = len(imgs)


while len(imgs_ok) < taille_fin and len(imgs_ok) > longueur_precedente:
    longueur_precedente = len(imgs_ok)
    imgs = imgs_ok + reste
    (imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
    print(imgs_ok)
    print(reste)
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg']
['SF-1003.jpg', 'SF-1002.jpg']
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg', 'SF-1003.jpg']
['SF-1002.jpg']
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg', 'SF-1003.jpg']
['SF-1002.jpg']
imgs = ['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
        'NM-1010.jpg']

imgs_ok = [] # au début aucune image n'est bien rangée
reste = imgs # et donc toutes les images sont à ranger
longueur_precedente = -1 # pour entrer au moins une fois dans la boucle
taille_fin = len(imgs)


while len(imgs_ok) < taille_fin and len(imgs_ok) > longueur_precedente:
    longueur_precedente = len(imgs_ok)
    imgs = imgs_ok + reste
    (imgs_ok, reste) = force_contrainte_categorie(imgs, 1)
    print(imgs_ok)
    print(reste)
['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'NM-1010.jpg']
['SF-1002.jpg']
['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'NM-1010.jpg', 'SF-1002.jpg']
[]
def rearrange(images, k):
    """
    prend en argument un tableau d'images et un nombre k 
    qui est un maximum d'images consécutives d'une même catégorie
    
    renvoie un tableau réarrangé de façon à respecter la contrainte de catégorie
    """
    imgs_ok = [] # au début aucune image n'est bien rangée
    reste = images # et donc toutes les images sont à ranger
    longueur_precedente = -1 # pour entrer au moins une fois dans la boucle
    taille_fin = len(images)

    while len(imgs_ok) < taille_fin and len(imgs_ok) > longueur_precedente:
        longueur_precedente = len(imgs_ok)
        imgs = imgs_ok + reste
        (imgs_ok, reste) = force_contrainte_categorie(imgs, k)

    return imgs_ok
rearrange(['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
           'NM-1010.jpg'], 1)
['SF-1001.jpg', 'NM-1007.jpg', 'SF-1003.jpg', 'NM-1010.jpg', 'SF-1002.jpg']
rearrange(['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
           'NM-1010.jpg'], 1)
['NM-1007.jpg', 'SF-1001.jpg', 'NM-1010.jpg', 'SF-1003.jpg']
def melange_et_repartit(images):
    """
    Répartit les images en deux tableaux. 
    Chacun des tableaux contient les même personnes, mais avec une expression différente 
    et dans un ordre différent.
    """
    images1 = []
    images2 = []
    random.shuffle(images)
    for img in images:
        if img[0] == 'S':
            img_a_trouver = 'N'+img[1:]
        else:
            img_a_trouver = 'S'+img[1:]
        if img_a_trouver in images1:
            images2.append(img)
        else:
            images1.append(img)
    return (images1, images2)
melange_et_repartit(['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
           'NM-1010.jpg', 'SM-1007.jpg', 'NF-1001.jpg', 'NF-1003.jpg', 'NF-1002.jpg', 
           'SM-1010.jpg'])
(['NF-1002.jpg', 'NF-1001.jpg', 'NM-1007.jpg', 'NM-1010.jpg', 'SF-1003.jpg'],
 ['SF-1001.jpg', 'SM-1007.jpg', 'NF-1003.jpg', 'SF-1002.jpg', 'SM-1010.jpg'])
def tirage(images, k):
    """
    Répartit aléatoirement les images en deux tableaux de même taille tels que:
    - chaque personne apparaît exactement une fois dans chaque tableau
    - on a pas plus de k photos d'une même catégorie (expression, genre) qui se suivent
    """
    images_r1 = [] 
    images_r2 = []
    while len(images_r1) + len(images_r2) < len(images):
        (images1, images2) = melange_et_repartit(images)
        images_r1 = rearrange(images1, k)
        images_r2 = rearrange(images2, k)
    return (images_r1, images_r2)    
tirage(['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
           'NM-1010.jpg', 'SM-1007.jpg', 'NF-1001.jpg', 'NF-1003.jpg', 'NF-1002.jpg', 
           'SM-1010.jpg'], 1)
(['NM-1010.jpg', 'SM-1007.jpg', 'NF-1002.jpg', 'SF-1001.jpg', 'NF-1003.jpg'],
 ['SF-1003.jpg', 'SM-1010.jpg', 'NM-1007.jpg', 'NF-1001.jpg', 'SF-1002.jpg'])
def fabrique_fichiers(debut_fichier, images, k):
    """
    Détermine deux tableaux d'images aléatoires prises dans `images` et respectant les contraintes suivantes:
    - chaque personne apparaît exactement une fois dans chaque tableau
    - on a pas plus de k photos d'une même catégorie (expression, genre) qui se suivent
    Enregistre ces tableaux chacun dans un fichier dont le nom commence par `debut_fichier`
    """
    (images_1, images_2) = tirage(images, k)
    with open(debut_fichier+"-1.csv", "w", encoding="utf-8") as f:
        ecrivain = csv.writer(f)
        ecrivain.writerow(["image"])
        for img in images_1:
            ecrivain.writerow([img])
    with open(debut_fichier+"-2.csv", "w", encoding="utf-8") as f:
        ecrivain = csv.writer(f)
        ecrivain.writerow(["image"])
        for img in images_2:
            ecrivain.writerow([img])
    
fabrique_fichiers("toto", ['NM-1007.jpg', 'SF-1001.jpg', 'SF-1003.jpg', 'SF-1002.jpg', 
           'NM-1010.jpg', 'SM-1007.jpg', 'NF-1001.jpg', 'NF-1003.jpg', 'NF-1002.jpg', 
           'SM-1010.jpg'], 2)
def genere_donnees(dossier_donnees, dossier_images, nombre, k):
    """
    génère les fichiers dans `dossier_donnees` pour `nombre` jeux de données en prenant les images
    dans `dossier_images` et en respectant les contraintes de ne pas avoir plus de k images consécutives
    d'une même catégorie
    """
    images = []
    for fichier in os.listdir(dossier_images):
        if fichier[-4:] == ".jpg" :   # c'est une image
            images.append(fichier)
    for i in range(0, nombre):
        fabrique_fichiers(dossier_donnees + "/tirage-" + str(i), images, k)
    
genere_donnees("donnees", "images", 32, 3)
def gen_file(i,c):
    nm = "M" if i % 5 == 0 else "F"
    return f"{c}{nm}-{i}.jpg"
beaucoup_images = [ gen_file(i, c) for i in range(1001, 1221) for c in ["N","S"] ]

r_images1 = []
r_images2 = []
while len(r_images1) + len(r_images2) < len(beaucoup_images):
    random.shuffle(beaucoup_images)
    images1 = []
    images2 = []
    
    for img in beaucoup_images:
        if img[0] == 'S':
            img_a_trouver = 'N'+img[1:]
        else:
            img_a_trouver = 'S'+img[1:]
        if img_a_trouver in images1:
            images2.append(img)
        else:
            images1.append(img)
    r_images1 = rearrange(images1, 3)
    print(len(r_images1))
    r_images2 = rearrange(images2, 3)
    print(len(r_images2))
print("ok")
218
216
207
215
219
214
218
213
218
220
215
220
220
220
ok
Maître de conférences en Informatique