# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# +
import sys
import os
import numpy as np
import glob
import pickle

import cv2
from PIL import Image
from scipy.stats import kendalltau

from tqdm.contrib.concurrent import process_map
from tqdm import notebook
# -

# # Declare Vars & Load Data

# +
#### Important variables

number_of_images = 588
number_of_objects = 2434
main_path = "./SalMoN_Dataset/" ## Dataset folder

#### Multi-core processing parameters

max_workers = 4
chunksize = 32

#### Load important data

with open(os.path.join(main_path, "object_saliencies.pkl"), "rb") as fid:
    object_saliencies = pickle.load(fid)
    
with open(os.path.join(main_path, "object_counts.pkl"), "rb") as fid:
    object_counts = pickle.load(fid)
    
object_offsets = np.cumsum(object_counts[:-1])
object_offsets = np.concatenate([np.zeros((1), dtype=int), object_offsets])
# -

# # Load Saliency Maps Results for a Method

results_folder = "example_results"


# +
def shrink_image(image):
    image = cv2.resize(image, dsize=None, fx=.1, fy=.1, interpolation=cv2.INTER_AREA)
    return image

def load_image(path, shrink=False):
    saliency_map = np.array(Image.open(path))
    if shrink:
        saliency_map = shrink_image(saliency_map)
    return saliency_map

def load_maps(image_index):
    saliency_map_path = os.path.join(main_path, results_folder, f"{image_index+1:04d}.png")
    saliency_map = load_image(saliency_map_path, shrink=False)
    return saliency_map

saliency_maps = process_map(
    load_maps,
    range(number_of_images),
    max_workers=max_workers,
    chunksize=chunksize,
)


# -

# # Calculate Precision, Recall, AUC

# +
def get_auc(sorted_targets, eps=1e-8):
    
    fn = np.cumsum(sorted_targets)
    tp = fn.max() - fn

    fp = np.cumsum(1 - sorted_targets[::-1])[::-1]

    precision = tp / (tp + fp + eps)
    recall = tp / (tp + fn + eps)
    
    auc = abs(np.trapz(precision, recall))
    
    return auc

def calculate_metrics(name, ix, obj_number):
    
    path = os.path.join(main_path, name, f"{obj_number}.png")
    smap = load_image(path, shrink=True)

    smap = np.uint8(smap > 0)
    smap = smap.reshape((-1))

    sorted_targets = smap[ix]
    
    return get_auc(sorted_targets)

def process(image_index):
    
    saliency_map = shrink_image(saliency_maps[image_index])
    
    flat_saliency_map = saliency_map.reshape((-1))
    ix = np.argsort(flat_saliency_map)

    offset = object_offsets[image_index]

    F_aucs = []
    P_aucs = []
    R_aucs = []
    
    total_aucs = []

    for k in range(object_counts[image_index]):
        obj_number = offset + k + 1
        F_aucs.append(calculate_metrics("sortedObjectsEyeSaliency", ix, obj_number))
        P_aucs.append(calculate_metrics("sortedObjectsPointSaliency", ix, obj_number))
        R_aucs.append(calculate_metrics("sortedObjectsRectangleSaliency", ix, obj_number))
        
        maxi = max(F_aucs[-1], max(P_aucs[-1], R_aucs[-1]))
        total_aucs.append(maxi)
        
    result = {
        "eye_fixation_aucs": F_aucs,
        "point_clicking_aucs": P_aucs,
        "rectangle_drawing_aucs": R_aucs,
        "total_aucs": total_aucs
    }

    return result

results = process_map(
    process,
    range(number_of_images),
    max_workers=max_workers,
    chunksize=chunksize,
)

# +
flattened_results = {}

for result in results:
    for key in result:
        if key not in flattened_results:
            flattened_results[key] = []
        flattened_results[key] += result[key]
        
for key, value in flattened_results.items():
    print(f"{key}: {np.mean(value):.3f}")


# -

# # Calculate Object Saliency

# +
def calculate_saliency(i):
    
    estimated_saliency = []
    
    paths = sorted(glob.glob(os.path.join(main_path, "gtIndividualObjects", f"{i+1:04d}", "*.png")))
    
    for du in range(object_counts[i]):
        
        GT = np.array(Image.open(paths[du]))
        if len(GT.shape) > 2:
            GT = GT[:, :, 0] / 255.
        count = np.sum(GT)
        
        estimated_saliency.append(np.sum((saliency_maps[i] / 255.) * GT) / count)
        
    return estimated_saliency
        
estimated_saliency = process_map(
    calculate_saliency,
    range(number_of_images),
    max_workers=max_workers,
    chunksize=chunksize,
)
# -

estimated_saliency = [value for element in estimated_saliency for value in element]

# # Calculate Mean-Absolute Error

# +
EF_abs_diff = np.abs(object_saliencies["FixationSaliency"][:, 0] - estimated_saliency)
PC_abs_diff = np.abs(object_saliencies["PointSaliency"][:, 0] - estimated_saliency)
RD_abs_diff = np.abs(object_saliencies["RectangleSaliency"][:, 0] - estimated_saliency)

mini = np.minimum(EF_abs_diff, np.minimum(PC_abs_diff, RD_abs_diff))

MAE = {
    "Fixation": np.mean(EF_abs_diff),
    "Point": np.mean(PC_abs_diff),
    "Rectangle": np.mean(RD_abs_diff),
    "Total": np.mean(mini),
}

for key, value in MAE.items():
    print(f"{key}: {value:.3f}")
# -

# # Calculate Kendall's Tau

# +
FixationtauD = kendalltau(object_saliencies["FixationSaliency"], estimated_saliency)[0]
PointtauD = kendalltau(object_saliencies["PointSaliency"], estimated_saliency)[0]
RectangletauD = kendalltau(object_saliencies["RectangleSaliency"], estimated_saliency)[0]

Tau = {
    "Fixation": FixationtauD,
    "Point": PointtauD,
    "Rectangle": RectangletauD,
}

for key, value in Tau.items():
    print(f"{key}: {value:.3f}")
# -

# # Calculate Combined (over 3 Saliency Map) Kendall's Tau

# +
y, x = np.triu_indices(2434, k=1)

def get_value(symbol, name):
    
    efx = object_saliencies[name]
    efy = object_saliencies[name]
    
    if symbol == ">":
        ef = efx > efy.T
    elif symbol == "<":
        ef = efx < efy.T
    elif symbol == "==":
        ef = efx == efy.T
    elif symbol == "<=":
        ef = efx <= efy.T
    elif symbol == ">=":
        ef = efx >= efy.T
    elif symbol == "!=":
        ef = efx != efy.T

    ef = np.float32(ef)
    ef = ef[y, x]
    
    return ef

def get_comparison(symbol, direction):
    
    ef = get_value(symbol, "FixationSaliency")
    pc = get_value(symbol, "PointSaliency")
    rd = get_value(symbol, "RectangleSaliency")
    
    if direction == "max":
        return np.maximum(ef, np.maximum(pc, rd))
    elif direction == "min":
        return np.minimum(ef, np.minimum(pc, rd))

def get_estimated_comparison(symbol):
    
    efx = np.array(estimated_saliency).reshape((-1, 1))
    efy = np.array(estimated_saliency).reshape((-1, 1))
    
    if symbol == ">":
        val = efx > efy.T
    elif symbol == "<":
        val = efx < efy.T
    elif symbol == "==":
        val = efx == efy.T
        
    val = np.float32(val)
    val = val[y, x]
        
    return val

C = 0
D = 0

T_rho = 0
TR = 0
        
Gs_xgy = get_comparison(">", "max")
Gs_xly = get_comparison("<", "max")

E_xgy = get_estimated_comparison(">")
E_xly = get_estimated_comparison("<")

C = np.sum(Gs_xgy * E_xgy + Gs_xly * E_xly)

Gi_xley = get_comparison("<=", "min")
Gi_xgey = get_comparison(">=", "min")

D = np.sum(Gs_xly * Gi_xley * E_xgy) + np.sum(Gs_xgy * Gi_xgey * E_xly)

Gi_xey = get_comparison("==", "min")

T_rho = np.sum(Gi_xey * (E_xgy + E_xly))

Gs_xny = get_comparison("!=", "max")
E_xey = get_estimated_comparison("==")

TR = np.sum(Gs_xny * E_xey)
# -

combined_tau = (C - D) / np.sqrt((C + D + TR) * (C + D + T_rho))
combined_tau



StarcoderdataJupyterScriptsDedupFiltered