'''Intelligence artificielle'''

'''Réseau de neurones Convolution d’images Détection de contours - Elèves'''

## Lecture des images

# Affichage

import matplotlib.pyplot as plt
plt.close('all')

def f_Affiche(fig,image):
    plt.figure(fig)
    plt.imshow(image)
    plt.axis('off')
    plt.show()
    plt.pause(0.01)

# Lecture des images

def f_Lecture(Chemin):
    Image = plt.imread(Chemin)
    Image = Image[:,:,:3] # Si RGBA
    return Image

# Lecture et affichage de l'image fournie

Chemin = "Image.bmp"
Image = f_Lecture(Chemin)
f_Affiche(1,Image)

## Fonctions de transformation

# Imports

import numpy as np

# Données des transformations globales pour la suite

kr,kg,kb = 1/3,1/3,1/3
S = 60 # Seuil NB - Plus il est petit, plus il y a de blanc
K = np.array([[0,1,0],[1,-4,1],[0,1,0]]) # Noyau de convolution dimension 3
n = np.shape(K)[0]

# Nuances de gris

def f_NG(im):
    '''Passage d'une image quelconque en nuances de gris (R=G=B entre 0 et 255)'''
    Nl,Nc = im.shape[0:2]
    imng = np.copy(im)
    for c in range(Nc):
        for l in range(Nl):
            R,G,B = im[l,c]
            Nuance = kr * R + kg * G + kb * B
            Nuance = int(round(Nuance,0))
            imng[l,c,:] = Nuance
    return imng

# Noir et blanc

def f_NB(im):
    '''Passage d'une image quelconque en noir et blanc (0 ou 255)'''
    Nl,Nc = im.shape[0:2]
    imnb = np.copy(im)
    for c in range(Nc):
        for l in range(Nl):
            R,G,B = im[l,c]
            Nuance = kr * R + kg * G + kb * B # Inutile sur image NG
            if Nuance < S:
                NB = 0
            else:
                NB = 255
            imnb[l,c,:] = NB
    return imnb

# Convolution

def f_Conv_Loc(M,K):
    '''Produit de convolution local renvoyant le triplet RGB associé à l'image local M et le noyau K'''
    def f_RGB(i):
        M_RGB = M[:,:,i]
        Prod = K*M_RGB
        Somme = np.sum(Prod)
        RGB = int(Somme)
        RGB = max(min(RGB,255),0)
        return RGB
    R = f_RGB(0)
    G = f_RGB(1)
    B = f_RGB(2)
    return [R,G,B]

'''
La normalisation de K est inutile dans ce TD, la somme des coefficients vaut 0 dans le Laplacien
'''

def f_Convolution(im,f_conv_loc,K):
    '''Convolution de toute l'image, bords supprimés'''
    Nl,Nc = im.shape[0:2]
    k = n//2
    Im_Conv = np.copy(im)
    for c in range(k,Nc-k):
        for l in range(k,Nl-k):
            Im_Loc = im[l-k:l+k+1,c-k:c+k+1]
            Im_Conv_Loc = f_conv_loc(Im_Loc,K)
            Im_Conv[l,c] = Im_Conv_Loc
    Im_Conv = Im_Conv[k:-k,k:-k,:]
    return Im_Conv

# Test de filtrage

Image_NG = f_NG(Image)
f_Affiche(2,Image_NG)
Image_Conv = f_Convolution(Image_NG,f_Conv_Loc,K)
f_Affiche(3,Image_Conv)
Image_NB = f_NB(Image_Conv)
f_Affiche(4,Image_NB)

## Création de la convolution locale totale

def f_Conv_loc_NB(Mng,K):
    '''Convolution locale de la petite image en nuances de gris Mng de dimensions nxn'''
    # Convolution locale
    R = 0
    for l in range(n):
        for c in range(n):
            tk = K[l,c]
            RM = Mng[l,c,0]
            R += tk*RM
    R = int(round(R))
    R = max(min(R,255),0)
    # N&B
    if R < S:
        Val = 0 # Noir
    else:
        Val = 255 # Blanc
    return [Val,Val,Val]

# Test de filtrage

Image_Conv_Tot = f_Convolution(Image_NG,f_Conv_loc_NB,K)
f_Affiche(10,Image_Conv_Tot)

## Données pour le RN