# Part D: Comparison of toroidal meniscus models with different profile shapes

## Introduction

So far all the capillary entry pressures for the percoaltion examples were calculated using the ``Standard`` physics model which is the ``Washburn`` model for straight walled capillary tubes. This has been shown to be a bad model for fibrous media where the walls of throats are converging and diverging. In the study [Capillary Hysteresis in Neutrally Wettable Fibrous Media: A Pore Network Study of a Fuel Cell Electrode](http://link.springer.com/10.1007/s11242-017-0973-2) percolation in fibrous media was simulated using a meniscus model that assumed the contrictions between fibers are similar to a toroid:

This model was first proposed by Purcell and treats the inner solid profile as a circle. As the fluid invades through the center of the torus the meniscus is pinned to the surface and the "effective" contact angle becomes influenced by the converging diverging geometry and is a function of the filling angle $\alpha$. The shape of the meniscus as the invading phase moves upwards through the torus with key model parameters is shown below.

Different intrinsic contact angles through invading phase are shown above: (a) 60$^\circ$, (b) 90$^\circ$ and (c) 120$^\circ$. All scenarios clearly show an inflection of the meniscus curvature signifying a switch in the sign of the capillary pressure from negative to positive. This inflection is predicted to occur for all contact angles by the model with varying filling angle. The capillary pressure can be shown to be:

$P_C = -2\sigma cos(\theta-\alpha))/(r+R(1-cos(\alpha))$

A consequence of the circular solid profile is that all fluid behaves as non-wetting fluid because $\alpha$ can range from -90$^\circ$ to 90$^\circ$ degrees and so even if $\theta$ is 0 then the meniscus is still pinned at zero capillary pressure at the very furthest part of the throat where the $\alpha$ is 90$^\circ$

Considering other shapes of solid profile this situation can be avoided. It will be shown by reformulating the Purcell model in a more general way that allows for a flexible defintion of the solid profile that filling angle can be limited to values below 90 and allow for spontaneous imbibition (percolation threshold below zero) of highly wetting fluids.

## Set up
We will set up a trivially small network with one throat to demonstrate the use of the meniscus model. Here we do the imports and define a few functions for plotting.

```python
import matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import sympy as syp
from sympy import lambdify, symbols
from sympy import atan as sym_atan
from sympy import cos as sym_cos
from sympy import sin as sym_sin
from sympy import sqrt as sym_sqrt
from sympy import pi as sym_pi
from ipywidgets import interact, fixed
from IPython.display import display
import warnings
np.random.seed(10)
warnings.simplefilter(action='ignore')
matplotlib.rcParams['figure.figsize'] = (5, 5)
```

```python
theta = 60
fiberRad = 5e-6
throatRad = 1e-5
max_bulge = 1e-5
```

Now we define our two pore network and add the meniscus model in several modes: 'max' returns the maximum pressure experienced by the meniscus as it transitions through the throat, i.e. the burst entry pressure. 'touch' is the pressure at which the meniscus has protruded past the throat center a distance defined by the 'touch_length' dictionary key. In network simulations this could be set to the pore_diameter. Finally the 'men' mode accepts a target_Pc parameter and returns all the mensicus information required for assessing cooperative filling or plotting.

```python
import openpnm as op
%config InlineBackend.figure_formats = ['svg']
import openpnm.models.physics as pm
net = op.network.Cubic(shape=[2, 1, 1], spacing=5e-5)
geo = op.geometry.SpheresAndCylinders(network=net,
                               pores=net.pores(),
                               throats=net.throats())
phase = op.phases.Water(network=net)
phase['pore.contact_angle'] = theta
phys = op.physics.Standard(network=net,
                           phase=phase,
                           geometry=geo)
geo['throat.diameter'] = throatRad*2
geo['throat.touch_length'] = max_bulge
```

We define a plotting function that uses the meniscus data:
$\alpha$ is filling angle as defined above,
$radius$ is the radius of curvature of the mensicus,
$center$ is the position of the centre of curvature relative to the throat center along the axis of the throat,
$\gamma$ is the angle between the throat axis and the line joining the meniscus center and meniscus contact point.

```python
def plot_meniscus(target_Pc, meniscus_model=None, ax=None):
    throatRad = geo['throat.diameter'][0]/2
    theta = np.deg2rad(phys['pore.contact_angle'][0])
    throat_a = phys['throat.scale_a']
    throat_b = phys['throat.scale_b']
    x_points = np.arange(-0.99, 0.99, 0.01)*throat_a
    if ax is None:
        fig, ax = plt.subplots()
    if meniscus_model.__name__ == 'purcell':
        # Parameters for plotting fibers
        x, R, rt, s, t = syp.symbols('x, R, rt, s, t')
        y = R*syp.sqrt(1- (x/R)**2)
        r = rt + (R-y)
        rx = syp.lambdify((x, R, rt), r, 'numpy')
        ax.plot(x_points, rx(x_points, fiberRad, throatRad), 'k-');
        ax.plot(x_points, -rx(x_points, fiberRad, throatRad), 'k-');
        phys.add_model(propname='throat.meniscus',
                       model=meniscus_model,
                       mode='men',
                       r_toroid=fiberRad,
                       target_Pc=target_Pc)
    elif meniscus_model.__name__ == 'sinusoidal':
        x, a, b, rt, sigma, theta = syp.symbols('x, a, b, rt, sigma, theta')
        y = (sym_cos(sym_pi*x/(2*a)))*b
        r = rt + (b-y)
        rx = lambdify((x, a, b, rt), r, 'numpy')
        ax.plot(x_points, rx(x_points, throat_a, throat_b, throatRad), 'k-');
        ax.plot(x_points, -rx(x_points, throat_a, throat_b, throatRad), 'k-');
        phys.add_model(propname='throat.meniscus',
                       model=meniscus_model,
                       mode='men',
                       r_toroid=fiberRad,
                       target_Pc=target_Pc)
    else:
        # General Ellipse
        x, a, b, rt, sigma, theta = syp.symbols('x, a, b, rt, sigma, theta')
        profile_equation = phys.models['throat.entry_pressure']['profile_equation']
        if profile_equation == 'elliptical':
            y = sym_sqrt(1 - (x/a)**2)*b
        elif profile_equation == 'sinusoidal':
            y = (sym_cos(sym_pi*x/(2*a)))*b
        r = rt + (b-y)
        rx = lambdify((x, a, b, rt), r, 'numpy')
        ax.plot(x_points, rx(x_points, throat_a, throat_b, throatRad), 'k-');
        ax.plot(x_points, -rx(x_points, throat_a, throat_b, throatRad), 'k-');
        phys.add_model(propname='throat.meniscus',
                       model=meniscus_model,
                       profile_equation=profile_equation,
                       mode='men',
                       target_Pc=target_Pc)
    men_data = {}
    men_data['alpha'] = phys['throat.meniscus.alpha']
    men_data['gamma'] = phys['throat.meniscus.gamma']
    men_data['radius'] = phys['throat.meniscus.radius']
    men_data['center'] = phys['throat.meniscus.center']
    arc_cen = men_data['center']
    arc_rad = men_data['radius']
    arc_angle = men_data['gamma']
    angles = np.linspace(-arc_angle, arc_angle, 100)
    arcx = arc_cen + arc_rad*np.cos(angles)
    arcy = arc_rad*np.sin(angles)
    ax.plot(arcx, arcy, 'b-')
    ax.scatter(phys['throat.meniscus.pos'], phys['throat.meniscus.rx']);
    ax.axis('equal')
    ax.ticklabel_format(style='sci', axis='both', scilimits=(-6,-6))
    return ax
```

# Circular (Purcell)

```python
circular_model = pm.meniscus.purcell

phys.add_model(propname='throat.max',
               model=circular_model,
               mode='max',
               r_toroid=fiberRad)
phys.add_model(propname='throat.touch',
               model=circular_model,
               mode='touch',
               r_toroid=fiberRad)
phys.add_model(propname='throat.meniscus',
               model=circular_model,
               mode='men',
               r_toroid=fiberRad,
               target_Pc=1000)
touch_Pc = phys['throat.touch'][0]
print('Pressure at maximum bulge', np.around(touch_Pc, 0))
max_Pc_circle = phys['throat.max'][0]
print('Circular profile critical entry pressure', np.around(max_Pc_circle, 0))
```

    Pressure at maximum bulge 7213.0
    Circular profile critical entry pressure 8165.0

We can see that the touch_Pc calculated earlier, corresponds with the tip of the meniscus exceeding the max_bulge parameter. Try changing this and re-running to see what happens.

```python
ax = plot_meniscus(target_Pc=touch_Pc, meniscus_model=circular_model)
ax.plot([max_bulge, max_bulge], [-throatRad, throatRad], 'r--');
```

    [<matplotlib.lines.Line2D at 0x7f1048c87d00>]

```python
ax = plot_meniscus(target_Pc=max_Pc_circle, meniscus_model=circular_model)
```

We can interact with the mensicus model by changing the target_Pc parameter.

```python
interact(plot_meniscus,
         target_Pc=(-2000, max_Pc_circle, 1),
         meniscus_model=fixed(circular_model),
         ax=fixed(None));
```

    interactive(children=(FloatSlider(value=3082.0, description='target_Pc', max=8165.324889242946, min=-2000.0, s…

    <function __main__.plot_meniscus(target_Pc, meniscus_model=None, ax=None)>

Here we can see that the critical entry pressure for the circular profile is positive, even though the intrinsic contact angle is highly non-wetting

# Sinusoidal

Now we can start to compare the different meniscus models:

```python
sinusoidal_model = pm.meniscus.sinusoidal
```

```python
display(sinusoidal_model)
```

    <function openpnm.models.physics.meniscus.sinusoidal(target, mode='max', target_Pc=None, num_points=1000.0, r_toroid=5e-06, throat_diameter='throat.diameter', pore_diameter='pore.diameter', touch_length='throat.touch_length', surface_tension='pore.surface_tension', contact_angle='pore.contact_angle')>

```python
phys.add_model(propname='throat.meniscus',
               model=sinusoidal_model,
               mode='men',
               r_toroid=fiberRad,
               target_Pc=1000)
```

The equation for the solid sinusoidal profile is:

```python
x, a, b, rt, sigma, theta = syp.symbols('x, a, b, rt, sigma, theta')
y = (sym_cos(sym_pi*x/(2*a)))*b
r = rt + b-y
r
```

$\displaystyle - b \cos{\left(\frac{\pi x}{2 a} \right)} + b + rt$

```python
# Derivative of profile
rprime = r.diff(x)
rprime
```

$\displaystyle \frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a}$

```python
# Filling angle
alpha = sym_atan(rprime)
alpha
```

$\displaystyle \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)}$

```python
# Angle between y axis, meniscus center and meniscus contact point
eta = sym_pi - (theta + alpha)
eta
```

$\displaystyle - \theta - \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} + \pi$

```python
# Angle between x axis, meniscus center and meniscus contact point
gamma = sym_pi/2 - eta
gamma
```

$\displaystyle \theta + \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} - \frac{\pi}{2}$

```python
# Radius of curvature of meniscus
rm = r/sym_cos(eta)
rm
```

$\displaystyle - \frac{- b \cos{\left(\frac{\pi x}{2 a} \right)} + b + rt}{\cos{\left(\theta + \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} \right)}}$

```python
# Distance along x-axis from center of curvature to meniscus contact point
d = rm*sym_sin(eta)
d
```

$\displaystyle - \frac{\left(- b \cos{\left(\frac{\pi x}{2 a} \right)} + b + rt\right) \sin{\left(\theta + \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} \right)}}{\cos{\left(\theta + \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} \right)}}$

```python
# Capillary Pressure
p = 2*sigma/rm
p
```

$\displaystyle - \frac{2 \sigma \cos{\left(\theta + \operatorname{atan}{\left(\frac{\pi b \sin{\left(\frac{\pi x}{2 a} \right)}}{2 a} \right)} \right)}}{- b \cos{\left(\frac{\pi x}{2 a} \right)} + b + rt}$

```python
phys.add_model(propname='throat.max',
               model=sinusoidal_model,
               mode='max',
               r_toroid=fiberRad)
phys.add_model(propname='throat.touch',
               model=sinusoidal_model,
               mode='touch',
               r_toroid=fiberRad)
max_Pc_sin = phys['throat.max'][0]
print(max_Pc_sin)
```

    4729.770413396985

```python
plot_meniscus(target_Pc=max_Pc_sin, meniscus_model=sinusoidal_model);
```

    <AxesSubplot:>

```python
interact(plot_meniscus,
         target_Pc=(-2000, max_Pc_sin, 1),
         meniscus_model=fixed(sinusoidal_model),
         ax=fixed(None));
```

    interactive(children=(FloatSlider(value=1364.0, description='target_Pc', max=4729.770413396985, min=-2000.0, s…

    <function __main__.plot_meniscus(target_Pc, meniscus_model=None, ax=None)>

Now the crtical entry pressure is negative signifying that spontaneous imbibition will occur

# General Elliptical

Similarly we can define an elliptical profile and use the same method to determine the capillary pressure:

```python
y = sym_sqrt(1 - (x/a)**2)*b
y
```

$\displaystyle b \sqrt{1 - \frac{x^{2}}{a^{2}}}$

In-fact this is the model that OpenPNM uses for Purcell as well with a = b = fiber radius

```python
# Scale ellipse in x direction
phys['throat.scale_a'] = fiberRad
# Scale ellipse in y direction
phys['throat.scale_b'] = fiberRad
general_model = pm.meniscus.general_toroidal
phys.add_model(propname='throat.entry_pressure',
               model=general_model,
               profile_equation='elliptical',
               mode='max')
max_Pc_ellipse = phys['throat.entry_pressure'][0]
print(max_Pc_ellipse)
```

    8165.324889242946

```python
plot_meniscus(target_Pc=max_Pc_ellipse, meniscus_model=general_model);
```

    <AxesSubplot:>

```python
max_Pc_ellipse
```

    8165.324889242946

```python
interact(plot_meniscus,
         target_Pc=(-2000, max_Pc_ellipse, 1),
         meniscus_model=fixed(general_model),
         ax=fixed(None));
```

    interactive(children=(FloatSlider(value=3082.0, description='target_Pc', max=8165.324889242946, min=-2000.0, s…

    <function __main__.plot_meniscus(target_Pc, meniscus_model=None, ax=None)>

The two scale factors can now be used to determine a wide range of capillary behaviours with one general model. Below we run the model for a range of scaling factors showing the effect on the sign and magnitude of the entry pressure.

```python
bs = np.linspace(0.2, 1.0, 4)*throatRad
phys['throat.scale_a'] = throatRad
elliptical_pressures = []
sinusoidal_pressures = []
fig, (ax1, ax2) = plt.subplots(2, len(bs), figsize=(10, 10))
for i in range(len(bs)):
    phys['throat.scale_b'] = bs[i]
    phys.add_model(propname='throat.entry_pressure',
                   model=general_model,
                   profile_equation='elliptical',
                   mode='max',
                   num_points=1000)
    Pc = phys['throat.entry_pressure']
    elliptical_pressures.append(Pc)
    plot_meniscus(target_Pc=Pc, meniscus_model=general_model, ax=ax1[i])
for i in range(len(bs)):
    phys['throat.scale_b'] = bs[i]
    phys.add_model(propname='throat.entry_pressure',
                   model=general_model,
                   profile_equation='sinusoidal',
                   mode='max',
                   num_points=1000)
    Pc = phys['throat.entry_pressure']
    sinusoidal_pressures.append(Pc)
    plot_meniscus(target_Pc=Pc, meniscus_model=general_model, ax=ax2[i])
```

```python
plt.figure()
plt.plot(bs/throatRad, elliptical_pressures, 'g-');
plt.plot(bs/throatRad, sinusoidal_pressures, 'r-');
```

    [<matplotlib.lines.Line2D at 0x7f1048287e20>]

Here we can see that the two different shaped profiles lead to quite different capiallary behaviour. The elliptical profile always resuls in positive pressure and the meniscus is basically pinned to the end of the throat where highest pressure occurs as alpha always reaches 90. Whereas the sinusiodal model allows for spontaneous imbibition where a breakthrough may occur at negative capillary pressure for wetting fluids if the wall angle is shallow.


# Práctica Background Subtraction

En esta segunda práctica del bloque de análisis de secuencias haremos trabajo con 3 técnicas de background subtraction.

En primer lugar debéis implementar vuestro propio método de eliminación de fondo basado en la idea que explicamos del filtro exponencial. Podéis hacer las adaptaciones que encontréis necesario a la idea general del método para mejorar su rendimiento.

En segundo lugar debéis de usar las implementaciones del MOG y del MOG2 que se encuentran en la librería
 [OpenCV](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html).

En tercer lugar lo que quiero es que hagáis una comparativa entre su método y los dos basados en Mixture de gausiano utilizando el dataset de la competición [changedetection.net](http://changedetection.net/) del año 2012.

En concreto debe usar una secuencia de cada categoría exceptuando la de *Thermal*.

Las métricas que a usar para cada secuencia son:

* **TP** : True Positive
* **FP** : False Positive
* **FN** : False Negative
* **TN** : True Negative
* **Re (Recall)** : TP / (TP + FN)
* **F-Measure** : (2 * Precision * Recall) / (Precision + Recall)
* **Precision** : TP / (TP + FP)

Finalmente se pide que hagáis un análisis de los resultados obtenidos por cada secuencia: problemas, carencias, puntos fuertes de los algoritmos ...

**Entrega:**

* Explicación del algoritmo implementado y código fuente.
* Resultados de las secuencias en formato imagen o video.
* Resultados de las secuencias en formato tabla resumen de las métricas.
* Análisis de los resultados

Secuencias a usar:
- baseline: todo
- cameraJitter: badminton, traffic
- dynamicBackground: canoe, fall, fountain02
- intermittentObjectMotion: sofa,
- shadow: busStation, copyMachine, cubicle, peopleInShade

### Métricas

```python
def recall(tp, fn):
    return (tp/(tp+fn))

def precision(tp, fp):
    return (tp/(tp+fp))

def f_measure(precision, recall):
    return ((2*precision*recall)/(precision+recall))

def all_metrics (resultPath, groundtruthPath, start_frame, end_frame):
    # Cargamos el resultado del filtro indicado
    result = loadImages(resultPath)
    groundTruth = loadImages(groundtruthPath)

    # ground truth empieza en start_frame, los frames están numerados de 1 hasta n, pero el array de frames va de 0 a n-1
    total_frames = end_frame-start_frame

    # Inicializamos un array para cada métrica donde se el resultado para cada frame
    tp =  np.zeros(total_frames)
    fp =  np.zeros(total_frames)
    fn =  np.zeros(total_frames)
    tn =  np.zeros(total_frames)

    # Calculamos las métricas True Positive, False Positive, False Negative, True Negative para cada frame
    for i in range(total_frames):
        tp[i], fp[i], fn[i], tn[i] = comparator(result[i+start_frame], groundTruth[i+start_frame])

    # Calculamos las métricas Recall, Precision y F-measure para cada frame
    recall_frame = recall(tp=tp, fn=fn)
    precision_frame = precision(tp=tp, fp=fp)
    fMeasure_frame = f_measure(precision=precision_frame, recall=recall_frame)

    # Calculamos las métricas anteriores para toda la secuencia en conjunto
    tp_secuencia = tp.sum()
    fp_secuencia = fp.sum()
    fn_secuencia = fn.sum()
    tn_secuencia = tn.sum()

    recall_secuencia = recall(tp=tp_secuencia, fn=fn_secuencia)
    precision_secuencia = precision(tp=tp_secuencia, fp=fp_secuencia)
    fMeasure_secuencia = f_measure(precision=precision_secuencia, recall=recall_secuencia)

    cm_frames = np.array([tp,fp,fn,tn])
    cm_secuencia = np.array ([tp_secuencia, fp_secuencia, fn_secuencia, tn_secuencia])

    r_p_fm_frames = np.array([recall_frame, precision_frame, fMeasure_frame])
    r_p_fm_secuencia = np.array([recall_secuencia, precision_secuencia, fMeasure_secuencia])

    return cm_frames, cm_secuencia, r_p_fm_frames, r_p_fm_secuencia
```

### Filtro exponencial para _background subtraction_
Parte de la idea de eliminación de fondo más básica: restar el fotograman **_fondo_** (_background_) del fotograma actual para obtener el **_primer plano_** (_foreground_).
El primer problema o tarea para realizar este algoritmo es conseguir ese fotograma **_fondo_**. Para ello se necesita una imagen que represente el fondo sin ningún otro objeto, pero esto no siempre es posible, por lo tanto hay que buscar otras soluciones. Una de ellas es estimar el fondo como la media o la mediana a partir de los primeros _n_ fotogramas.
El segundo problema que surge es que el fondo en los casos prácticos varía con el tiempo y por lo tanto es posible que ese fotograma _fondo_ que hemos estimado no nos sirve más tarde. Por lo tanto la mejora que se propone es estimar el fondo recursivamente respecto el fotograma anterior siguiendo la siguiente fórmula:
$$
\begin{align}
B_t=(1-{\alpha})B_{t-1}+{\alpha}I_t
\end{align}
$$
Donde $B_t$ es la estimación del fondo para el fotograma actual, $B_{t-1}$ es el fondo para el fotograma anterior, $I_t$ es el fotograma actual y $\alpha$ es el factor de aprendizaje que indica cuánto del fotograma actual se considerará fondo para el siguiente fotograma.

```python
from utils import *
import numpy as np
from tqdm.notebook import tqdm
import matplotlib.pyplot as plt
```

Para mantener la limpieza del _notebook_ se han definidos las funciones para realizar el análisis dentro del archivo _utils.py_.
Las funciones que se encuentran son las siguientes:
- **comparator**: compara un _frame_ resultante de un modelo de _background subtraction_ con el resultado esperado (_groundtruth_)
- **loadImages**: devuelve una lista con las imágenes dentro de la carpeta especificada
- **exponentialFilter**: implementación del algoritmo basado en filtro exponencial
- **MOG**: implementación del algoritmo MOG disponible [aquí](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html)
- **MOG2**: implementación del algoritmo MOG2 disponible [aquí](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html)
- **im2vid**: genera video a partir de las imágenes ubicadas en una carpeta
- **showVideo**: muestra el video en una ventana flotante para visualizar mejor el resultado del modelo

Notar que, a pesar de tratarse de algoritmos que trabajan con video, el _dataset_ que se proporciona para realizar las pruebas son imágenes que representan los fotogramas de una secuencia. Por lo tanto, las funciones que se han realizado, se han pensado para trabajar con imágenes en vez de video.

Pasos a seguir para cada secuencia:
1. Cargar las imágenes en una variable (path de las imágenes)
2. Aplicar el filtro deseado EF, MOG y MOG2 (path donde se guardarán las imágenes aplicadas por el filtro)
3. Obtener las métricas con comparator (hacer bucle a lo largo de las imágenes resultado -> path del groundtruth)
4. Mostrar los resultados y videos
5. Comparar los resultados (hacer gráfica a lo largo del

```python
# dynamicBackground canoe dataset output paths
expFilter_canoe_path = 'DATA/dynamicBackground/results/canoe/expFilter/'
MOG_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG/'
MOG2_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG2'

# intermittentObject sofa dataset output paths
expFilter_sofa_path = 'DATA/intermittentObjectMotion/results/sofa/expFilter/'
MOG_sofa_path = 'DATA/intermittentObjectMotion/results/sofa/MOG'
MOG2_sofa_path = 'DATA/intermittentObjectMotion/results/sofa/MOG2'

# shadow copyMachine dataset output paths
expFilter_copyMachine_path = 'DATA/shadow/results/copyMachine/expFilter/'
MOG_copyMachine_path = 'DATA/shadow/results/copyMachine/MOG'
MOG2_copyMachine_path = 'DATA/shadow/results/copyMachine/MOG2'
```

# 1. Secuencia _highway_ del dataset _baseline_

Cargamos las imágenes de entrada y el ground truth con el que se calcularán las métricas.

```python
# baseline highway dataset groundtruth y input paths
gt_highway_path = 'DATA/baseline/baseline/highway/groundtruth/*.png'
in_highway_path = 'DATA/baseline/baseline/highway/input/*.jpg'

groundTruth = loadImages(gt_highway_path)
frames = loadImages(in_highway_path)
```

    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2667.40it/s]
    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:01<00:00, 1208.82it/s]

## 1.1. Algoritmo filtro exponencial

Aplicamos el algoritmo basado en el filtro exponencial que hemos implementado.

```python
# baseline highway dataset output path
expFilter_highway_path = 'DATA/baseline/results/highway/expFilter/'

exponentialFilter(frames, 0.3, expFilter_highway_path, 20, bgFilter ='MEDIAN')
```

    Algorithm application: 100%|█████████████████████████████████████████████████████| 1680/1680 [00:01<00:00, 1032.18it/s]

Convertimos la secuencia de imágenes en video para poder visualizar mejor el resultado.

```python
#im2vid(expFilter_highway_path+'*.png','testvid.mp4')
```

Mostramos el video en una ventana flotante.

```python
#showVideo('testvid.mp4')
```

### 1.1.1. Cálculo de métricas
Calculamos las métricas comparando con el _ground truth_ propocionado. Para cada secuencia se proporciona una ROI (Region Of Interest) sobre la cual se realiza el groundtruth, para simplificar el cálculo se han seleccionado aquellas secuencias en las que la ROI sea toda la imagen. Por otro lado, también se especifica el _frame_ de inicio y final sobre los que se ha de realizar la verificación del algoritmo, por lo tanto solo se calcularán las métricas dentro de ese rango.

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_EF = all_metrics (expFilter_highway_path+'*.png', gt_highway_path, start_frame=469, end_frame=1699)
```

    Loading images: 100%|█████████████████████████████████████████████████████████████| 1700/1700 [00:06<00:00, 262.06it/s]
    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2594.43it/s]

## 1.2. Algoritmo MOG

Aplicamos el algoritmo MOG (Mixture Of Gaussians)

```python
# baseline highway dataset output path
MOG_highway_path = 'DATA/baseline/results/highway/MOG/'

MOG(frames,MOG_highway_path)
```

    Algorithm application2: 100%|█████████████████████████████████████████████████████| 1700/1700 [00:03<00:00, 496.46it/s]

```python
#im2vid(MOG_highway_path+'*.png','testvid.mp4')
```

```python
#showVideo('testvid.mp4')
```

### 1.2.1. Cálculo de métricas

```python
cm_frames_MOG,\
cm_secuencia_MOG,\
r_p_fm_frames_MOG,\
r_p_fm_secuencia_MOG = all_metrics (MOG_highway_path+'*.png', gt_highway_path, start_frame=469, end_frame=1699)
```

    Loading images: 100%|█████████████████████████████████████████████████████████████| 1700/1700 [00:06<00:00, 275.06it/s]
    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2675.90it/s]

## 1.3. Algoritmo MOG2

```python
# baseline highway dataset output path
MOG2_highway_path = 'DATA/baseline/results/highway/MOG2/'

MOG2(frames,MOG2_highway_path)
```

    Algorithm application: 100%|██████████████████████████████████████████████████████| 1700/1700 [00:03<00:00, 448.95it/s]

### 1.3.1. Cálculo de métricas

```python
cm_frames_MOG2,\
cm_secuencia_MOG2,\
r_p_fm_frames_MOG2,\
r_p_fm_secuencia_MOG2 = all_metrics (MOG2_highway_path+'*.png', gt_highway_path, start_frame=469, end_frame=1699)
```

    Loading images: 100%|█████████████████████████████████████████████████████████████| 1700/1700 [00:06<00:00, 276.62it/s]
    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2637.81it/s]

## Comparación resultados

```python
cm_frames_gt,\
cm_secuencia_gt,\
r_p_fm_frames_gt,\
r_p_fm_secuencia_gt = all_metrics (gt_highway_path, gt_highway_path, start_frame=469, end_frame=1699)
```

    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2642.47it/s]
    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2634.41it/s]

```python
fig, ax = plt.subplots(3,3, sharex=True, sharey=True)
ax[0,0].plot(r_p_fm_frames_EF[0])
ax[0,0].set_title("recall-EF")
ax[1,0].plot(r_p_fm_frames_EF[1])
ax[1,0].set_title("precision-EF")
ax[2,0].plot(r_p_fm_frames_EF[2])
ax[2,0].set_title("f-measure-EF")

ax[0,1].plot(r_p_fm_frames_MOG[0])
ax[0,1].set_title("recall-MOG")
ax[1,1].plot(r_p_fm_frames_MOG[1])
ax[1,1].set_title("precision-MOG")
ax[2,1].plot(r_p_fm_frames_MOG[2])
ax[2,1].set_title("f-measure-MOG")

ax[0,2].plot(r_p_fm_frames_MOG2[0])
ax[0,2].set_title("recall-MOG2")
ax[1,2].plot(r_p_fm_frames_MOG2[1])
ax[1,2].set_title("precision-MOG2")
ax[2,2].plot(r_p_fm_frames_MOG2[2])
ax[2,2].set_title("f-measure-MOG2")

plt.ylim([0,1])
fig.tight_layout()
plt.show()
```

```python
import pandas as pd
```

```python
r_p_fm_secuencia_EF
```

    array([0.60293747, 0.5       , 0.54666514])

```python
r_p_fm_secuencia_MOG
```

    array([0.50234751, 0.5       , 0.501171  ])

```python
r_p_fm_secuencia_MOG2
```

    array([0.92913693, 0.5       , 0.65013849])

```python
cm_secuencia_gt
```

    array([ 5448641.,        0.,        0., 86228220.])

```python
cm_secuencia_MOG-cm_secuencia_gt
```

    array([-3168986.,    68877.,  2258349.,   -14606.])

```python
np.concatenate((r_p_fm_secuencia_EF,cm_secuencia_EF))
```

    array([6.02937474e-01, 5.00000000e-01, 5.46665145e-01, 2.95299300e+06,
           3.57410400e+06, 1.94468400e+06, 6.80320250e+07])

```python
cm_secuencia_EF.sum()
```

    94464000.0

```python
cm_secuencia_MOG.sum()
```

    94464000.0

```python
cm_secuencia_MOG2.sum()
```

    94464000.0

```python
cm_secuencia_gt.sum()
```

    91676861.0

```python
gt_result = loadImages(gt_highway_path)
```

    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 2606.23it/s]

```python
(gt_result[0].shape[0])
```

    240

```python
pixels = 0
for i in range(469,len(gt_result)):
    gt_result[i] = cv2.cvtColor(gt_result[i], cv2.COLOR_BGR2GRAY)
    print(np.unique(gt_result[i]))
```

    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]
    [  0  50 170 255]

```python
pixels
```

    94540800

```python
mog_result = loadImages(MOG2_highway_path+'*.png')
```

    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:00<00:00, 1703.61it/s]

```python
mog_result[469].shape
```

    (240, 320, 3)

```python
ef_result = loadImages(expFilter_highway_path+'*.png')
```

    Loading images: 100%|████████████████████████████████████████████████████████████| 1700/1700 [00:01<00:00, 1313.18it/s]

```python
ef_result[469] = cv2.cvtColor(ef_result[469], cv2.COLOR_BGR2GRAY)
```

```python
ef_result[469]
```

    array([[  0,   0,   1, ..., 254,   3,   0],
           [  2,   0,   0, ..., 255,   0,   0],
           [254, 255,   0, ...,   0,   2,   1],
           ...,
           [  2,   0,   2, ...,   0,   0,   0],
           [  1,   0,   0, ...,   0,   1,   1],
           [  0,   1,   0, ...,   1,   1,   0]], dtype=uint8)

```python
df_highway = pd.DataFrame(np.array([np.concatenate((r_p_fm_secuencia_EF,cm_secuencia_EF)),
                                    np.concatenate((r_p_fm_secuencia_MOG,cm_secuencia_MOG)),
                                    np.concatenate((r_p_fm_secuencia_MOG2,cm_secuencia_MOG2)),
                                    np.concatenate((r_p_fm_secuencia_gt,cm_secuencia_gt))]),
                         columns = ['Recall', 'Precision','F-measure','TP','FP','FN','TN'])
df_highway['Algorithm'] = ['Exponential Filter','MOG','MOG2','Ground truth']
df_highway.set_index('Algorithm')
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Recall</th>
      <th>Precision</th>
      <th>F-measure</th>
      <th>TP</th>
      <th>FP</th>
      <th>FN</th>
      <th>TN</th>
    </tr>
    <tr>
      <th>Algorithm</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Exponential Filter</th>
      <td>0.590599</td>
      <td>0.434918</td>
      <td>0.500942</td>
      <td>4165508.0</td>
      <td>5412167.0</td>
      <td>2887516.0</td>
      <td>81998809.0</td>
    </tr>
    <tr>
      <th>MOG</th>
      <td>0.500938</td>
      <td>0.967187</td>
      <td>0.660027</td>
      <td>3156445.0</td>
      <td>107085.0</td>
      <td>3144618.0</td>
      <td>88055852.0</td>
    </tr>
    <tr>
      <th>MOG2</th>
      <td>0.933806</td>
      <td>0.774233</td>
      <td>0.846565</td>
      <td>6843616.0</td>
      <td>1995606.0</td>
      <td>485117.0</td>
      <td>85139661.0</td>
    </tr>
    <tr>
      <th>Ground truth</th>
      <td>1.000000</td>
      <td>1.000000</td>
      <td>1.000000</td>
      <td>5448641.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>86228220.0</td>
    </tr>
  </tbody>
</table>
</div>

```python
r_p_fm_secuencia_EF
```

    array([0.60293747, 0.5       , 0.54666514])

```python
df_highway
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Recall</th>
      <th>Precision</th>
      <th>F-measure</th>
      <th>Algorithm</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0.602937</td>
      <td>0.5</td>
      <td>0.546665</td>
      <td>Exponential Filter</td>
    </tr>
    <tr>
      <th>1</th>
      <td>0.502348</td>
      <td>0.5</td>
      <td>0.501171</td>
      <td>MOG</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0.929137</td>
      <td>0.5</td>
      <td>0.650138</td>
      <td>MOG2</td>
    </tr>
  </tbody>
</table>
</div>

```python
df2 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9],[10,11,12]]),
                   columns=['a', 'b', 'c'])
df2
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
      <th>c</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
    </tr>
    <tr>
      <th>2</th>
      <td>7</td>
      <td>8</td>
      <td>9</td>
    </tr>
    <tr>
      <th>3</th>
      <td>10</td>
      <td>11</td>
      <td>12</td>
    </tr>
  </tbody>
</table>
</div>

# 2. Secuencia _badminton_ del dataset _cameraJitter_

Cargamos las imágenes de entrada y el ground truth con el que se calcularán las métricas.

```python
#camaraJitter  badminton dataset input
gt_badminton_path = 'DATA/cameraJitter/cameraJitter/badminton/groundtruth/*.png'
in_badminton_path = 'DATA/cameraJitter/cameraJitter/badminton/input/*.jpg'

groundTruth = loadImages(gt_badminton_path)
frames = loadImages(in_badminton_path)
```

    Loading images: 100%|█████████████████████████████████████████████████████████████| 1150/1150 [00:03<00:00, 296.71it/s]
    Loading images: 100%|█████████████████████████████████████████████████████████████| 1150/1150 [00:08<00:00, 129.45it/s]

## 2.1. Algoritmo filtro exponencial

```python
# camaraJitter badminton dataset output path
expFilter_badminton_path = 'DATA/cameraJitter/results/badminton/expFilter/'

```

### 2.1.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_EF = all_metrics (expFilter_badminton_path+'*.jpg', gt_badminton_path, start_frame=800, end_frame=1150)
```

## 2.2. Algoritmo MOG

```python
# camaraJitter badminton dataset output paths
MOG_badminton_path = 'DATA/cameraJitter/results/badminton/MOG/'
```

### 2.2.1. Cálculo de métricas

```python
cm_frames_MOG,\
cm_secuencia_MOG,\
r_p_fm_frames_MOG,\
r_p_fm_secuencia_MOG = all_metrics (MOG_badminton_path+'*.jpg', gt_badminton_path, start_frame=800, end_frame=1150)
```

## 2.3. Algoritmo MOG2

```python
# camaraJitter badminton dataset output paths
MOG2_badminton_path = 'DATA/cameraJitter/results/badminton/MOG2'
```

### 2.3.1. Cálculo de métricas

```python
cm_frames_MOG2,\
cm_secuencia_MOG2,\
r_p_fm_frames_MOG2,\
r_p_fm_secuencia_MOG2 = all_metrics (MOG2_badminton_path+'*.jpg', gt_badminton_path, start_frame=800, end_frame=1150)
```

## Comparación resultados

# 3. Secuencia _canoe_ del dataset _dynamicBackground_

```python
Cargamos las imágenes de entrada y el ground truth con el que se calcularán las métricas.
```

```python
# dynamicBackground  canoe dataset input
gt_canoe_path = 'DATA/dynamicBackground/dynamicBackground/canoe/groundtruth/*.png'
in_canoe_path = 'DATA/dynamicBackground/dynamicBackground/canoe/input/*.jpg'

groundTruth = loadImages(gt_canoe_path)
frames = loadImages(in_canoe_path)
```

```python
# dynamicBackground canoe dataset output path
expFilter_canoe_path = 'DATA/dynamicBackground/results/canoe/expFilter/'
MOG_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG/'
MOG2_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG2'
```

## 3.1. Algoritmo filtro exponencial

```python
# dynamicBackground canoe dataset output paths
expFilter_canoe_path = 'DATA/dynamicBackground/results/canoe/expFilter/'
```

### 3.1.1 Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_canoe_path+'*.jpg', gt_canoe_path, start_frame=469, end_frame=1699)
```

## 3.2. Algoritmo MOG

```python
# dynamicBackground canoe dataset output path
MOG_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG/'
```

### 3.2.1 Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (MOG_canoe_path+'*.jpg', gt_canoe_path, start_frame=469, end_frame=1699)
```

## 3.3. Algoritmo MOG2

```python
# dynamicBackground canoe dataset output path
MOG2_canoe_path = 'DATA/dynamicBackground/results/canoe/MOG2'
```

### 3.3.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (MOG2_canoe_path+'*.jpg', gt_canoe_path, start_frame=469, end_frame=1699)
```

## 3.4. Comparación resultados

# 4. Secuencia _sofa_ del dataset _intermittentObjectMotion_

```python
Cargamos las imágenes de entrada y el ground truth con el que se calcularán las métricas.
```

```python
# intermittentObjectMotion sofa dataset input
gt_sofa_path = 'DATA/intermittentObjectMotion/intermittentObjectMotion/sofa/groundtruth/*.png'
in_sofa_path = 'DATA/intermittentObjectMotion/intermittentObjectMotion/sofa/input/*.jpg'

groundTruth = loadImages(gt_sofa_path)
frames = loadImages(in_sofa_path)
```

## 4.1. Algoritmo filtro exponencial

### 4.1.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 4.2. Algoritmo MOG

### 4.2.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 4.3. Algoritmo MOG2

### 4.3.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 4.4. Comparación resultados

# 5. Secuencia _copyMachine_ del dataset _shadow_

```python
Cargamos las imágenes de entrada y el ground truth con el que se calcularán las métricas.
```

```python
# shadow copyMachine dataset input
gt_copyMachine_path = 'DATA/shadow/shadow/copyMachine/groundtruth/*.png'
in_copyMachine_path = 'DATA/shadow/shadow/copyMachine/input/*.jpg'

groundTruth = loadImages(gt_copyMachine_path)
frames = loadImages(in_copyMachine_path)
```

## 5.1. Algoritmo filtro exponencial

### 5.1.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 5.2. Algoritmo MOG

### 5.2.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 5.3. Algoritmo MOG2

### 5.3.1. Cálculo de métricas

```python
cm_frames_EF,\
cm_secuencia_EF,\
r_p_fm_frames_EF,\
r_p_fm_secuencia_RF = all_metrics (expFilter_highway_path+'*.jpg', gt_highway_path, start_frame=469, end_frame=1699)
```

## 5.4. Comparación resultados


# Autoencoders

In this notebook we will explore autoencoder models. These are models in which the inputs are *encoded* to some intermediate representation before this representation is then *decoded* to try to reconstruct the inputs. They are example of a model which uses an unsupervised training method and are both interesting as a model in their own right and as a method for pre-training useful representations to use in supervised tasks such as classification. Autoencoders were covered as a pre-training method in the [sixth lecture slides](http://www.inf.ed.ac.uk/teaching/courses/mlp/2016/mlp06-enc.pdf).

## Exercise 1: Linear autoencoders

For the first exercise we will consider training a simple 'contractive' autoencoder - that is one in which the hidden representation is smaller in dimension than the input and the objective is to minimise the mean squared error between the original inputs and reconstructed inputs. To begin with we will consider models in which the encoder and decoder are both simple affine transformations.

When training an autoencoder the target outputs for the model are the original inputs. A simple way to integrate this in to our `mlp` framework is to define a new data provider inheriting from a base data provider (e.g. `MNISTDataProvider`) which overrides the `next` method to return the inputs batch as both inputs and targets to the model. A data provider of this form has been provided for you in `mlp.data_providers` as `MNISTAutoencoderDataProvider`.

Use this data provider to train an autoencoder model with a 50 dimensional hidden representation and both encoder and decoder defined by affine transformations. You should use a sum of squared differences error and a basic gradient descent learning rule with learning rate 0.01. Initialise the biases to zero and use a uniform Glorot initialisation for both layers weights. Train the model for 25 epochs with a batch size of 50.

```python
import numpy as np
import logging
import mlp.layers as layers
import mlp.models as models
import mlp.optimisers as optimisers
import mlp.errors as errors
import mlp.learning_rules as learning_rules
import mlp.data_providers as data_providers
import mlp.initialisers as initialisers
import matplotlib.pyplot as plt
%matplotlib inline
```

```python

```

Using the function defined in the cell below (from the first lab notebook), plot a batch of the original images and the autoencoder reconstructions.

```python
def show_batch_of_images(img_batch, fig_size=(3, 3), num_rows=None):
    fig = plt.figure(figsize=fig_size)
    batch_size, im_height, im_width = img_batch.shape
    if num_rows is None:
        # calculate grid dimensions to give square(ish) grid
        num_rows = int(batch_size**0.5)
    num_cols = int(batch_size * 1. / num_rows)
    if num_rows * num_cols < batch_size:
        num_cols += 1
    # intialise empty array to tile image grid into
    tiled = np.zeros((im_height * num_rows, im_width * num_cols))
    # iterate over images in batch + indexes within batch
    for i, img in enumerate(img_batch):
        # calculate grid row and column indices
        r, c = i % num_rows, i // num_rows
        tiled[r * im_height:(r + 1) * im_height,
              c * im_height:(c + 1) * im_height] = img
    ax = fig.add_subplot(111)
    ax.imshow(tiled, cmap='Greys', vmin=0., vmax=1.)
    ax.axis('off')
    fig.tight_layout()
    plt.show()
    return fig, ax
```

```python

```

### Optional extension: principle components analysis

*This section is provided for the interest of those also sitting MLPR or otherwise already familiar with eigendecompositions and PCA. Feel free to skip over if this doesn't apply to you (or even if it does).*

For a linear (affine) contractive autoencoder model trained with a sum of squared differences error function there is an analytic solution for the optimal model parameters corresponding to [principle components analysis](https://en.wikipedia.org/wiki/Principal_component_analysis).

If we have a training dataset of $N$ $D$-dimensional vectors $\left\lbrace \boldsymbol{x}^{(n)} \right\rbrace_{n=1}^N$, then we can calculate the empiricial mean and covariance of the training data using

\begin{equation}
  \boldsymbol{\mu} = \frac{1}{N} \sum_{n=1}^N \left[ \boldsymbol{x}^{(n)} \right]
  \qquad
  \text{and}
  \qquad
  \mathbf{\Sigma} = \frac{1}{N}
  \sum_{n=1}^N \left[
    \left(\boldsymbol{x}^{(n)} - \boldsymbol{\mu} \right)
    \left(\boldsymbol{x}^{(n)} - \boldsymbol{\mu} \right)^{\rm T}
  \right].
\end{equation}

We can then calculate an [eigendecomposition](https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix) of the covariance matrix
\begin{equation}
  \mathbf{\Sigma} = \mathbf{Q} \mathbf{\Lambda} \mathbf{Q}^{\rm T}
  \qquad
  \mathbf{Q} = \left[
  \begin{array}{cccc}
  \uparrow & \uparrow & \cdots & \uparrow \\
  \boldsymbol{q}_1 & \boldsymbol{q}_2 & \cdots & \boldsymbol{q}_D \\
  \downarrow & \downarrow & \cdots & \downarrow \\
  \end{array}
  \right]
  \qquad
  \mathbf{\Lambda} = \left[
  \begin{array}{cccc}
  \lambda_1 & 0 & \cdots & 0 \\
  0 & \lambda_2 & \cdots & \vdots \\
  \vdots & \vdots & \ddots & 0 \\
  0 & 0 & \cdots & \lambda_D \\
  \end{array} \right]
\end{equation}

with $\mathbf{Q}$ an orthogonal matrix, $\mathbf{Q}\mathbf{Q}^{\rm T} = \mathbf{I}$, with columns $\left\lbrace \boldsymbol{q}_d \right\rbrace_{d=1}^D$ corresponding to the eigenvectors of $\mathbf{\Sigma}$ and $\mathbf{\Lambda}$ a diagonal matrix with diagonal elements $\left\lbrace \lambda_d \right\rbrace_{d=1}^D$ the corresponding eigenvalues of $\mathbf{\Sigma}$.

Assuming the eigenvalues are ordered such that $\lambda_1 < \lambda_2 < \dots < \lambda_D$ then the top $K$ principle components of the inputs (eigenvectors with largest eigenvalues) correspond to $\left\lbrace \boldsymbol{q}_d \right\rbrace_{d=D + 1 - K}^D$. If we define a $D \times K$ matrix $\mathbf{V} = \left[ \boldsymbol{q}_{D + 1 - K} ~ \boldsymbol{q}_{D + 2 - K} ~\cdots~ \boldsymbol{q}_D \right]$ then we can find the projections of a (mean normalised) input vector on to the selected $K$ principle components as $\boldsymbol{h} = \mathbf{V}^{\rm T}\left( \boldsymbol{x} - \boldsymbol{\mu}\right)$. We can then use these principle component projections to form a reconstruction of the original input just in terms of the $K$ top principle components using $\boldsymbol{r} = \mathbf{V} \boldsymbol{h} + \boldsymbol{\mu}$. We can see that this is just a sequence of two affine transformations and so is directly analagous to a model with two affine layers and with $K$ dimensional outputs of the first layer / inputs to second.

The function defined in the cell below will calculate the PCA solution for a set of input vectors and a defined number of components $K$. Use it to calculate the top 50 principle components of the MNIST training data. Use the returned matrix and mean vector to calculate the PCA based reconstructions of a batch of 50 MNIST images and use the `show_batch_of_images` function to plot both the original and reconstructed inputs alongside each other. Also calculate the sum of squared differences error for the PCA solution on the MNIST training set and compare to the figure you got by gradient descent based training above. Will the gradient based training produce the same hidden representations as the PCA solution if it is trained to convergence?

```python
def get_pca_parameters(inputs, num_components=50):
    mean = inputs.mean(0)
    inputs_zm = inputs - mean[None, :]
    covar = np.einsum('ij,ik', inputs_zm, inputs_zm)
    eigvals, eigvecs = np.linalg.eigh(covar)
    return eigvecs[:, -num_components:], mean
```

```python

```

## Exercise 2: Non-linear autoencoders

Those who did the extension in the previous exercise will have just seen that for an autoencoder with both linear / affine encoder and decoders, there is an analytic solution for the parameters which minimise a sum of squared differences error.

In general the advantage of using gradient-based training methods is that it allows us to use non-linear models for which there is no analytic solution for the optimal parameters. The hope is the use of non-linear transformations between the affine transformation layers will increase the representational power of the model (a sequence of affine transformations applied without any interleaving non-linear operations can always be represented by a single affine transformation).

Train a contractive autoencoder with an initial affine layer (output dimension again 50) followed by a rectified linear layer, then an affine transformation projecting to outputs of same dimension as the original inputs, and finally a logistic sigmoid layer at the output. As the only layers with parameters are the two affine layers which have the same dimensions as in the fully affine model above, the overall model here has the same number of parameters as previously.

Again train for 25 epochs with 50 training examples per batch and use a uniform Glorot initialisation for the weights, and zero biases initialisation. Use our implementation of the 'Adam' adaptive moments learning rule (available in `mlp.learning_rules` as `AdamLearningRule`) rather than basic gradient descent here (the adaptivity helps deal with the varying appropriate scale of updates induced by the non-linear transformations in this model).

```python

```

Plot batches of the inputs and reconstructed inputs for this non-linear contractive autoencoder model and compare to the corresponding plots for the linear models above.

```python

```

## Exercise 3: Denoising autoencoders

So far we have just considered autoencoders that try to reconstruct the input vector fed into them via some intermediate lower-dimensional 'contracted' representation. The contraction is important as if we were to mantain the input dimensionality in all layers of the model a trivial optima for the model to learn would be to apply an identity transformation at each layer.

It can be desirable for the intermediate hidden representation to be robust to noise in the input. The intuition is that this will force the model to learn to maintain the 'important structure' in the input in the hidden representation (that needed to reconstruct the input). This also removes the requirement to have a contracted hidden representation (as the model can no longer simply learn to apply an identity transformation) though in practice we will still often use a lower-dimensional hidden representation as we believe there is a certain level of redundancy in the input data and so the important structure can be represented with a lower dimensional representation.

Create a new data provider object which adds to noise to the inputs to an autoencoder in each batch it returns. There are various different ways you could introduce noise. The three suggested in the lecture slides are

  * *Gaussian*: add independent, zero-mean Gaussian noise of a fixed standard-deviation to each dimension of the input vectors.
  * *Masking*: generate a random binary mask and perform an elementwise multiplication with each input (forcing some subset of the values to zero).
  * *Salt and pepper*: select a random subset of values in each input and randomly assign either zero or one to them.

You should choose one of these noising schemes to implement. It may help to know that the base `DataProvider` object already has access to a random number generator object as its `self.rng` attribute.

```python

```

Once you have implemented your chosen scheme, use the new data provider object to train a denoising autoencoder with the same model architecture as in exercise 2.

```python

```

Use the `show_batch_of_images` function from above to visualise a batch of noisy inputs from your data provider implementation and the denoised reconstructions from your trained denoising autoencoder.

```python

```

## Exercise 4: Using an autoencoder as an initialisation for supervised training

As a final exercise we will use the first layer of an autoencoder for MNIST digit images as a layer within a multiple layer model trained to do digit classification. The intuition behind pretraining methods like this is that the hidden representations learnt by an autoencoder should be a more useful representation for training a classifier than the raw pixel values themselves. We could fix the parameters in the layers taken from the autoencoder but generally we can get better performance by letting the whole model be trained end-to-end on the supervised training task, with the learnt autoencoder parameters in this case acting as a potentially more intelligent initialisation than randomly sampling the parameters which can help ease some of the optimisation issues encountered due to poor initialisation of a model.

You can either use one of the autoencoder models you trained in the previous exercises, or train a new autoencoder model for specifically for this exercise. Create a new model object (instance of `mlp.models.MultipleLayerModel`) in which the first layer(s) of the list of layer passed to the model constructor are the trained first layer(s) from your autoencoder model (these can be accessed via the `layers` attribute which is a list of all the layers in a model). Add any additional layers you wish to the pretrained layers - at the very least you will need to add an output layer with output dimension 10 to allow the model to be used to predict class labels. Train this new model on the original MNIST image, digit labels pairs with a cross entropy error.

```python

```