# Codi per TFG de informatica 17-18

#Inicial

import cv2
import dlib
import numpy as np

import math
import openface
import openface.helper
from openface.data import iterImgs

import sys
import os
import glob
import argparse
from PIL import Image as pilimage

from keras.models import load_model
from keras.preprocessing import image

import random
import time

# llibreries fetes per les funcions
import llibreries as lib
#from sklearn import datasets # ejemplos para datos

# Directorios para referencias
fileDir = os.path.dirname(os.path.realpath(__file__)) #localiza directorio  NOTA .- buscar funcion que encuentre ruta absoluta

dlibModelDir = os.path.join('.','models', 'dlib')
openfaceModelDir = os.path.join('.','models', 'openface')

#modelDir = os.path.join(fileDir, '..', 'models')
#dlibModelDir = os.path.join(modelDir, 'dlib')
#openfaceModelDir = os.path.join(modelDir, 'openface')

genderModelDir = './models/gender/simple_CNN.81-0.96.hdf5'


# Argumentos de entrada
parser = argparse.ArgumentParser(description='Runs face detection on a folder of images.')
parser.add_argument('-input_path', type=str,
                   help='path where the input images are stored',
                   default = None)
parser.add_argument('-output_path', type=str,
                   help='path where the result is stored',
                   default='')
parser.add_argument('-data_path', type=str,
                   help='path where the data is clustening',
                   default='./data')

parser.add_argument('-factor_scale', type=str, help="Escala del factor de busqueda",
                default=1.2)
parser.add_argument('-min_neighbors', type=str, help="Veins minimos",
                default=0)
parser.add_argument('-min_size', type=int, help="Tamany minim en pixels de la cara",
                default=-1)
parser.add_argument('-max_size', type=int, help="Tamany maxim en pixels de la cara",
                default=-1)

parser.add_argument('-haarcascades', type=str, help="fitxers xml per a filtre haar",
                #default=['haarcascades/haarcascade_frontalface_alt2.xml', 'haarcascades/haarcascade_profileface.xml','haarcascade_frontalface_alt.xml','haarcascade_frontalcatface.xml'])
                default=['haarcascades/haarcascade_frontalface_alt2.xml', 'haarcascades/haarcascade_profileface.xml'])

parser.add_argument('-model_predictor', type=str, help="landmarks del modelo predictivo para detectar caras",
                default=os.path.join(dlibModelDir, "shape_predictor_68_face_landmarks.dat"))
parser.add_argument('-neuronal_net', type=str, help="modelo de red neuronal",
                default=os.path.join(openfaceModelDir, 'nn4.small2.v1.t7'))
parser.add_argument('-img_size', type=str, help="Dimension para analizar las referencias default 96x96",
                default=96)

parser.add_argument('-option', type=str, help="Opcio desitjada a realitzar",
                default='all')
parser.add_argument('-image', type=str, help="directori i nom del fitxe a llegir")

parser.add_argument('-extensions', type=str, help="extensions que es volen comprovar",
                default=['*.jpg','*.jpeg','*.png'])
parser.add_argument('-type_vector', type=str, help="Tipus de vector que utilitzara per agrupar i classificar",
                default='face') # Tipus -> ('face','face-clothes')

parser.add_argument('-level_blur', type=str, help="Nivel de distorsion de la cara entre 0.0 a 1.0",
                default=0.3)

parser.add_argument('-corte_affinity', type=str, help="Valor del tall per descartar cares per mitja de Pearson",
                default = 0.70)
parser.add_argument('-corte_clothes', type=str, help="Valor del tall descartar imatges amb roba diferent per mitja de bhattacharyya",
                default = None )#0.35)

parser.add_argument('-skin', type=str, help="Valor True/False per si es treu o no la pell",
                default = False)

parser.add_argument('-corte_jer', type=float, help="Valor del tall per agrupament Jerarquic default None, sense tall",
                default = None)
parser.add_argument('-metode', type=str, help="metode d'agrupament jerarquic que s'aplica",
                default='average;average')

parser.add_argument('-aviso', type=str, help="Per mostrar avisos per pantalla",
                default=True)

parser.add_argument('-bd_faces', type=str, help="Directori dels fitxers amb vectors de diferentes cares",
                default='./BD')
parser.add_argument('-name_face', type=str, help="nom de la cara que es vols vetoritzar i guardar")

parser.add_argument('-file_test', type=str, help="Fitxer amb les dades de les imatges",
                default='./test/locFaces.txt')


args = parser.parse_args()

#variables con los modelos predictivos y entrenados asignados por defecto

align = openface.AlignDlib(args.model_predictor)
net = openface.TorchNeuralNet(args.neuronal_net, int(args.img_size))
gender_classifier = load_model(genderModelDir, compile=False)

# Revisio de les varaibles de entrada
if args.corte_affinity == 'None':
    args.corte_affinity = None
    
if args.corte_clothes == 'None':
    args.corte_clothes = None

# Controlar que sempre hi hagi directori de input
if not args.option in ['report-clusters', 'blur_image', 'clip_image']:    
    if args.input_path is None:
        sys.stdout.write("\x1B[33m") # Canvia de color
        print 'Falta introduir directori en el parametre -input_path'
        sys.stdout.write("\x1B[37m") 
        sys.exit(0)
    else:
        if not os.path.exists(args.input_path):
            sys.stdout.write("\x1B[33m") # Canvia de color
            print 'Directori introduit en - input_path --> ' + args.input_path + ' : Inexistent'
            sys.stdout.write("\x1B[37m") 
            sys.exit(0)

# Comprovar entrada del tipus de vector per analitzar
if not args.type_vector in ['face','face-clothes']:
    sys.stdout.write("\x1B[33m") # Canvia de color
    print 'Tipus de vector mal definit utilitzar --> - type_vector < face , face-clothes >'
    sys.stdout.write("\x1B[37m") 
    sys.exit(0)

def main(args):
    #opcions del programa
    opn = ('all','clip_image','vectors','vector_face','clip','blur','blur_image',
           'vectors-meanshift', 'vectors-spectral',
           'test', 'test-meanshift','test-spectral',
           'test-complet', 'test-complet-meanshift','test-complet-spectral',
           'report-clusters')
    
    if args.option in opn:
        
        # si el valor de pixels veins es 0 vol dir que no s'ha entrat posant un per defecte
        if args.min_neighbors == 0:
            if str(args.option).startswith('clip') or str(args.option).find('all') != -1: 
                args.min_neighbors = 5 # Per fer una cerca d'una cara amb detalls
            else:
                args.min_neighbors = 1 #Per simplement buscar totes les cares possibles cara
                
        # Si no hi ha filtres assignats vol dir que no s'ha entrat posant un per defecte
        if args.haarcascades == '':
            if str(args.option).find('clip') != -1 or str(args.option).find('all') != -1: 
                args.haarcascades = ['haarcascades/haarcascade_frontalface_alt2.xml', 'haarcascades/haarcascade_profileface.xml'] # Per fer una cerca d'una cara amb detalls pel vector
            else:
                args.haarcascades = ['haarcascades/haarcascade_frontalface_alt2.xml', 'haarcascades/haarcascade_profileface.xml','haarcascade_frontalface_alt.xml'] #Per simplement buscar el major numero de cares
    
        # Opcio completa de tot el proces
        if args.option == 'all':
            if args.input_path != '' and args.output_path != '':
                start_ini = time.time()
                #Es poden indicare diferents filtres haar amb les opcions, aixi com diferents parametres            
                lib.findFaces.extractFaces(args.input_path, args.output_path, scale_factor=float(args.factor_scale), min_neighbors=int(args.min_neighbors),
                                           min_size=args.min_size, max_size=args.max_size, exts=args.extensions,
                                           flags=cv2.CASCADE_SCALE_IMAGE, face_cascade_paths=args.haarcascades, 
                                           aviso=args.aviso) # Obtener las imagenes
                

                #Extreure els vectors de les cares
                # Sortida [reps,errors] reps conte els objectes amb totes les dades de la imatge
                valores = lib.vecFace.extractVectors(args.output_path, align, net, gender_classifier, args = args, imgDim=int(args.img_size), aviso = args.aviso)
                values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]], [x.getVecClothes() for x in valores[0]], [x.getVecFaceClothes() for x in valores[0]]]
                
                # Seleccionar el tipus de vector per agrupar
                if args.type_vector == 'face':
                    dades = values[0]
                if args.type_vector == 'face-clothes':
                    dades = values[3]
                    
                # Classificacio per mitja de clustening
                clusters = lib.classi.procesJerCom(data = dades, labels = values[1], obj_images = valores[0], args = args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                #clusters['valores'] = [x for x in valores[0] if x.getPath() in clusters['images'][0]]

                
                #Guardar amb ids les persones
                if not os.path.exists(args.data_path):
                    os.mkdir(args.data_path)                
                lib.classi.saveImg(clusters,args.data_path, args = args)
                
                #Realitzar mitjes dels clusters
                print str(clusters['images'])
                lib.utils.mitjaClusters(args.data_path)
 
                
                # Guardar imatges descartades
                if len(clusters['descarts']) > 0:
                    lib.utils.moveImg([clusters['descarts']],os.path.join(args.data_path,'_descarts'))
                
                
                if len(valores[1]) > 0:
                    if args.aviso:
                        print "Imatges amb errors en el proces per obtenir vector: " + str(len(valores[1]))
                        #print "Imatges amb errors en el proces per obtenir vector dels Homes: " + str(len(valuesMen[1]))
                    lib.utils.moveImg([valores[1]],os.path.join(args.data_path,'_errors'))
                else:
                    if args.aviso:
                        print "Imatges processades sense errors"
 
                if args.aviso:
                    print("Temps Total: {} seconds.".format(time.time() - start_ini))
            else:
                print 'Falta directori entrada i/o sortida'
                
        # sols retalla les imatges i guarda els retalls de les cares    
        if args.option == 'clip':
            if args.input_path != '' and args.output_path != '':
                start = time.time()
                lib.findFaces.extractFaces(args.input_path, args.output_path, scale_factor=float(args.factor_scale), min_neighbors=int(args.min_neighbors),
                                           min_size=args.min_size, max_size=args.max_size, exts=args.extensions,
                                           flags=cv2.CASCADE_SCALE_IMAGE, face_cascade_paths=args.haarcascades, 
                                           aviso=args.aviso) # Obtener las imagenes
                
                print "S'han Obtingut " + str(len(glob.glob(args.output_path+'/*.png'))) + " Cara(es)"
                if args.aviso:
                    print("Temps transcurregut per localitzar i retallar les cares: {} seconds.".format(time.time() - start))
            else:
                print 'Falta directori entrada i/o sortida'
          
        # Sols retalla les cares de una imatge pel que el valor d'entrada es una imatge
        if args.option == 'clip_image':
            if args.image is not None and args.output_path != '':
                start = time.time()
                #Es poden indicare diferents filtres haar amb les opcions, aixi com diferents parametres            
                lib.findFaces.imageFaces(args.image,args.output_path, None, args.haarcascades ,scale_factor=float(args.factor_scale),min_neighbors=int(args.min_neighbors), exts=args.extensions,flags=cv2.CASCADE_SCALE_IMAGE)
                if args.aviso:
                    print("Temps transcurregut per localitzar i retallar les cares: {} seconds.".format(time.time() - start))
            else:
                print "Falta argument -image << .../directori/imatge.jpg >> i/o directori de sortida"  
          
          
        # sols retalla les imatges i guarda els retalls de les cares    
        if args.option == 'blur':
            start = time.time()
            lib.findFaces.smoothFaces(args.input_path,args.output_path,blur_lvl = float(args.level_blur),scale_factor = float(args.factor_scale),
                                      face_cascade_paths = args.haarcascades, min_size = args.min_size, max_size = args.max_size,
                                      exts=args.extensions,min_neighbors=int(args.min_neighbors))
            
            if args.aviso:
                    print("Temps transcurregut per distorsionar les cares: {} seconds.".format(time.time() - start))
            
            images =[]
            for ext in args.extensions:    
                images.extend(glob.glob(args.output_path+'/'+ext))
            
            num = 0
            for nfaces in images:
                num += int(nfaces.split('/')[-1].split('.')[0].split('-')[-1])
            
            if args.aviso:
                print "S'han distorsionat " + str(num) + " Cara(es)"
        
        # Distorsionar les cares d'una solo fotografia
        if args.option == 'blur_image':
            if args.image is not None:
                lib.findFaces.imageSmooth(args.image,args.output_path, blur_lvl=float(args.level_blur),scale_factor=float(args.factor_scale),
                                          min_size=args.min_size, max_size=args.max_size,
                                          face_cascade_paths=args.haarcascades, 
                                          exts=args.extensions,
                                          min_neighbors=int(args.min_neighbors))
            else:
                print "Falta argument -image << .../directori/imatge.jpg >>"
         
        if args.option == 'vector_face':
            if args.name_face != '':
                lib.vecFace.saveRepsFace(inputDir = args.input_path, bdDir = args.bd_faces , nameFace = args.name_face , align = align , net = net, imgDim = int(args.img_size), aviso = args.aviso, tipo = args.type_vector)
            else:
                print "No ha indicat el nom del candidat a vetoritzar les seves imatges"
        
        # Comprova els vectors de cares ja retallades i realitza agrupament jerarquic
        # Crear tabla de proximidad en metodos --> single complete weighted centroid median ward
        if args.option == 'vectors':
            #Verificar que existeix el directori amb les imatges
            if os.path.exists(args.input_path):
            
                #Extreure els vectors de les cares
                # Sortida [reps,errors] reps conte els objectes amb totes les dades de la imatge
                valores = lib.vecFace.extractVectors(args.input_path, align, net, gender_classifier, args = args, imgDim=int(args.img_size), aviso = args.aviso)
                values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]], [x.getVecClothes() for x in valores[0]], [x.getVecFaceClothes() for x in valores[0]]]
                
                # Seleccionar el tipus de vector per agrupar
                if args.type_vector == 'face':
                    dades = values[0]
                if args.type_vector == 'face-clothes':
                    dades = values[3]
                    
                # Classificacio per mitja de clustening
                clusters = lib.classi.procesJerCom(data = dades, labels = values[1], obj_images = valores[0], args = args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                #clusters['valores'] = [x for x in valores[0] if x.getPath() in clusters['images'][0]]

                # Guardar els grups a directori
                #print str(clusters['images'])
                #lib.utils.moveImg(clusters['images'],'./data')
                #lib.utils.moveImg(lib.cluster.unirClusters(agrupRep,agrupacio, 0.45)[1],'./data')
                
                #Guardar amb ids les persones
                if not os.path.exists(args.data_path):
                    os.mkdir(args.data_path)                
                lib.classi.saveImg(clusters,args.data_path, args = args)
                
                #Realitzar mitjes dels clusters
                print str(clusters['images'])
                lib.utils.mitjaClusters(args.data_path)
                
                #if not os.path.exists('./data/'+lib.gd.gender_dict[1]):
                #    os.mkdir('./data/'+lib.gd.gender_dict[1])                
                #lib.classi.saveImg(clustersM,'./data/'+lib.gd.gender_dict[1])
                
                # Guardar imatges descartades
                if len(clusters['descarts']) > 0:
                    lib.utils.moveImg([clusters['descarts']],os.path.join(args.data_path,'_descarts'))
                
                
                if len(valores[1]) > 0:
                    if args.aviso:
                        print "Imatges amb errors en el proces per obtenir vector: " + str(len(valores[1]))
                        #print "Imatges amb errors en el proces per obtenir vector dels Homes: " + str(len(valuesMen[1]))
                    lib.utils.moveImg([valores[1]],os.path.join(args.data_path,'_errors'))
                else:
                    if args.aviso:
                        print "Imatges processades sense errors"
            else:
                print 'Directori ' + args.input_path + ' inexistent'
 
        if args.option == 'vectors-meanshift':
            if os.path.exists(args.input_path):
                #Sortida [reps,errors] reps conte els objectes amb totes les dades de la imatge
                valores = lib.vecFace.extractVectors(args.input_path, align, net, gender_classifier, args = args, imgDim=int(args.img_size), aviso = args.aviso)
                values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]], [x.getVecClothes() for x in valores[0]], [x.getVecFaceClothes() for x in valores[0]]]
                #values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]]]
                
                # Seleccionar el tipus de vector per agrupar
                if args.type_vector == 'face':
                    dades = values[0]
                if args.type_vector == 'face-clothes':
                    dades = values[3]
                
                #Organitzar segons meanShift
                clusters = lib.classi.procesAgrupament(dades,values[1], tipus = 'meanshift', args = args)
                #clusters = lib.cluster.clusterMeanShift(values[0],values[1])
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['valores'] = [x for x in valores[0]]
                
                #Guardar amb ids les persones
                if not os.path.exists(args.data_path):
                    os.mkdir(args.data_path)                
                lib.classi.saveImg(clusters,args.data_path, args = args)
                
                #Realitzar mitjes dels clusters
                lib.utils.mitjaClusters(args.data_path)
                
                # Guardar imatges descartades
                if len(clusters['descarts']) > 0:
                    lib.utils.moveImg([clusters['descarts']],os.path.join(args.data_path,'_descarts'))
                
                if len(valores[1]) > 0:
                    if args.aviso:
                        print "Imatges amb errors en el proces per obtenir vector: " + str(len(valores[1]))
                        #print "Imatges amb errors en el proces per obtenir vector dels Homes: " + str(len(valuesMen[1]))
                    lib.utils.moveImg([valores[1]],os.path.join(args.data_path,'_errors'))
                else:
                    if args.aviso:
                        print "Imatges processades sense errors"
            else:
                print 'Directori '+ args.input_path + ' inexistent'
                
        if args.option == 'vectors-spectral': 
            if os.path.exists(args.input_path):
                #Sortida [reps,errors] reps conte els objectes amb totes les dades de la imatge
                valores = lib.vecFace.extractVectors(args.input_path, align, net, gender_classifier, args = args, imgDim=int(args.img_size), aviso = args.aviso)
                values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]], [x.getVecClothes() for x in valores[0]], [x.getVecFaceClothes() for x in valores[0]]]
                #values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]]]
                
                # Seleccionar el tipus de vector per agrupar
                if args.type_vector == 'face':
                    dades = values[0]
                if args.type_vector == 'face-clothes':
                    dades = values[3]
                
                #Organitzar segons Spectal Clustering
                clusters = lib.classi.procesAgrupament(dades,values[1], tipus = 'spectral', args = args)
                #clusters = lib.cluster.clusterSpectral(values[0],values[1],args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['valores'] = [x for x in valores[0]]
                
                #Guardar amb ids les persones
                if not os.path.exists(args.data_path):
                    os.mkdir(args.data_path)                
                lib.classi.saveImg(clusters,args.data_path)
                
                #Realitzar mitjes dels clusters
                lib.utils.mitjaClusters(args.data_path)
                
                # Guardar imatges descartades
                if len(clusters['descarts']) > 0:
                    lib.utils.moveImg([clusters['descarts']],os.path.join(args.data_path,'_descarts'))
                
                if len(valores[1]) > 0:
                    if args.aviso:
                        print "Imatges amb errors en el proces per obtenir vector: " + str(len(valores[1]))
                        #print "Imatges amb errors en el proces per obtenir vector dels Homes: " + str(len(valuesMen[1]))
                    lib.utils.moveImg([valores[1]],os.path.join(args.data_path,'_errors'))
                else:
                    if args.aviso:
                        print "Imatges processades sense errors"
            else:
                print 'Directori '+ args.input_path + ' inexistent'
                
        if args.option.startswith('test'):
            
            if not os.path.exists(args.file_test):
                print 'No esta indicat o no existeix el fitxer amb la verificacio del test --> -file_test <./directori/arxiu.txt>'
                sys.exit(0)
            
            lib.test.testViola(args.input_path, args.output_path, args.file_test)
            
            valores = lib.vecFace.extractVectors(args.output_path, align, net, gender_classifier, args = args, imgDim = int(args.img_size), aviso = args.aviso)
            values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]], [x.getVecClothes() for x in valores[0]], [x.getVecFaceClothes() for x in valores[0]]]
            #values =[[x.getVecFace() for x in valores[0]],[x.getPath() for x in valores[0]],[x.getVecFaceClothes() for x in valores[0]]]
            
            # Seleccionar el tipus de vector per agrupar
            if args.type_vector == 'face':
                dades = values[0]
            if args.type_vector == 'face-clothes':
                dades = values[3]
            
            #Seleccionar el tipos de test
            tipo = args.option.split('-')[-1]
            if tipo == 'test':
                pantalla = tipo.replace('test','jerarquic')
            else:
                pantalla = tipo.replace('complet', 'jerarquic')
            
            if not args.option.startswith('test-complet'):
            
                # Generar els vectors per realitzar el test
                vecImgTest = lib.test.vecImagesTest(values[1], div = 5)
                vecRepsTest = lib.test.vecImagesTest(dades, div = 5)
                
                if not tipo in ['test','meanshift','spectral']: 
                    print 'Especificar agrupament correctament, utilitzar -> (test,test-meanshift o test-spectral)'
                    sys.exit(0)
                
                if args.aviso:
                    print '---> Agrupant per mitja de ' + pantalla.capitalize()
                
                # Sortida diccionaro amb keys ['images', 'reps', 'descarts', 'desReps', 'errors']
                if tipo == 'test':
                    clusters = lib.classi.procesJerCom(data = vecRepsTest['first'][0], labels = vecImgTest['first'][0], obj_images = valores[0], args = args)
                if tipo == 'meanshift':
                    clusters = lib.classi.procesAgrupament(vecRepsTest['first'][0],vecImgTest['first'][0], tipus = 'meanshift', args = args)
                    #clusters = lib.cluster.clusterMeanShift(vecRepsTest['first'][0],vecImgTest['first'][0])
                if tipo == 'spectral':
                    clusters = lib.classi.procesAgrupament(vecRepsTest['first'][0],vecImgTest['first'][0], tipus = 'spectral', args = args)
                    #clusters = lib.cluster.clusterSpectral(vecRepsTest['first'][0],vecImgTest['first'][0],args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['valores'] = [x for x in valores[0]]
                
                cv2.destroyAllWindows()
                
                saveData = lib.test.saveImgTest(clusters)
                lib.classi.saveImg(clusters,args.data_path, args = args)
                
                lib.test.testCross(saveData,args.input_path, args.file_test, args.bd_faces) # Es comprova el 75%

                if args.option == 'test':
                    clusters = lib.classi.procesJerCom(data = vecRepsTest['second'][0], labels = vecImgTest['second'][0], args = args)
                if args.option == 'test-meanshift':
                    clusters = lib.classi.procesAgrupament(vecRepsTest['second'][0],vecImgTest['second'][0], tipus = 'meanshift', args = args)
                if args.option == 'test-spectral':
                    clusters = lib.classi.procesAgrupament(vecRepsTest['second'][0],vecImgTest['second'][0], tipus = 'spectral', args = args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['valores'] = [x for x in valores[0]]
                
                saveData = lib.test.saveImgTest(clusters,saveData)
                lib.classi.saveImg(clusters, args.data_path, args = args)
                
                lib.test.testCross(saveData,args.input_path, args.file_test, args.bd_faces) #Es comproba el 100%
                
            else:
                
                if not tipo in ['complet','meanshift','spectral']: 
                    print 'Especificar agrupament correctament, utilitzar -> (test-complet,test-complet-meanshift o test-complet-spectral)'
                    sys.exit(0)
                    
                if args.aviso:
                    print '---> Agrupant per mitja de ' + pantalla.capitalize()
                    
                # Sortida diccionaro amb keys ['images', 'reps', 'descarts', 'desReps', 'errors']
                if tipo == 'complet':
                    clusters = lib.classi.procesJerCom(data = dades, labels = values[1], obj_images = valores[0], args = args)
                if tipo == 'meanshift':
                    clusters = lib.classi.procesAgrupament(dades,values[1], tipus = 'meanshift', args = args)
                if tipo == 'spectral':
                    clusters = lib.classi.procesAgrupament(dades,values[1], tipus = 'spectral', args = args)
                
                clusters['sex'] = [[v.getSex() for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['clothes'] = [[v.getVecClothes()  for v in valores[0] for x in z  if v.getPath() == x] for z in clusters['images']]
                clusters['valores'] = [x for x in valores[0]]
                
                saveData = lib.test.saveImgTest(clusters)
                lib.classi.saveImg(clusters,args.data_path, args = args)
                
                # Guardar imatges descartades
                if len(clusters['descarts']) > 0:
                    lib.utils.moveImg([clusters['descarts']],os.path.join(args.data_path,'_descarts'))
                
                
                if len(valores[1]) > 0:
                    if args.aviso:
                        print "Imatges amb errors en el proces per obtenir vector: " + str(len(valores[1]))
                        #print "Imatges amb errors en el proces per obtenir vector dels Homes: " + str(len(valuesMen[1]))
                    lib.utils.moveImg([valores[1]],os.path.join(args.data_path,'_errors'))
                
                lib.test.testCross(saveData,args.input_path, args.file_test, args.bd_faces, grafic = False) # Es comprova el 100%
            
        if args.option == 'report-clusters':
            if os.path.exists(args.data_path):
                #llista de persones
                persones = lib.utils.llistaDir(args.data_path)
                #Means dels clusters
                repsMeans = lib.utils.readCsv(os.path.join(args.data_path,'means.csv'))
                
                #crear diaccionari amb els reps
                person_dict = {}
                for i in range(len(persones)):
                    person_dict[persones[i]] = repsMeans[i]
                    
                print 'Distancies entre els clusters:'
                print 'Ids de Persones ' + str(persones)
                print '-------------------------------------------------------------------------------------'
                    
                for i in range(1, len(persones)):
                    for j in range(0, i):
                        vec1 = person_dict[persones[i]]
                        vec2 = person_dict[persones[j]]  
                        
                        euclidia = lib.utils.euclidean(vec1,vec2)
                        pearson = lib.utils.pearson(vec1,vec2)
                        bhatt = lib.utils.bhattaNega(vec1,vec2) #Es suma 0.5 per tal que eliminar els valors negatius
                            
                        print 'Persona ' + persones[i] + ' amb ' + persones[j] + ' Euclidiana: ' + str(round(euclidia,3)) + ' Pearson: ' + str(round(pearson,3)) + ' bhattacharyya: ' + str(round(bhatt,3)) 
                
                #Grafica dels vectors caracteristics
                lib.reports.grafica(range(len(repsMeans[0])),repsMeans,etiquetes = persones)

            else:
                print 'Directori '+ args.input_path + ' inexistent'
        
    else:
        print "Unknow option -> Use < " + str(opn) + ">"

    print 'Proces Finalitzat'

    
## Ejecucion del programa              
main(args)

