Traitement image, suite

Nous allons effectuer des traitements différents de la semaine précédente sur l'image suivante:

Nous importons donc les mêmes modules, et la même méthode pour lire l'image:

Python
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import numpy as np

img = mpimg.imread("Paris.jpg")

Les 4 transformations étudiées sont : flou, contours, symetrie axe horizontal, rotation (par composée de symétrie), et en utilisant la méthode diviser pour régner.

1. Flou⚓︎

En modifiant chaque pixel par la moyenne du pixel et des 8 adjacents, on obtient un léger flou. Il nous faut donc pour chaque pixel calculer une moyenne à partir des pixels de gauche, du haut, de droite et du bas.

Nous allons alors rogner de 2 lignes et 2 colonnes pour toujours avoir des pixels sur les côtés. Il est aussi possible de ne pas rogner et de calculer une moyenne autrement pour les pixels du bord de l'image.

Python
def flou(img):
    forme = img.shape
    largeur = forme[1]
    hauteur = forme[0]
    image_t = np.ndarray((forme[0] - 2, forme[1] - 2,3)) # création d'une image vide au format rogné de 2 lignes et 2 colonnes

    # parcours des pixels de l'image d'origine
    for x in range(1 ,largeur -1):
        for y in range(1, hauteur -1):
            pixc = img[y][x].copy() # copie du pixel du centre
            pixel = np.zeros(3) # création d'un pixel avec la valeur [0 0 0]

            # parcours des 9 pixels inclus dans le carré autour du pixel
            for deltax in [-1,0,1]:
                for deltay in [-1,0,1]:

                    pixel += img[...][...] / (9 * 255) # ajout de la valeur de chaque pixel avec la pondération 1/9 et ramené en flottant
            # ajout du pixel Ă  l'image contour
            image_t[y - 1][x - 1]= np.array(pixel)
    return image_t

2. Contours⚓︎

Pour détecter les contours dans une image, il est possible d'utiliser le filtre de Laplace.

L'idée est de calculer une moyenne comme pour le flou mais avec des pondérations positives et négativess pour les pixels autour.

En donnant une pondération 8 au pixel central et -1 aux pixels adjacents, les pixels entourés de pixels de mêmes couleurs auront ainsi une couleur noire.

\[\begin{pmatrix} -1& -1& -1 \\ -1 & 8 & -1 \\ -1 & -1 & -1 \end{pmatrix}\]

Remarque: pour éviter une structure conditionnelle, sans changer la valeur de cette moyenne pondérée.

il est possible pour chacun des 9 pixels du carré de compter 1 fois positivement celui du centre et 1 fois negativement tous les pixels.

Python
def laplace(img):
    forme = img.shape
    largeur = forme[1]
    hauteur = forme[0]
    image_t = np.ndarray(forme)
    for x in range(1,largeur -1):
        for y in range(1, hauteur - 1):
            pixc = img[y][x].copy()
            pixel = np.zeros(3)
            for deltax in [-1,0,1]:
                for deltay in [-1,0,1]:
                    pixel += ... # ajout de la valeur du pixel central
                    pixel -= ... # soustraction de la valeur du pixel concerné [y + deltay][x + deltax]
            # ajout du pixel Ă  l'image contour
            image_t[y - 1][x - 1]= np.array(pixel/255)
    return image_t

3. Symétrie d'axe horizontal⚓︎

hauteur = img.shape[0]

Le code est assez simple, il suffit de remplacer le pixel[y][x] par pixel[hauteur - 1 - y][x]

Attention hauteur - 1 et pas hauteurcar y commence à 0 et finit à hauteur - 1. Sans cette précaution, nous aurions une sortie de tableau.

Python
Code Ă  Ă©crire

3. Rotation⚓︎

Une rotation de 90° anti-horaire peut être obtenue en compsant une symétrie d'axe horizontal et une autre symétrie d'axe la diagonale principale du carré.

Le code sera alors assez semblable à celui de la symétrie.

Python
def rotation(img):

    forme = img.shape
    largeur = forme[1]
    hauteur = forme[0]
    nouvelle_forme = (forme[1], forme[0],3) # au cas où l'image n'est pas carrée, les dimensions largeur, hauteur sont permutées.
    image_t = np.ndarray(nouvelle_forme)

    for x in range(largeur):
        for y in range(hauteur) :
            image_t[y][x] = img[...][...] /255
    return image_t

4. Rotation avec la méthode diviser pour régner.⚓︎

Rappel : la méthode diviser pour régner, divise un problème en plusieurs problèmes indépendants qui seront traités séparément avant d'être combinés.

Les 3 étapes sont : diviser, régner, combiner

Ici L'image est divisée en 4 parties par deux axes: un horizontal, un vertical

Text Only
1 2
3 4

Chacune des parties est transformée par rotation, puis

Les parties sont réassemblées d'ans l'ordre :

Text Only
2 4
1 3

Pour assembler les parties, nous utilisons deux méthodes np.hstack et np.vstack qui permettent de coller des tableaux (matrices) respectivement horizontalement et verticalement.

Python
def rotation_dpr(img):
    forme=img.shape
    largeur = forme[1]
    hauteur = forme[0]

    ml  = largeur // 2 # mi largeur
    mh = hauteur // 2 # mi hauteur

    # Diviser
    hg = img[0:mh,0:ml] # quart haut gauche
    hd = img[0:mh,ml:largeur] # quart haut droit
    bg = img[mh:hauteur,0:ml] # quart bas gauche
    bd = img[mh:hauteur,ml:largeur] # quart bas droite

    # RĂ©gner
    rhg = rotation(hg)
    rhd = rotation(hd)
    rbg = rotation(bg)
    rbd = rotation(bd)

    # Combiner (Assemblage)
    haut = np.hstack([rhd,rbd])
    bas =   np.hstack([rhg,rbg])
    return np.vstack([haut,bas])

Remarque Cette utilisation du diviser pour régner est ici moins intéressante que pour le tri fusion. En effet, la résolution de chaque sous-problème n'ayant pas une compléxité quadratique, il n'y a pas de gain de compléxité temporelle globale.