Source code for colourlab.image_core
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
image_core: Colour image core operations, part of the colourlab package
Copyright (C) 2017 Ivar Farup
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import numpy as np
import sys
try: # Hack to use numba only when installed
from numba import jit # (mainly to avoid trouble with Travis)
except ImportError:
def jit(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
if 'sphinx' in sys.modules: # Hack to make sphinx avoid using @jit
[docs] def jit(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
ANGLE_PRIME = 95273 # for LUTs, to be true to the original
RADIUS_PRIME = 29537 # for LUTs, to be true to the original
[docs]@jit
def stress(im, ns=3, nit=5, R=0):
"""
Compute the stress image and range.
Parameters
----------
im : ndarray
Greyscale image
ns : int
Number of sample points
nit : int
Number of iterations
R : int
Maximum radius. If R=0, the diagonal of the image is used.
Returns
-------
stress_im : ndarray
The result of stress
range_im : ndarray
The range image (see paper)
"""
theta = np.random.rand(ANGLE_PRIME) * 2 * np.pi # create LUTs
lut_cos = np.cos(theta)
lut_sin = np.sin(theta)
radiuses = np.random.rand(RADIUS_PRIME)
if R == 0:
R = np.sqrt(im.shape[0]**2 + im.shape[1]**2)
angle_no = 0 # indexes to LUTs
radius_no = 0
res_v = np.zeros(im.shape)
res_r = np.zeros(im.shape)
for i in range(im.shape[0]): # iterate over image
for j in range(im.shape[1]):
for it in range(nit): # iterations
best_min = im[i, j]
best_max = best_min
for s in range(ns): # samples
while True: # "repeat"
angle_no = (angle_no + 1) % ANGLE_PRIME
radius_no = (radius_no + 1) % RADIUS_PRIME
u = i + int(R * radiuses[radius_no] *
lut_cos[angle_no])
v = j + int(R * radiuses[radius_no] *
lut_sin[angle_no])
if ((u < im.shape[0]) and
(u >= 0) and
(v < im.shape[1]) and
(v >= 0)):
break # "until"
if best_min > im[u, v]:
best_min = im[u, v]
if best_max < im[u, v]:
best_max = im[u, v] # end samples
ran = best_max - best_min
if ran == 0:
s = 0.5
else:
s = (im[i, j] - best_min) / ran
res_v[i, j] += s
res_r[i, j] += ran # end iterations
return res_v / nit, res_r / nit