#!/usr/bin/env python
"""

Determinación de la Vida Media del Muón

Este código muestra como es el proceso de datos de los Detectores Cherenkov de Agua para la determiación de la Vida Media del Muón.

Authors:
        Jenifer Ortega (EPN)

Supervisor:
        

Este código se desarrolló como parte del programa La-ConGa Physics, en el curso de Ciencia de datos.


"""
import numpy as np 
from PIL import Image
from matplotlib import pyplot as plt
import matplotlib.cm as cm
import cv2
from numpy import asarray
from matplotlib.pyplot import figure


def gra_umbral(path):
    '''Función que recibe la ruta de una imagen y retorna el histograma de los píxeles de la imagen y la 
    imagen en pantalla (original y escala de grises)
    path: direccion de la imagen
    '''
    # Leer la imagen y transformarla en escale de grises.
    img = cv2.imread(path)
    image = Image.open(path) # cargamos la imagen
    matriz = asarray(image) # abrimos la imagen en formato  numpy.ndarray
    b,g,r = cv2.split(img) # leer la imagen según GRB
    rgb_img = cv2.merge([r,g,b]) 
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # transformar la imagen en escala de grises
    
    # Gráficar la imágenes
    fig, (ax1, ax2) = plt.subplots(1,2, figsize=(12,4))
    ax1.set_title('Imagen original')
    ax1.imshow(matriz)
    ax2.set_title('Histograma de la intensidad de los píxeles')
    ax2.set_ylabel('Número de Píxeles')
    ax2.set_xlabel('Intesidad del píxel')
    ax2.hist(np.concatenate((gray), axis=0), bins=250)
    plt.show()

def thresh_norm(path, umbral):
    '''Función que divide a la imagen mediante THRESH_BINARY_INV por medio de un umbral , 
    path: direccion de la imagen
    umbral: valor del pixel para la divición
    '''
    img = cv2.imread(path)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    umbral = 160
    _, thresh = cv2.threshold(gray, umbral, 255, cv2.THRESH_BINARY)
    
    return thresh

def thresh_inv(path, umbral):
    '''Función que divide a la imagen mediante THRESH_BINARY_INV por medio de un umbral , 
    path: direccion de la imagen
    umbral: valor del pixel para la divición
    '''
    img = cv2.imread(path)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    umbral = 160
    _, thresh = cv2.threshold(gray, umbral, 255, cv2.THRESH_BINARY_INV)
    
    return thresh
    
def segmentar(path, thresh, distancia): 
    '''Función que realiza la segmentación  por watershed mediante marcadores, 
    path: direccion de la imagen
    thresh: imagen dividida mediante la funcion cv2.threshold.
    distancia: anchura de la zona que debe segmentarse deacuerdo al tamaño del objeto.
    '''
    img = cv2.imread(path)
    # calculo de marcadores 
    kernel = np.ones((1,1))
    opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN, kernel, iterations = 1) # operación mofológica
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE , kernel, iterations = 1) # operación mofológica

    kernel = np.ones((1,1),np.uint8)
    Mark_int = cv2.dilate(closing, kernel,iterations=1) # cálculo primer marcador
    Mark_int  = Mark_int.astype(np.uint8)
   
    dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3) # calculo de distancia en imágenes cerradas

    ret, Mark_fondo = cv2.threshold(dist_transform, distancia*dist_transform.max(),255,0) # calculos segundo marcador

    Mark_fondo = np.uint8(Mark_fondo) # convertimos al marcador a un formato compatible
    desconocido = cv2.subtract(Mark_int,Mark_fondo)

    closing = closing.astype(np.uint8) # convertimos al marcador a un formato compatible
    ret, markers = cv2.connectedComponents(closing)

    markers = markers+1

    # generamos la imagen que ingresará en el algoritmo watershed
    markers[desconocido == 255] = 0

    markers = cv2.watershed(img, markers)
    img[markers == -1] = [255,0,0]
    # Imagenes en pantalla
    fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(18,4))
    ax1.set_title('Imagen aplicada el umbral Normal')
    ax1.imshow(thresh,  'gray')
    
    ax2.set_title('Marcadores')
    ax2.imshow(desconocido, 'gray')
    
    ax3.set_title('Imagen segmentada')
    ax3.imshow(img, 'gray')
    
    plt.show()
    return img

def segmentar1(path, thresh, distancia): 
    '''Función que realiza la segmentación  por watershed mediante marcadores, 
    path: direccion de la imagen
    thresh: imagen dividida mediante la funcion cv2.threshold.
    distancia: anchura de la zona que debe segmentarse deacuerdo al tamaño del objeto.
    '''
    img = cv2.imread(path)
    # calculo de marcadores 
    kernel = np.ones((1,1))
    opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN, kernel, iterations = 1) # operación mofológica
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE , kernel, iterations = 1) # operación mofológica

    kernel = np.ones((1,1),np.uint8)
    Mark_int = cv2.dilate(closing, kernel,iterations=1) # cálculo primer marcador
    Mark_int  = Mark_int.astype(np.uint8)
   
    dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3) # calculo de distancia en imágenes cerradas

    ret, Mark_fondo = cv2.threshold(dist_transform, distancia*dist_transform.max(),255,0) # calculos segundo marcador

    Mark_fondo = np.uint8(Mark_fondo) # convertimos al marcador a un formato compatible
    desconocido = cv2.subtract(Mark_int,Mark_fondo)

    closing = closing.astype(np.uint8) # convertimos al marcador a un formato compatible
    ret, markers = cv2.connectedComponents(Mark_fondo)

    markers = markers+1

    # generamos la imagen que ingresará en el algoritmo watershed
    markers[desconocido == 255] = 0

    markers = cv2.watershed(img, markers)
    img[markers == -1] = [255,0,0]
    # Imagenes en pantalla
    fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(18,4))
    ax1.set_title('Imagen aplicada el umbral Normal')
    ax1.imshow(thresh,  'gray')
    
    ax2.set_title('Marcadores')
    ax2.imshow(desconocido, 'gray')
    
    ax3.set_title('Imagen segmentada')
    ax3.imshow(img, 'gray')
    
    plt.show()
    return img