Commit c518bf4a authored by robin.danz's avatar robin.danz
Browse files

Comments & readme updates

parent bb867f32
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
#Python cache directory

/__pycache__/
 No newline at end of file
+9 −1
Original line number Diff line number Diff line
@@ -37,6 +37,14 @@ Description des differents modules du projet:
 - `fourierTransform.py` : Contient une fonction pour calculer la transformée de Fourier et deux fonctions pour afficher les résultats.
 - `imageReader.py` : module utilitaire utilisé pour la lecture d'une image.

 Des descriptions plus précises sont disponibles dans les commentaires des modules.
 
 Pour afficher l'aide d'un module, exécuter les commandes suivantes dans la console Python:
 ```python
 import [nom du module]
 help([nom du module])
 ```

## Utilisation
### Exécution générale
Le module `main.py` lance l'ensemble de l'application. Il est possible de le lancer en ligne de commande (depuis le répértoire du projet):
@@ -48,7 +56,7 @@ python main.py
Il est également possible de lancer l'application depuis VSCode directement. Aucun autre editeur n'a été testé mais celà devrait être également compatible.


L'image lu par l'application peut être changé. Pour celà il faut se rendre à la ligne 10 du module `main.py`
L'image lu par l'application peut être changé. Pour celà il faut se rendre à la ligne 15 du module `main.py`
```python
img = imageReader.open("res\lemon.png")
```
+44 −30
Original line number Diff line number Diff line
import filters

import numpy as np

import matplotlib.pyplot as plt
import matplotlib.image as npimage

@@ -15,10 +14,11 @@ class cannyEdgeDetector:
    def __init__(self, img):
        """
        Constructeur de la classe
        Input: une image (ndarray)
        -   Input: une image (ndarray)
        """
        
        self.img = img
        self.M, self.N = img.shape[:2]
        self.imgFinal = []
        self.sigma = 1
        self.kernelSize = 5
@@ -27,32 +27,42 @@ class cannyEdgeDetector:
        self.weakPixel = 25
        self.strongPixel = 255

        #Passe l'image en niveau de gris
        #Passe l'image en niveau de gris. Perte de la notion de transparence
        rgb_weights = [0.299, 0.587, 0.114]
        self.img = np.dot(self.img[..., :3], rgb_weights)

    def __gaussianKernel__(self, size=5, sigma=1):
        """
        Suppression du bruit de l'image avec un flou Gaussien
        Opérateur de convolution pour le filtrage gaussien 2D.
        Retourne une matrice 2D
        """
    
        size = int(size) // 2
        x, y = np.mgrid[-size:size+1, -size:size+1]
        normal = 1 / (2.0 * np.pi * sigma**2)
        
        g = np.exp(-((x**2 + y**2) / (2.0*sigma**2))) * normal
        return g

    def __sobelFilter__(self, img):
        """
        Filtre de Sobel, ce filtre calcul la direction de la plus forte variation du clair au sombre
        Filtre de Sobel
        -   Calcul le gradient d'intensité de chaque pixel
            -   Le gradient d'intensité indique la direction de la plus forte variation du clair au sombre
        -   Retourne deux matrices:
            -   Une contenant le module des vecteurs gradients de chaque point
            -   Une contenant l'angle de chaque gradient de chaque point
        """

        #Matrices de convolution pour approximer les derives horizontales et verticales
        Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], np.float32)
        Ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], np.float32)
        
        #Convolution avec l'image et les matrices contenants les derives de chaque points
        Ix = convolve(img, Kx)
        Iy = convolve(img, Ky)

        #Norme et direction du gradient en chaque point de l'image
        G = np.hypot(Ix, Iy)
        G = G/G.max()*255
        theta = np.arctan2(Iy, Ix)
@@ -61,17 +71,20 @@ class cannyEdgeDetector:
    
    def __nonMaxSuppression__(self, img, D):
        """
        Traitement des contours approximatifs et trop epais. Parcours la matrice retournée par la fonction SobelFilter et
        trouve les pixels avec la valeur maximale dans la direction du contour.
        Traitement des contours approximatifs et trop epais. Parcours la matrice des gradients retournée par la fonction SobelFilter.
        Fonctionnement:
        -   Creation d'une matrice vide (Z)
        -   Identification des angles base sur la matrice contenant la direction de chaque point (double boucle for)
        -   Analyse de l'intensite des pixels dans la même direction que le pixel en traitement (q er r) pour trouver le plus intense.
        -   Retourne l'image apres analyse
        """

        M, N = img.shape
        Z = np.zeros((M, N), dtype=np.int32)
        Z = np.zeros((self.M, self.N), dtype=np.int32)
        angle = D * 180. / np.pi
        angle[angle < 0] += 180

        for i in range(1, M-1):
            for j in range(1, N-1):
        for i in range(1, self.M-1):
            for j in range(1, self.N-1):
                try:
                    q = 255
                    r = 255
@@ -104,38 +117,39 @@ class cannyEdgeDetector:

    def __threshold__(self, img):
        """
        Identifie 3 types de pixel: fort, faible ou sans importance. 
        Les pixels détecté comme "fort" vont être accentuées. Les pixels "faibles" vont être atténuées.
        Identifie 3 types de pixel: 
        -   fort (conserve)
        -   faible (conserve)
        -   sans importance (pas conserve)
        Retourne l'image traite, elle ne contient plus que deux types de pixels: faible et fort
        """

        highThreshold = img.max() *  self.highThreshold
        lowThreshold = highThreshold * self.lowThreshold

        M, N = img.shape
        res = np.zeros((M, N), dtype=np.int32)

        weak = np.int32(25)
        strong = np.int32(255)
        res = np.zeros((self.M, self.N), dtype=np.int32)

        #Stockage de l'emplacement des pixels fort et faible
        strong_i, strong_j = np.where(img >= highThreshold)
        zeros_i, zeros_j = np.where(img < lowThreshold)

        weak_i, weak_j = np.where((img <= highThreshold) & (img >= lowThreshold))

        res[strong_i, strong_j] = strong
        res[weak_i, weak_j] = weak
        #Rends les pixels fort blanc et les pixels faibles moins intense
        res[strong_i, strong_j] = self.strongPixel
        res[weak_i, weak_j] = self.weakPixel


        return res

    def __hysteresis__(self, img):
        """
        Se base sur les resultats de "threshold()". Cette fonction consiste a transfomer les pixels faibles en pixels fort
        si l'un des pixels adjacents a celui traite est fort.
        Se base sur les resultats de "threshold()". 
        -   Intensifie le contour en des points ou il est plus faible, test par rapport aux pixels adjacents
        -   Supprime les pixels faibles perdus dans l'image
        """

        M, N = img.shape  
        for i in range(1, M-1):
            for j in range(1, N-1):
        
        for i in range(1, self.M-1):
            for j in range(1, self.N-1):
                if (img[i,j] == self.weakPixel):
                    try:
                        if ((img[i+1, j-1] == self.strongPixel) or (img[i+1, j] == self.strongPixel) or (img[i+1, j+1] == self.strongPixel)
+25 −24
Original line number Diff line number Diff line
@@ -4,9 +4,9 @@ import matplotlib.pyplot as plt

def redFilter(img_orig):
    """
    Applique un filtre rouge à l'image.
    Input: image
    Output: image
    Applique un filtre rouge a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -18,9 +18,9 @@ def redFilter(img_orig):

def blueFilter(img_orig):
    """
    Applique un filtre bleu à l'image.
    Input: image
    Output: image
    Applique un filtre bleu a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -32,9 +32,9 @@ def blueFilter(img_orig):

def greenFilter(img_orig):
    """
    Applique un filtre vert à l'image.
    Input: image
    Output: image
    Applique un filtre vert a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -46,9 +46,9 @@ def greenFilter(img_orig):

def cyanFilter(img_orig):
    """
    Applique un filtre cyan à l'image.
    Input: image
    Output: image
    Applique un filtre cyan a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -60,9 +60,9 @@ def cyanFilter(img_orig):

def magentaFilter(img_orig):
    """
    Applique un filtre magenta à l'image.
    Input: image
    Output: image
    Applique un filtre magenta a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -74,9 +74,9 @@ def magentaFilter(img_orig):

def yellowFilter(img_orig):
    """
    Applique un filtre jaune à l'image.
    Input: image
    Output: image
    Applique un filtre jaune a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -88,9 +88,9 @@ def yellowFilter(img_orig):

def blackFilter(img_orig):
    """
    Applique un filtre en niveau de gris à l'image.
    Input: image
    Output: image
    Applique un filtre en niveau de gris a l'image.
    -   Input: image
    -   Output: image
    """

    im = np.copy(img_orig)  # On fait une copie de l'original
@@ -103,8 +103,9 @@ def blackFilter(img_orig):

def plotAllFilters(img):
    """
    Fonction permettant d'appliquer tous les filtres du module "filters" a l'image "img". Cette fonction s'occupe aussi d'afficher
    les resultats apres application des filtres.
    Fonction permettant d'appliquer tous les filtres du module "filters" a l'image "img". 
    
    Afficher les resultats apres application des filtres.
    """

    plt.subplot(221)
@@ -154,7 +155,7 @@ def plotAllFilters(img):


"""
Permet de tester les fonctions créées dans ce module
Permet de tester les fonctions creees dans ce module
"""
if __name__ == "__main__": 
    import imageReader
+16 −6
Original line number Diff line number Diff line

import numpy as np
import imageReader

from matplotlib import pyplot as plt


def fourierTransform(img):
    """
    Applique une transformation de Fourier sur un tableau à deux dimensions
    Input: image (ndarray, tableau de pixels)
    Ouput: transformation de Fourier (ndarray)
    Applique une transformation de Fourier sur un tableau a deux dimensions
    -   Input: image (ndarray, tableau de pixels)
    -   Ouput: transformation de Fourier de l'image (ndarray)
    """

    fft = np.fft.fft2(img)
    return fft

def plotResult(img, img_fft):
    """
    Affiche l'image de base et les resultats de la transformation de Fourier
    """
    
    plt.subplot(211)
    plt.title("Base picture")
    imgplot = plt.imshow(img)




    plt.subplot(212)
    plt.title("Picture after FFT")
    imgplot = plt.imshow(abs(img_fft))
@@ -29,6 +33,12 @@ def plotResult(img, img_fft):
    plt.show()

def plotCannyResult(cannyImg, cannyImg_fft):
    """
    Affiche l'image de base et les resultats de la transformation de Fourier

    Cette fonction est utile pour afficher la transformation de Fourier d'une image traitee par l'algorithme de Canny
    """

    plt.subplot(211)
    plt.title("Base picture")
    imgplot = plt.imshow(cannyImg, cmap="gray")
@@ -42,7 +52,7 @@ def plotCannyResult(cannyImg, cannyImg_fft):
    plt.show()

"""
Permet de tester la fonctions créée dans ce module
Permet de tester les fonctions créées dans ce module
"""
if __name__ == "__main__":
    img = imageReader.open("res\dice.png");
Loading