# -*- coding: utf-8 -*-
"""
Created on Thu Apr 24 12:20:31 2014

@author: denis
"""

import skimage.io as io
import numpy as np
import random as rd #Exercices : 1.6;
import matplotlib.pyplot as plt

js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')

"""Exercice 1"""
###Question 1
io.imsave('../ploum.jpg',js_image)
print(type(js_image))

###Question 2
print('forme de l\'image : '+str(js_image.shape))

###Question 3
lignes,colonnes=js_image.shape
io.imshow(js_image[:lignes//2,colonnes//2:])
io.show()

###Question 4
js_image[0,0]=255
io.imshow(js_image) #zoomer pour voir le pixel, sinon problèmes d'arrondis dans l'affichage
io.show()

###Question 5
js_image[100:lignes-100,100:110]=0
js_image[100:lignes-100,500:510]=0
js_image[100:110,100:500]=0
js_image[lignes-110:lignes-100,100:500]=0
io.imshow(js_image) 
io.show()

##Pauvre Jon Snow qui n'a rien demandé. On va reprendre une image non tagguée.
js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')
##Attention, on manipule des entiers, gag possible : 
##faire +10*i,+i n'est pas équivalent à +i,+i//10
##On peut aussi faire les calculs en flottant puis arrondir à la fin avec int()
for i in range(101):
    js_image[200+i,280+i//5]=255 
    js_image[300-i//10,300+i]=255
for i in range(121):
    js_image[200+(3*i)//4,280+i]=255
io.imshow(js_image) 
io.show()

###Question 6 (optionnelle) :
##randrange(n) : entier aléatoire entre 0 et n-1 :
image_aleatoire=np.array([[rd.randrange(256) for k in range(100)] for i in range(100)])
io.imshow(image_aleatoire) 
io.show()


"""Exercice 2"""
js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')
###Question 1 :
lignes,colonnes=js_image.shape
#for i in range(lignes):
#    for j in range(colonnes):
#        js_image[i,j]=255-js_image[i,j]
## A la numpy -- c'est beaucoup plus rapide. "255" représente la matrice avec des 255 partout :
js_image=255-js_image
io.imshow(js_image) 
io.show()

###Question 2 :
js_image=js_image.T
io.imshow(js_image) 
io.show()


###Question 3 (optionnelle) :
def rot_moins_90(image):
    image=image.T #On commence par transposer
    lignes,colonnes=image.shape    
    for i in range(lignes//2):
        image[i],image[lignes-i-1]=image[lignes-i-1].copy(),image[i].copy()
    return image
def rot_plus_90(image):
    image=image.T.copy() #On commence par transposer
    lignes,colonnes=image.shape    
    for i in range(colonnes//2):
        image[:,i],image[:,colonnes-i-1]=image[:,colonnes-i-1].copy(),image[:,i].copy()
    return image
def rot_plus_180(image): #Bon, on pouvait écrire rot_plus_90(rot_plus_90(image)) [je me suis retenu]
    lignes,colonnes=image.shape    
    for i in range(colonnes//2):
        image[:,i],image[:,colonnes-i-1]=image[:,colonnes-i-1].copy(),image[:,i].copy()
    for i in range(lignes//2):
        image[i],image[lignes-i-1]=image[lignes-i-1].copy(),image[i].copy()
    return image

js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')
js_image=rot_plus_90(js_image)
#js_image=rot_plus_180(js_image)
io.imshow(js_image) 
io.show()

"""Exercice 3"""
### Question 1:
print(len(js_image[js_image<26]))
print(len(js_image[js_image>(255-26)]))
### Question 2: Il y a une incohérence à régler.
N=10
L=[len(js_image[js_image<int(255./10)])]
for i in range(1,N):
    L.append(len(js_image[js_image<int(i*255./10)])-sum(L))
plt.scatter(range(N),L)
plt.show()    
##Plus simple :
lignes,colonnes=js_image.shape    
plt.hist(js_image.reshape(lignes*colonnes),N,normed='True')
plt.show()    

### Question 3:
#N=int(input('Rentrez N: '))

### Question 4:
js_bool=js_image>128
for i in range(lignes):
    for j in range(colonnes):
        if js_bool[i,j]:
            js_image[i,j]=255
        else:
            js_image[i,j]=0
io.imshow(js_image) 
io.show()
### Question 4:
js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')
"""L'idée est de faire une transformation qui laisse 0 et 255 fixe, 
mais qui pousse le reste vers 255. 
On peut faire une transformation affine par morceaux, 
ou plus proprement avec des puissances. On se ramène dans [0,1]"""
a=.2  #concave : on rapproche de 1.
for i in range(lignes):
    for j in range(colonnes):
        js_image[i,j]=int(((js_image[i,j]/255.)**a)*255)
##Mieux : réussir à utiliser map
io.imshow(js_image) 
io.show()


"""Exercice 4"""

N=100
n=10
perturbation=np.array([[rd.randrange(10) for k in range(N)] for kk in range(N)])
nouv_image=np.zeros((N,N))
for k in range(n):
    nouv_image[int(k*N/n)]=255
    nouv_image[:,int(k*N/n)]=255
nouv_image=255-nouv_image
io.imshow(nouv_image) 
io.show()
nouv_image=nouv_image+perturbation
io.imshow(nouv_image) 
io.show()

##Rmq : en fait, skimage réussi à manipuler aussi des float.
image_inv=np.linalg.inv(nouv_image)
def conversion_vers_int8(image):
    imax=np.max(image)
    imin=float(np.min(image))
    image=(image.copy()-imin)*255./(imax-imin) #Désormais image[i,j] est un float entre 0 et 255
    for i in range(lignes): #
        for j in range(colonnes):
            js_image[i,j]=int(js_image[i,j])

io.imshow(conversion_vers_int8(image_inv)) 
io.show()

"""Exercice 5"""
js_image=io.imread('../FichiersTP/TPImages/js_fichier.jpg')
def baisse_resolution(image): 
    lignes=image.shape[0]//2
    colonnes=image.shape[1]//2
    nouv_image=np.empty(lignes,colonnes)
    for i in range(lignes):
        for j in range(colonnes):
            nouv_image[i,j]=np.mean(image[2*i:2*i+2,2*j:2*j+2])
    return nouv_image

"""Le truc vicieux, ce sont les bords"""
def floutage(image): #plus propre : prendre p pixel autour de [i,j], et traîter les bords en conséquence
    lignes,colonnes=image.shape
    nouv_image=np.empty((lignes,colonnes))
    #Le cas général:
    for i in range(1,lignes-1):
        for j in range(1,colonnes-1):
            nouv_image[i,j]=np.mean(image[i-1:i+2,j-1:j+2])
    #Le cas des bords
    for i in range(1,lignes-1):
        nouv_image[i,0]=np.mean(image[i-1:i+2,0:2])
        nouv_image[i,colonnes-1]=np.mean(image[i-1:i+2,colonnes-2:colonnes])
    for j in range(1,colonnes-1):
        nouv_image[0,j]=np.mean(image[0:2,j-1:j+2,0:2])
        nouv_image[lignes-1,j]=np.mean(image[lignes-2:lignes,j-1:j+2])
    #Le cas des coins
    nouv_image[0,0]=sum(image[0:2,0:2])/4.        
    nouv_image[0,colonnes-1]=sum(image[0:2,colonnes-2:colonnes])/4.#a rectifier : avec np.mean   
    nouv_image[lignes-1,0]=sum(image[lignes-2:lignes,0:2])/4.        
    nouv_image[lignes-1,colonnes-1]=sum(image[lignes-2:lignes,colonnes-2:colonnes])/4.        
    return nouv_image
    
"""on peut tester plusieurs passages de la fonction, pour accentuer l'effet"""

"""Contours : ouh là ! Compliqué.
regarder l'écart à la moyenne du pixel central 
(dans le cas hors bord, évidemment, et avec 9 pixels). 
Si l'écart est grand, on est peut-être sur un bord. 
Noter les coordonnées des pixels "candidats" dans une liste. 
Ecarter les pixels isolés.
Une fois la liste trouvée, on peut essayer de renforcer les bords (l'inverse du floutage, en quelque sorte)
Cf le web pour des algos plus intelligents"""

"""Exercice 6"""
print('1) Une image couleur est un tableau de triplet [R,V,B], ce n\'est que de l\'adaptation.')

print('2) Chercher les pixels pas trop "loin" du bleu du fond, en mettant par exemple une distance du type')
print('sqrt((R-R0)^2+(V-V0)^2+(B-B0)^2) sur l\'espace des couleurs')
def distance_coul_pixel(a,b): #a et b sont des tableaux numpy de taille 3, contenant un pixel
    return np.sqrt(sum([(a[i]-b[i])**2 for i in range(3)]))

print('niveaux de gris : to do') 
