Skip to content

Instantly share code, notes, and snippets.

@KelSolaar KelSolaar/barten.py
Created Jan 31, 2019

Embed
What would you like to do?
Contrast Sensitivity Function - Barten (1999)
# https://pure.tue.nl/ws/files/1613279/9901043.pdf
#http://car.france3.mars.free.fr/Formation%20INA%20HD/HDTV/HDTV%20%202007%20v35/SMPTE%20normes%20et%20confs/Contrastm.pdf
# %%
from __future__ import division
import matplotlib.pyplot as plt
import numpy as np
from colour.utilities import as_float_array
from colour.plotting import colour_style, plot_single_function
colour_style()
def photon_conversion_factor():
"""
Mmmh, tasty stuff to be done.
"""
pass
def optical_MTF_Barten1999(u, sigma=0.5):
"""
Parameters
----------
u : numeric or array_like
Spatial frequency :math:`u`.
sigma : numeric or array_like, optional
Standard deviation :math:`\sigma` of the line-spread function resulting
from the convolution of the different elements of the convolution
process.
"""
u = as_float_array(u)
sigma = as_float_array(sigma)
return np.exp(-2 * np.pi**2 * sigma**2 * u**2)
def pupil_diameter_Barten1999(L, X_0):
"""
Parameters
----------
L : numeric or array_like
Average luminance :math:`L` in :math:`cd/m^2`.
X_0 : numeric or array_like
Angular size of the object :math:`X_0` in degrees.
"""
return 5 - 3 * np.tanh(0.4 * np.log(L * X_0**2 / 40**2))
def sigma_Barten1999(sigma_0=0.5 / 60, C_ab=0.08 / 60, d=2.5):
"""
Parameters
----------
sigma_0 : numeric or array_like, optional
Constant :math:`\sigma_{0}` in degrees.
C_ab : numeric or array_like, optional
Spherical aberration of the eye :math:`C_{ab}` in degrees.
d : numeric or array_like, optional
Pupil diameter :math:`d` in millimeters.
Returns
-------
ndarray
Standard deviation :math:`\sigma` of the line-spread function resulting
from the convolution of the different elements of the convolution
process.
"""
sigma_0 = as_float_array(sigma_0)
C_ab = as_float_array(C_ab)
return np.sqrt((sigma_0)**2 + (C_ab * d)**2)
def retinal_illuminance_Barten1999(L, d=2.5, stiles_crawford_correction=True):
"""
Parameters
----------
d : numeric or array_like
Pupil diameter :math:`d` in millimeters.
L : numeric or array_like
Average luminance :math:`L` in :math:`cd/m^2`.
Returns
-------
ndarray
Retinal illuminance :math:`E` in Trolands.
Notes
-----
- This definition is for use with photopic viewing conditions and thus
corrects for the Stiles-Crawford effect by default, i.e. directional
sensitivity of the cone cells with lower response of cone cells
receiving light from the edge of the pupil.
"""
d = as_float_array(d)
L = as_float_array(L)
E = (np.pi * d**2) / 4 * L
if stiles_crawford_correction:
E *= (1 - (d / 9.7)**2 + (d / 12.4)**4)
return E
# %%
def function_contrast_sensitivity_Barten1999(u,
sigma=sigma_Barten1999(
0.5 / 60, 0.08 / 60, 3.0),
k=3.0,
T=0.1,
X_0=60,
X_max=12,
N_max=15,
n=0.03,
p=1.2 * 10**6,
E=retinal_illuminance_Barten1999(
20, 3),
phi_0=3 * 10**-8,
u_0=7):
"""
Parameters
----------
u : numeric
Spatial frequency :math:`u`.
sigma : numeric or array_like, optional
Standard deviation :math:`\sigma` of the line-spread function resulting
from the convolution of the different elements of the convolution
process.
k : numeric or array_like, optional
Signal-to-noise (SNR) ratio :math:`k`.
T : numeric or array_like, optional
Integration time :math:`T` in seconds of the eye .
X_0 : numeric or array_like, optional
Angular size :math:`X_0` in degrees of the object.
X_max : numeric or array_like, optional
Maximum angular size :math:`X_{max}` in degrees of the integration
area.
N_max : numeric or array_like, optional
Maximum number of cycles :math:`N_{max}` over which the eye can
integrate the information.
n : numeric or array_like, optional
Quantum efficiency of the eye :math:`n`.
p : numeric or array_like, optional
Photon conversion factor :math:`p` in
:math:`photons\div seconds\div degrees^2\div Trollands` that
depends on the light source.
E : numeric or array_like, optional
Retinal illuminance :math:`E` in Troland.
phi_0 : numeric or array_like, optional
Spectral density :math:`\phi_0` in :math:`seconds degrees^2` of the
neural noise.
u_0 : numeric or array_like, optional
Spatial frequency :math:`u_0` in :math:`cycles\div degrees` above which
the lateral inhibition ceases
Returns
-------
ndarray
Contrast sensitivity function :math:`S`.
Notes
-----
- This formula holds for the situation that the object dimensions in x
and y directions are equal. For non-equal dimensions, the factor
between the brackets that contains the object size has to be replaced
by :math:`1 / XY` where :math`X` and :math`Y` are given by ...
respectively.
"""
u = as_float_array(u)
k = as_float_array(k)
T = as_float_array(T)
X_0 = as_float_array(X_0)
X_max = as_float_array(X_max)
N_max = as_float_array(N_max)
n = as_float_array(n)
p = as_float_array(p)
E = as_float_array(E)
phi_0 = as_float_array(phi_0)
u_0 = as_float_array(u_0)
M_opt = optical_MTF_Barten1999(u, sigma)
S = (M_opt / k) / np.sqrt(
2 / T * (1 / X_0**2 + 1 / X_max**2 + u**2 / N_max**2) *
(1 / (n * p * E) + phi_0 / (1 - np.exp(-(u / u_0)**2))))
return S
# %%
L = np.linspace(0.01, 100, 10000)
# L = 500
X_0 = 60
d = pupil_diameter_Barten1999(L, X_0)
# d = 5 - 3 * np.tanh(0.4 * np.log(L))
sigma = sigma_Barten1999(0.5 / 60, 0.08 / 60, d)
E = retinal_illuminance_Barten1999(L, d, True)
# E = 14.7 * L**0.83
# u = np.linspace(0.1, 100, 10000)
u = X_0 / 15
y = lambda x: 1 / function_contrast_sensitivity_Barten1999(
u=u,
sigma=sigma,
k=3.0,
T=0.1,
X_0=X_0,
X_max=12,
N_max=15,
n=0.03,
p=1.2274*10**6,
E=E,
phi_0=3*10**-8,
u_0=7) * 2 * (1/ 1.27)
# plt.semilogx(u, optical_MTF_Barten1999(u, sigma))
# plt.semilogx(u, np.exp(-0.0016 * u**2 * (1 + 100 / L)**0.08))
# plt.show()
plot_single_function(
y,
samples=L,
log_x=10,
# log_y=10,
bounding_box=[0.1, 100, 0.001, 0.03],
**{'axes.grid.which': 'both'})
@KelSolaar

This comment has been minimized.

Copy link
Owner Author

KelSolaar commented Jan 31, 2019

barten

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.