#### TP n°5: Manipulation d'images ####
#################







## Question 1 

### MANIPULATIONS SIMPLES SUR LES PIXELS ###
## Question 2 : Négatif
image_negatif=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur):
        image_negatif[i,j]=255-image[i,j]
plt.figure()
plt.imshow(image_negatif,cmap="gray")
plt.show()
## Question 3 : Seuillage
seuil=150
image_seuillee=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur):
        if image[i,j]<seuil:
            image_seuillee[i][j]=0
        else:
            image_seuillee[i][j]=255
plt.figure()
plt.imshow(image_seuillee,cmap="gray")
plt.show()
## Question 4 : Équipartition
nbpixels=hauteur*largeur
histogramme=numpy.zeros(256)
for i in range(hauteur):
    for j in range(largeur):
        histogramme[image[i][j]]+=1
seuil=0
nb=0
while nb<nbpixels//2:
    nb+=histogramme[seuil]
    seuil=seuil+1
print("seuil="+str(seuil))
image_equipart=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur):
        if image[i,j]<seuil:
            image_equipart[i][j]=0
        else:
            image_equipart[i][j]=255
plt.figure()
plt.imshow(image_equipart,cmap="gray")
plt.show()
### APPLICATION DE FILTRES SUR PLUSIEURS PIXELS ###

## Question 5 : Détection de contours
image_gradient_horizontal=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur-1):
        image_gradient_horizontal[i][j]=abs(image[i][j+1]-image[i][j])
plt.figure()
plt.imshow(image_gradient_horizontal,cmap="gray")
plt.show()
## Question 6 
import math
image_gradient=numpy.zeros([hauteur,largeur])
for i in range(hauteur-1):
    for j in range(largeur-1):
        image_gradient[i][j]=math.sqrt((image[i][j+1]-image[i][j])**2+(image[i+1][j]-image[i][j])**2)
plt.figure()
plt.imshow(image_gradient,cmap="gray")
plt.show()
## Question 7 : Floutage par moyennage
image_flou=numpy.zeros([hauteur,largeur])
taille=3
for i in range(taille,hauteur-taille):
    for j in range(taille,largeur-taille):
        somme=0
        for ivoisin in range(i-taille,i+taille+1):
            for jvoisin in range(j-taille,j+taille+1):
                somme=somme+image[ivoisin,jvoisin]
        image_flou[i][j]=somme/(2*taille+1)**2
plt.figure()
plt.imshow(image_flou,cmap="gray")
plt.show()
## Question 8 : Floutage gaussien

## Question 9 
import scipy.ndimage
image_contour=image-scipy.ndimage.gaussian_filter(image,3)
plt.figure()
plt.imshow(image_contour,cmap="gray")
plt.show()
## Question 10 : Réduction du bruit
image_bruitee=image+numpy.random.normal(loc=0,scale=30,size=image.shape)
plt.figure()
plt.imshow(image_bruitee,cmap="gray")
plt.show()
image_mediane=numpy.zeros([hauteur,largeur])
taille=2
for i in range(taille,hauteur-taille):
    for j in range(taille,largeur-taille):
        pixels_voisins=[]
        for ivoisin in range(i-taille,i+taille+1):
            for jvoisin in range(j-taille,j+taille+1):
                pixels_voisins.append(image[ivoisin][jvoisin])
        image_mediane[i][j]=numpy.median(pixels_voisins)
plt.figure()
plt.imshow(image_mediane,cmap="gray")
plt.show()
### TRANSFORMATIONS GÉOMÉTRIQUES ###
## Question 11 : Extraction d'une sous-image
image_corps=numpy.zeros([94,139])
for i in range(94):
    for j in range(139):
        image_corps[i][j]=image[87+i][67+j]
plt.figure()
plt.imshow(image_corps,cmap="gray")
plt.show()
## Question 12 : Agrandissement
facteur=1.6
image_agrandie=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur):
        x=int(j/facteur)
        y=int(i/facteur)
        image_agrandie[i][j]=image[y][x]
plt.figure()
plt.imshow(image_agrandie,cmap="gray")
plt.show()
## Question 13 : Rétrécissement
facteur=0.7
image_reduite=numpy.zeros([hauteur,largeur])
for i in range(hauteur):
    for j in range(largeur):
        x=int(j/facteur)
        y=int(i/facteur)
        if x<largeur-1 and y<hauteur-1:
            image_reduite[i][j]=image[y][x]
plt.figure()
plt.imshow(image_reduite,cmap="gray")
plt.show()
## Question 14 : Rotation de 90°
image_tourne90=numpy.zeros([largeur,hauteur])
for i in range(largeur):
    for j in range(hauteur):
        image_tourne90[i][j]=image[j][largeur-1-i]
plt.figure()
plt.imshow(image_tourne90,cmap="gray")
plt.show()
## Question 15 : Rotation quelconque
import math
image_tourne=numpy.zeros([hauteur,largeur])
angle=30*math.pi/180 # en radians
for i in range(hauteur):
    for j in range(largeur):
        x=int(j*math.cos(angle)-i*math.sin(angle))
        y=int(i*math.cos(angle)+j*math.sin(angle))
        if (x>0 and x<largeur-1 and y>0 and y<hauteur-1):
            image_tourne[i][j]=image[y][x]
plt.figure()
plt.imshow(image_tourne,cmap="gray")
plt.show()
### RECADRAGE INTELLIGENT ###


## Question 16 
def energie_pixel(img,i,j):
    return numpy.sqrt((img[i][j+1]-img[i][j-1])**2+(img[i+1][j]-img[i-1][j])**2)
## Question 17 
def cherche_chemin(img,i0):
    hauteur,largeur=img.shape
    liste=[i0]
    i=i0
    e=0
    for j in range(1,largeur-1):
        e1=+float("inf")
        if i>1:
            e1=energie_pixel(img,i-1,j)
        e2=energie_pixel(img,i,j)
        e3=+float("inf")
        if i<hauteur-2:
            e3=energie_pixel(img,i+1,j)
        if e2<=e1 and e2<=e3:
            e=e+e2
        elif e1<=e3:
            i=i-1
            e=e+e1
        else:
            i=i+1
            e=e+e1
        liste.append(i)
    liste.append(i)
    return (liste,e)


## Question 18 
def meilleur_chemin(img):
    hauteur,largeur=img.shape
    imin=0
    emin=float("inf")
    cmin=[]
    for i in range(2,hauteur-2):
        c,e=cherche_chemin(img,i)
        if e<emin:
            imin=i
            emin=e
            cmin=c
    return cmin,emin

## Question 19 
def enleve_une_ligne(img):
    hauteur,largeur=img.shape
    img2=numpy.zeros([hauteur-1,largeur])
    chemin,energie=meilleur_chemin(img)
    for j in range(largeur):
        ic=chemin[j]
        for i in range(0,ic):
            img2[i,j]=img[i,j]
        for i in range(ic,hauteur-1):
            img2[i,j]=img[i+1,j]
    return img2
image2=enleve_une_ligne(image)
plt.figure()
plt.imshow(image2,cmap="gray")
plt.show()
## Question 20 
def enleve_des_lignes(img,n):
    img2=img.copy()
    for i in range(n):
        img2=enleve_une_ligne(img2)
    return img2
image2=enleve_des_lignes(image,79)
plt.figure()
plt.imshow(image2,cmap="gray")
plt.show()


image2=numpy.asarray(Image.open("paysage4.jpg"),dtype="int")
hauteur,largeur=image.shape
plt.figure()
plt.imshow(image2,cmap="gray")
plt.show()
image2r=enleve_des_colonnes(image2,80)
plt.figure()
plt.imshow(image2r,cmap="gray")
plt.show()
### DÉTECTION DE FORMES ###

## Question 21 
import matplotlib.pyplot as plt
import numpy
from PIL import Image
image=numpy.asarray(Image.open("rubik.png").convert("L"),dtype="int")
plt.figure()
plt.imshow(image,cmap="gray")
plt.show()
## Question 22 
import numpy
import math
gradient=numpy.zeros(image.shape)
for i in range(image.shape[0]-1):
    for j in range(image.shape[1]-1):
        gradient[i][j]=math.sqrt((image[i+1][j]-image[i][j])**2+(image[i][j+1]-image[i][j])**2)
plt.figure()
plt.imshow(gradient,cmap="gray")
plt.show()
## Question 23 
rmax=int(math.sqrt(image.shape[0]**2+image.shape[1]**2))+1
accumulateur=numpy.zeros((rmax,rmax))
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        for k in range(rmax):
            angle=2*math.pi*k/rmax
            r=int(round(i*math.cos(angle)+j*math.sin(angle)))
            if r>0:
                accumulateur[k][r]+=gradient[i][j]
## Question 24 
kmaxi,rmaxi=0,0
for k in range(rmax):
    for r in range(rmax):
        if accumulateur[k,r]>accumulateur[kmaxi,rmaxi]:
            kmaxi,rmaxi=k,r
thetamaxi=2*math.pi*kmaxi/rmax
plt.figure()
plt.imshow(image,cmap="gray")
plt.plot([0,image.shape[1]-1],[rmaxi/math.cos(thetamaxi),rmaxi/math.cos(thetamaxi)-image.shape[1]*math.tan(thetamaxi)],color="red")
plt.ylim([image.shape[0],0])
plt.show()
## Question 25 
listetheta,lister=[],[]
voisinage=5
ndroites=10
accumulateur2=accumulateur.copy()
for d in range(ndroites):
    kmaxi,rmaxi=0,0
    for k in range(rmax):
        for r in range(rmax):
            if accumulateur2[k][r]>accumulateur2[kmaxi][rmaxi]:
                kmaxi,rmaxi=k,r
    thetamaxi=2*math.pi*kmaxi/rmax
    listetheta.append(thetamaxi)
    lister.append(rmaxi)
    accumulateur2[kmaxi-voisinage:kmaxi+voisinage+1,rmaxi-voisinage:rmaxi+voisinage+1]=0
print(listetheta,lister)
plt.figure()
plt.imshow(image,cmap="gray")
for d in range(ndroites):
    plt.plot([0,image.shape[1]-1],[lister[d]/math.cos(listetheta[d]),lister[d]/math.cos(listetheta[d])-image.shape[1]*math.tan(listetheta[d])],color="red")
plt.ylim([image.shape[0],0])
plt.show()

