"""!

@brief  Examples of usage and demonstration of abilities of Pulse Coupled Neural Network in image segmentation.

@authors Andrei Novikov (pyclustering@yandex.ru)
@date 2014-2020
@copyright BSD-3-Clause

"""
from PIL import Image

from pyclustering.utils import read_image, rgb2gray, draw_image_mask_segments

from pyclustering.nnet.pcnn import pcnn_network, pcnn_parameters, pcnn_visualizer
from pyclustering.nnet import *

from pyclustering.samples.definitions import IMAGE_SIMPLE_SAMPLES, IMAGE_MAP_SAMPLES, IMAGE_REAL_SAMPLES


def template_segmentation_image(image, parameters, simulation_time, brightness, scale_color=True, fastlinking=False,
                                show_spikes=False, ccore_flag=True):
    image_source = Image.open(image)
    image_size = image_source.size
    
    width = image_size[0]
    height = image_size[1]
    
    stimulus = read_image(image)
    stimulus = rgb2gray(stimulus)
    
    if brightness is not None:
        for pixel_index in range(len(stimulus)):
            if stimulus[pixel_index] < brightness:
                stimulus[pixel_index] = 1
            else:
                stimulus[pixel_index] = 0
    else:
        maximum_stimulus = float(max(stimulus))
        minimum_stimulus = float(min(stimulus))
        delta = maximum_stimulus - minimum_stimulus
        
        for pixel_index in range(len(stimulus)):
            if scale_color is True:
                stimulus[pixel_index] = 1.0 - ((float(stimulus[pixel_index]) - minimum_stimulus) / delta)
            else:
                stimulus[pixel_index] = float(stimulus[pixel_index]) / 255
    
    if parameters is None:
        parameters = pcnn_parameters()
    
        parameters.AF = 0.1
        parameters.AL = 0.1
        parameters.AT = 0.8
        parameters.VF = 1.0
        parameters.VL = 1.0
        parameters.VT = 30.0
        parameters.W = 1.0
        parameters.M = 1.0
        
        parameters.FAST_LINKING = fastlinking
    
    net = pcnn_network(len(stimulus), parameters, conn_type.GRID_EIGHT, height=height, width=width, ccore=ccore_flag)
    output_dynamic = net.simulate(simulation_time, stimulus)
    
    pcnn_visualizer.show_output_dynamic(output_dynamic)
    
    ensembles = output_dynamic.allocate_sync_ensembles()
    draw_image_mask_segments(image, ensembles)
    
    pcnn_visualizer.show_time_signal(output_dynamic)
    
    if show_spikes is True:
        spikes = output_dynamic.allocate_spike_ensembles()
        draw_image_mask_segments(image, spikes)
        
        pcnn_visualizer.animate_spike_ensembles(output_dynamic, image_size)


def segmentation_image_simple1():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE01, None, 47, 235)


def segmentation_image_simple2():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE02, None, 47, 235)


def segmentation_image_simple6():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE06, None, 47, 128)


def segmentation_image_black_thin_lines1():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_THIN_BLACK_LINES01, None, 47, 128)


def segmentation_image_black_thin_lines2():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_THIN_BLACK_LINES02, None, 47, 128)


def segmentation_image_black_thin_lines3():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_THIN_BLACK_LINES03, None, 47, 128)


def segmentation_gray_image_simple1():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE01, None, 47, None, True, False, True)


def segmentation_gray_image_simple5():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE05, None, 47, None, True, False, True)


def segmentation_gray_image_beach():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE_BEACH, None, 94, None, True, False, True)


def segmentation_gray_image_building():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE_BUILDING, None, 47, None, True, False, True)


def segmentation_fast_linking_image_beach():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE_BEACH, None, 47, None, False, True, True)


def segmentation_fast_linking_image_building():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE_BUILDING, None, 47, None, False, True, True)


def segmentation_fast_linking_image_fruits():
    template_segmentation_image(IMAGE_SIMPLE_SAMPLES.IMAGE_SIMPLE_FRUITS_SMALL, None, 47, None, False, True, True)


def segmentation_fast_linking_white_sea():
    template_segmentation_image(IMAGE_MAP_SAMPLES.IMAGE_WHITE_SEA_SMALL, None, 47, None, False, True, True)


def segmentation_fast_linking_nil():
    template_segmentation_image(IMAGE_MAP_SAMPLES.IMAGE_NILE_SMALL, None, 47, None, False, True, True)


def segmentation_fast_linking_field_flowers():
    parameters = pcnn_parameters()

    parameters.AF = 0.1
    parameters.AL = 0.1
    parameters.AT = 0.8
    parameters.VF = 1.0
    parameters.VL = 1.0
    parameters.VT = 80.0
    parameters.W = 1.0
    parameters.M = 1.0
    
    parameters.FAST_LINKING = True
    
    template_segmentation_image(IMAGE_REAL_SAMPLES.IMAGE_FIELD_FLOWER, parameters, 80, None, False, True, True)


# Examples of simple image segmentation
segmentation_image_simple1()
segmentation_image_simple2()
segmentation_image_simple6()

# Line allocation
segmentation_image_black_thin_lines1()
segmentation_image_black_thin_lines2()
segmentation_image_black_thin_lines3()

# More complex image segmentation examples
segmentation_gray_image_simple1()
segmentation_gray_image_simple5()
segmentation_gray_image_beach()
segmentation_gray_image_building()

# Fast linking usage examples
segmentation_fast_linking_image_beach()
segmentation_fast_linking_image_building()
segmentation_fast_linking_image_fruits()
segmentation_fast_linking_white_sea()
segmentation_fast_linking_nil()
segmentation_fast_linking_field_flowers()
