Skip to content

Commit

Permalink
removed classes and set calibration as numpy arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlib committed Jan 6, 2024
1 parent 9146a0b commit 27fbcaf
Show file tree
Hide file tree
Showing 19 changed files with 374 additions and 162 deletions.
107 changes: 35 additions & 72 deletions openptv_python/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ def rotation_matrix(ext: np.ndarray) -> None:
('kappa', np.float64),
('dm', np.float64, (3, 3))
])
# Exterior = np.zeros(1, dtype=exterior_dtype).view(np.recarray) # initialize memory
Exterior = np.array((0, 0, 0, 0, 0, 0, np.eye(3)), dtype = exterior_dtype).view(np.recarray)
rotation_matrix(Exterior) # rotation should be a unit matrix
assert np.allclose(np.eye(3), Exterior['dm'])
Expand All @@ -70,13 +69,6 @@ def rotation_matrix(ext: np.ndarray) -> None:
])
Interior = np.array( (0, 0, 0), dtype = interior_dtype).view(np.recarray)

# def set_primary_point(point: np.ndarray) -> None:
# """Set the primary point of the camera."""
# self.xh, self.yh, self.cc = point

# def set_back_focal_distance(self, cc: float) -> None:
# """Set the back focal distance of the camera."""
# self.cc = cc

ap52_dtype = np.dtype([
('k1', np.float64),
Expand All @@ -89,60 +81,27 @@ def rotation_matrix(ext: np.ndarray) -> None:
])
ap_52 = np.array((0, 0, 0, 0, 0, 1, 0), dtype = ap52_dtype).view(np.recarray)


# class ap_52:
# """Additional parameters for distortion correction."""

# def __init__(self, k1=0.0, k2=0.0, k3=0.0, p1=0.0, p2=0.0, scx=1.0, she=0.0):
# self.k1 = k1
# self.k2 = k2
# self.k3 = k3
# self.p1 = p1
# self.p2 = p2
# self.scx = scx
# self.she = she

# def set_radial_distortion(self, dist_array: np.ndarray) -> None:
# """Set the radial distortion parameters k1, k2, k3."""
# self.k1, self.k2, self.k3 = dist_array

# def set_decentering(self, decent: np.ndarray) -> None:
# """Set the decentring parameters p1 and p2."""
# self.p1, self.p2 = decent

# def set_affine_distortion(self, affine: np.ndarray) -> None:
# """Set the affine distortion parameters scx and she."""
# self.scx, self.she = affine

mmlut_dtype = np.dtype([
('origin', np.float64, 3),
('nr', np.int32),
('nz', np.int32),
('rw', np.int32),
('data', np.float64, (3, 3))
])

mm_lut = np.array((np.zeros(3), 0, 0, 0, np.zeros((3, 3))), dtype = mmlut_dtype).view(np.recarray)

# class mm_lut:
# """Multimedia lookup table data structure."""

# def __init__(self, origin=None, nr=3, nz=3, rw=0, data=None):
# if origin is None:
# origin = np.zeros(3, dtype=np.float32)
# # if data is None:
# # data = np.zeros((nr, nz), dtype=np.float32) # Assuming data is a 2D array, adjust as needed
# self.origin = origin
# self.nr = nr
# self.nz = nz
# self.rw = rw
# self.data = data
mm_lut = np.array((np.zeros(3), 0, 0, 0), dtype = mmlut_dtype).view(np.recarray)
mm_lut_data = np.empty((mm_lut['nr'], mm_lut['nz']), dtype=np.float64)


class Calibration:
"""Calibration data structure."""

def __init__(self, ext_par=None, int_par=None, glass_par=None, added_par=None, mmlut=None):
def __init__(self,
ext_par=None,
int_par=None,
glass_par=None,
added_par=None,
mmlut=None,
mmlut_data=None):
if ext_par is None:
ext_par = Exterior.copy()
if int_par is None:
Expand All @@ -152,13 +111,17 @@ def __init__(self, ext_par=None, int_par=None, glass_par=None, added_par=None, m
if added_par is None:
added_par = ap_52.copy()
if mmlut is None:
mmlut = mm_lut.copy() # (np.zeros(3), 0, 0, 0, None)
mmlut = mm_lut.copy() # (np.zeros(3), 0, 0, 0)
if mmlut_data is None:
mmlut_data = np.zeros((mmlut.nr, mmlut.nz), dtype=np.float64)


self.ext_par = ext_par
self.int_par = int_par
self.glass_par = glass_par
self.added_par = added_par
self.mmlut = mmlut
self.mmlut_data = mmlut_data


@classmethod
Expand Down Expand Up @@ -205,7 +168,7 @@ def from_file(cls, ori_file: str, add_file: str):

tmp = [float(x) for x in fp.readline().split()] # xh,yh
tmp += [float(x) for x in fp.readline().split()] # cc
ret.int_par.set_primary_point(np.array(tmp))
ret.set_primary_point(np.array(tmp))
# self.int_par.set_back_focal_distance(float(fp.readline()))

# Glass
Expand All @@ -224,9 +187,9 @@ def from_file(cls, ori_file: str, add_file: str):
with open(add_file, "r", encoding="utf-8") as fp:
tmp = list(map(float, fp.readline().split()))

ret.added_par.set_radial_distortion(np.array(tmp[:3]))
ret.added_par.set_decentering(np.array(tmp[3:5]))
ret.added_par.set_affine_distortion(np.array(tmp[5:]))
ret.set_radial_distortion(np.array(tmp[:3]))
ret.set_decentering(np.array(tmp[3:5]))
ret.set_affine_distortion(np.array(tmp[5:]))

except FileNotFoundError:
print("no addpar fallback used") # Waits for proper logging.
Expand Down Expand Up @@ -324,10 +287,11 @@ def set_primary_point(self, prim_point_pos: np.ndarray) -> None:
of point from sensor middle and sensor-point distance, int_par this
order.
"""
if len(prim_point_pos) != 3:
raise ValueError("Expected a 3-element list")
if prim_point_pos.shape != (3,):
raise ValueError("Expected a 3-element array")

self.int_par.set_primary_point(prim_point_pos)
self.int_par.xh, self.int_par.yh, self.int_par.cc = prim_point_pos
# self.int_par.set_primary_point(prim_point_pos)

def get_primary_point(self):
"""
Expand All @@ -349,10 +313,11 @@ def set_radial_distortion(self, dist_coeffs: np.ndarray) -> None:
---------
dist_coeffs - length-3 array, holding k_i.
"""
if len(dist_coeffs) != 3:
if dist_coeffs.shape != (3,):
raise ValueError("Expected a 3-element array")

self.added_par.set_radial_distortion(dist_coeffs)
self.added_par.k1, self.added_par.k2, self.added_par.k3 = dist_coeffs


def get_radial_distortion(self):
"""
Expand All @@ -370,29 +335,27 @@ def set_decentering(self, decent: np.ndarray) -> None:
---------
decent - array, holding p_i
"""
if len(decent) != 2:
if decent.shape != (2,):
raise ValueError("Expected a 2-element list")

self.added_par.set_decentering(decent)
self.added_par.p1, self.added_par.p2 = decent

def get_decentering(self):
"""Return the decentering parameters [1] as a 2 element array, (p_1, p_2)."""
ret = np.empty(2)
ret[0] = self.added_par.p1
ret[1] = self.added_par.p2
return ret
return np.r_[self.added_par.p1, self.added_par.p2]

def set_affine_trans(self, affine: np.ndarray) -> None:
def set_affine_distortion(self, affine: np.ndarray) -> None:
"""
Set the affine transform parameters (x-scale, shear) of the image.
Arguments:
---------
affine - array, holding (x-scale, shear) int_par order.
"""
if len(affine) != 2:
if affine.shape != (2,):
raise ValueError("Expected a 2-element list")
self.added_par.set_affine_distortion(affine)

self.added_par.scx, self.added_par.she = affine

def get_affine(self):
"""Return the affine transform parameters [1] as a 2 element array, (scx, she)."""
Expand All @@ -419,9 +382,9 @@ def get_glass_vec(self) -> np.ndarray:
"""Return the glass vector, a 3-element array of float."""
return self.glass_par

def set_added_par(self, listpar: np.ndarray | list):
def set_added_par(self, ap52_array: np.ndarray):
"""Set added par from an numpy array of parameters."""
self.added_par = np.array(listpar, dtype=ap52_dtype).view(np.recarray)
self.added_par = np.array(tuple(ap52_array.tolist()), dtype = ap52_dtype).view(np.recarray)

def copy(self, new_copy):
"""Copy the calibration data to a new object."""
Expand Down Expand Up @@ -486,7 +449,7 @@ def read_ori(ori_file: str, add_file: str) -> Calibration:
return ret


def compare_exterior(e1: np.ndarray, e2: np.ndarray) -> bool:
def compare_exterior(e1: np.recarray, e2: np.recarray) -> bool:
"""Compare exterior orientation parameters."""
return (
np.allclose(e1['dm'], e2['dm'], atol=1e-6)
Expand Down
2 changes: 1 addition & 1 deletion openptv_python/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@

NUM_ITER = 80
POS_INF = 1e20
CONVERGENCE = 0.00001
CONVERGENCE = 0.0001
16 changes: 7 additions & 9 deletions openptv_python/multimed.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def multimed_r_nlay(cal: Calibration, mm: MultimediaPar, pos: np.ndarray) -> flo
return 1.0

# interpolation using the existing mmlut
if cal.mmlut.data is not None:
if cal.mmlut_data.shape != (0, 0):
# print("going into get_mmf_from_mmlut\n")
mmf = get_mmf_from_mmlut(cal, pos)
if mmf > 0:
Expand Down Expand Up @@ -273,7 +273,7 @@ def init_mmlut(vpar: VolumePar, cpar: ControlPar, cal: Calibration) -> Calibrati
z_max_t = z_max

# intersect with image vertices rays
cal_t = Calibration(mmlut=cal.mmlut)
cal_t = Calibration(mmlut = cal.mmlut.copy())

for i in range(2):
for j in range(2):
Expand Down Expand Up @@ -330,19 +330,19 @@ def init_mmlut(vpar: VolumePar, cpar: ControlPar, cal: Calibration) -> Calibrati
cal.mmlut.nz = nz
cal.mmlut.rw = rw

if cal.mmlut.data is None:
data = np.empty((nr, nz), dtype=np.float64)
if cal.mmlut_data.shape == (0, 0):
cal.mmlut_data = np.empty((nr, nz), dtype=np.float64)
Ri = np.arange(nr) * rw
Zi = np.arange(nz) * rw + z_min_t

for i in range(nr):
for j in range(nz):
xyz = np.r_[Ri[i] + cal_t.ext_par.x0,
cal_t.ext_par.y0, Zi[j]]
data.flat[i * nz + j] = multimed_r_nlay(cal_t, cpar.mm, xyz)
cal.mmlut_data.flat[i * nz + j] = multimed_r_nlay(cal_t, cpar.mm, xyz)

# print(f"filled mmlut data with {data}")
cal.mmlut.data = data
# cal.mmlut_data = data

return cal

Expand All @@ -351,15 +351,13 @@ def get_mmf_from_mmlut(cal: Calibration, pos: np.ndarray) -> float:
"""Get the refractive index of the medium at a given position."""
rw = cal.mmlut.rw
origin = cal.mmlut.origin
data = cal.mmlut.data.flatten() # type: ignore
data = cal.mmlut_data.flatten() # type: ignore
nz = cal.mmlut.nz
nr = cal.mmlut.nr

return fast_get_mmf_from_mmlut(rw, origin, data, nz, nr, pos)

# @njit


def fast_get_mmf_from_mmlut(
rw: int,
origin: np.ndarray,
Expand Down
14 changes: 7 additions & 7 deletions openptv_python/orientation.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,13 @@ def orient(
)

# Interpret the results
print(
f"Coefficients (beta): {beta} \n \
Residuals: {residuals} \n \
singular_values: {singular_values} \n \
rank: {rank} \n \
"
)
# print(
# f"Coefficients (beta): {beta} \n \
# Residuals: {residuals} \n \
# singular_values: {singular_values} \n \
# rank: {rank} \n \
# "
# )

# stopflag
stopflag = True
Expand Down
8 changes: 5 additions & 3 deletions openptv_python/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,10 @@ class OrientPar(Parameters):
@classmethod
def from_file(cls, filename: str):
"""Read orientation parameters from file and returns orient_par object."""
ret = cls()
try:
with open(filename, "r", encoding="utf-8") as file:
ret = cls()

ret.useflag = int(file.readline().strip()) # /* use every point or every other pt */
ret.ccflag = int(file.readline().strip()) # /* change back focal distance */
ret.xhflag = int(file.readline().strip()) # /* change xh point, 1-yes, 0-no */
Expand All @@ -729,10 +730,11 @@ def from_file(cls, filename: str):
ret.scxflag = int(file.readline().strip()) # /* scx - scaling */
ret.sheflag = int(file.readline().strip()) # /* she - shearing */
ret.interfflag = int(file.readline().strip()) # /* interface glass vector */
return ret

except IOError:
print(f"Could not open orientation parameters file {filename}.")
return None

return ret



Expand Down
10 changes: 6 additions & 4 deletions openptv_python/trafo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from numba import float64, int32, njit
from numpy import cos, sin, sqrt

from .calibration import Calibration, ap_52
from .calibration import Calibration
from .parameters import ControlPar


Expand Down Expand Up @@ -147,7 +147,7 @@ def fast_arr_metric_to_pixel(

def distort_brown_affine(x: float,
y: float,
ap: ap_52
ap: np.recarray,
) -> Tuple[float, float]:
"""Distort a point using the Brown affine model."""
if x == 0 and y == 0:
Expand All @@ -160,7 +160,9 @@ def distort_brown_affine(x: float,
# print(f"x {x}, y {y}")


@njit(float64[:](float64,float64,float64,float64,float64,float64,float64,float64,float64))
# @njit(float64[:]
# (float64,float64,float64,float64,float64,
# float64,float64,float64,float64))
def fast_distort_brown_affine(
x: float,
y: float,
Expand Down Expand Up @@ -198,7 +200,7 @@ def fast_distort_brown_affine(


def correct_brown_affine(
x: float, y: float, ap: ap_52, tol: float = 1e-5
x: float, y: float, ap: np.recarray, tol: float = 1e-5
) -> Tuple[float, float]:
"""Correct a distorted point using the Brown affine model."""
return fast_correct_brown_affine(x, y, ap.k1, ap.k2, ap.k3, ap.p1, ap.p2, ap.she, ap.scx, tol)
Expand Down
Loading

0 comments on commit 27fbcaf

Please sign in to comment.