From 3a2ba7f31c388dc27d3f7dab332b48218392309b Mon Sep 17 00:00:00 2001 From: Alex Liberzon Date: Sat, 18 Nov 2023 18:09:58 +0200 Subject: [PATCH] seems that most of it works --- openptv_python/calibration.py | 16 ++++----- openptv_python/correspondences.py | 59 +++++++++++++++++++------------ openptv_python/epi.py | 3 -- openptv_python/find_candidate.py | 2 +- openptv_python/imgcoord.py | 3 ++ openptv_python/orientation.py | 5 ++- openptv_python/segmentation.py | 6 ++-- openptv_python/vec_utils.py | 5 +-- tests/gen_track_data.py | 25 ++++++++----- 9 files changed, 73 insertions(+), 51 deletions(-) diff --git a/openptv_python/calibration.py b/openptv_python/calibration.py index d226018..7e21639 100644 --- a/openptv_python/calibration.py +++ b/openptv_python/calibration.py @@ -2,7 +2,7 @@ import pathlib from dataclasses import dataclass, field -from typing import Optional +from typing import List, Optional import numpy as np @@ -111,15 +111,15 @@ class ap_52: scx: float = 1.0 she: float = 0.0 - def set_radial_distortion(self, dist_list: np.ndarray) -> None: + def set_radial_distortion(self, dist_list: List[float]) -> None: """Set the radial distortion parameters k1, k2, k3.""" self.k1, self.k2, self.k3 = dist_list - def set_decentering(self, decent: np.ndarray) -> None: + def set_decentering(self, decent: List[float]) -> None: """Set the decentring parameters p1 and p2.""" self.p1, self.p2 = decent - def set_affine_distortion(self, affine: np.ndarray) -> None: + def set_affine_distortion(self, affine: List[float]) -> None: """Set the affine distortion parameters scx and she.""" self.scx, self.she = affine @@ -214,7 +214,7 @@ def from_file(self, ori_file: str, add_file: str) -> None: # Additional parameters try: with open(add_file, "r", encoding="utf-8") as fp: - tmp = np.array(list(map(float, fp.readline().split()))) + tmp = list(map(float, fp.readline().split())) self.added_par.set_radial_distortion(tmp[:3]) self.added_par.set_decentering(tmp[3:5]) @@ -313,7 +313,7 @@ def get_primary_point(self): """ return np.r_[self.int_par.xh, self.int_par.yh, self.int_par.cc] - def set_radial_distortion(self, dist_coeffs: np.ndarray): + def set_radial_distortion(self, dist_coeffs: List[float]) -> None: """ Set the parameters for the image radial distortion, where the x/y. @@ -337,7 +337,7 @@ def get_radial_distortion(self): """ return np.r_[self.added_par.k1, self.added_par.k2, self.added_par.k3] - def set_decentering(self, decent: np.ndarray) -> None: + def set_decentering(self, decent: List[float]) -> None: """ Set the parameters of decentering distortion (a.k.a. p1, p2, see [1]). @@ -357,7 +357,7 @@ def get_decentering(self): ret[1] = self.added_par.p2 return ret - def set_affine_trans(self, affine: np.ndarray) -> None: + def set_affine_trans(self, affine: List[float]) -> None: """ Set the affine transform parameters (x-scale, shear) of the image. diff --git a/openptv_python/correspondences.py b/openptv_python/correspondences.py index 6729123..631d5a0 100644 --- a/openptv_python/correspondences.py +++ b/openptv_python/correspondences.py @@ -70,31 +70,46 @@ def safely_allocate_target_usage_marks( # lists[c1][c2] = None +# def safely_allocate_adjacency_lists( +# num_cams: int, target_counts: List[int] +# ) -> List[List[List[Correspond]]]: +# """Allocate adjacency lists.""" +# lists = [[[] for _ in range(num_cams)] for _ in range(num_cams)] +# error = 0 + +# for c1 in range(num_cams - 1): +# for c2 in range(c1 + 1, num_cams): +# if error == 0: +# lists[c1][c2] = [Correspond() for _ in range(target_counts[c1])] # type: ignore +# if not lists[c1][c2]: +# error = 1 +# lists[c1][c2] = [] + +# for edge in range(target_counts[c1]): +# lists[c1][c2][edge].n = 0 +# lists[c1][c2][edge].p1 = 0 +# else: +# lists[c1][c2] = [] + +# if error == 0: +# return lists + +# return [] + + def safely_allocate_adjacency_lists( num_cams: int, target_counts: List[int] ) -> List[List[List[Correspond]]]: - """Allocate adjacency lists.""" - lists = [[[float] for _ in range(num_cams)] for _ in range(num_cams)] - error = 0 - - for c1 in range(num_cams - 1): - for c2 in range(c1 + 1, num_cams): - if error == 0: - lists[c1][c2] = [Correspond() for _ in range(target_counts[c1])] # type: ignore - if not lists[c1][c2]: - error = 1 - lists[c1][c2] = [] - - for edge in range(target_counts[c1]): - lists[c1][c2][edge].n = 0 - lists[c1][c2][edge].p1 = 0 - else: - lists[c1][c2] = [] - - if error == 0: - return lists - - return [] + try: + lists = [ + [[Correspond() for _ in range(target_counts[c1])] for _ in range(num_cams)] + for c1 in range(num_cams) + ] + except MemoryError: + print("Memory allocation failed.") + lists = [] + + return lists def four_camera_matching( diff --git a/openptv_python/epi.py b/openptv_python/epi.py index a779188..0ee3f5c 100644 --- a/openptv_python/epi.py +++ b/openptv_python/epi.py @@ -92,9 +92,6 @@ def epi_mm(xl, yl, cal1, cal2, mmp, vpar) -> tuple[float, float, float, float]: ------- _type_: _description_ """ - z_min, z_max = 0, 0 - # pos, v, X = [0, 0, 0], [0, 0, 0], [0, 0, 0] - pos, v = ray_tracing(xl, yl, cal1, mmp) # calculate min and max depth for position (valid only for one setup) diff --git a/openptv_python/find_candidate.py b/openptv_python/find_candidate.py index 2e4a9c9..8a4a1ea 100644 --- a/openptv_python/find_candidate.py +++ b/openptv_python/find_candidate.py @@ -54,7 +54,7 @@ def find_candidate( ------- cand: list of candidates, or empty list if nothing is found """ - cand = [] + cand: List[Candidate] = [] # The image space is the image plane of the camera. The image space is # given in millimeters of sensor size and the origin is in the center of the sensor. diff --git a/openptv_python/imgcoord.py b/openptv_python/imgcoord.py index 6ddbb70..30e1bbb 100644 --- a/openptv_python/imgcoord.py +++ b/openptv_python/imgcoord.py @@ -102,6 +102,9 @@ def img_coord( ) -> Tuple[float, float]: """Image coordinate.""" # Estimate metric coordinates in image space using flat_image_coord() + if pos.shape[0] != 3: + raise ValueError("pos must be a 3D vector") + x, y = flat_image_coord(pos, cal, mm) # print(f"flat_image_coord: x = {x}, y = {y}") diff --git a/openptv_python/orientation.py b/openptv_python/orientation.py index e1a69d8..ef7a42e 100644 --- a/openptv_python/orientation.py +++ b/openptv_python/orientation.py @@ -113,7 +113,7 @@ def weighted_dumbbell_precision( """Calculate the weighted dumbbell precision of the current orientation.""" res = [np.empty((3,)), np.empty((3,))] dtot = 0.0 - len_err_tot = 0.0 + len_err_tot: float = 0.0 num_targs = targets.shape[0] num_cams = targets.shape[1] @@ -124,7 +124,7 @@ def weighted_dumbbell_precision( if pt % 2 == 1: dist = np.linalg.norm(res[0] - res[1]) - len_err_tot += 1 - ( + len_err_tot += 1.0 - float( db_length / dist if dist > db_length else dist / db_length ) @@ -590,7 +590,6 @@ def raw_orient( beta = np.zeros(6) dm = 0.0001 drad = 0.0001 - xp, yp, xc, yc = 0, 0, 0, 0 pos = np.zeros(3) cal.added_par.k1 = 0 diff --git a/openptv_python/segmentation.py b/openptv_python/segmentation.py index 6d9d3ea..0012257 100644 --- a/openptv_python/segmentation.py +++ b/openptv_python/segmentation.py @@ -238,9 +238,9 @@ def peak_fit( gv1, gv2 = 0, 0 x1, x2, y1, y2, s12 = 0.0, 0.0, 0.0, 0.0, 0.0 label_img = [0] * (imx * imy) - peaks = [] - waitlist = [[]] - pix = [] + peaks: List[Peak] = [] + waitlist: List[List[int]] = [[]] + pix: List[Target] = [] n_target = 0 for i in range(ymin, ymax - 1): diff --git a/openptv_python/vec_utils.py b/openptv_python/vec_utils.py index 424ec0c..b401358 100644 --- a/openptv_python/vec_utils.py +++ b/openptv_python/vec_utils.py @@ -54,9 +54,10 @@ def vec_norm(vec: np.ndarray) -> float: return float(np.linalg.norm(vec)) -def vec_dot(vec1: np.ndarray, vec2: np.ndarray) -> np.ndarray: +def vec_dot(vec1: np.ndarray, vec2: np.ndarray) -> float: """vec_dot() gives the dot product of two vectors as lists of floats.""" - return np.dot(vec1, vec2) + val = np.dot(vec1, vec2) + return float(val) def vec_cross(vec1: np.ndarray, vec2: np.ndarray) -> np.ndarray: diff --git a/tests/gen_track_data.py b/tests/gen_track_data.py index e743638..af6533b 100644 --- a/tests/gen_track_data.py +++ b/tests/gen_track_data.py @@ -1,3 +1,5 @@ +from typing import List + import numpy as np from openptv_python.calibration import Calibration @@ -23,7 +25,10 @@ cpar = ControlPar(num_cams=3) cpar.from_file("testing_fodder/track/parameters/control_newpart.par") -targs = [] +targs: List[List[List[float]]] = [ + [[0.0, 0.0] for _ in range(num_frames)] for _ in range(num_cams) +] + for cam in range(num_cams): cal = Calibration() cal.from_file( @@ -31,14 +36,15 @@ "testing_fodder/cal/cam1.tif.addpar", ) # check this out - x, y = img_coord(part_traject, cal, cpar.mm) - x, y = metric_to_pixel(x, y, cpar) - targs.append([x, y]) + for frame in range(num_frames): + x, y = img_coord(part_traject[frame, :], cal, cpar.mm) + x, y = metric_to_pixel(x, y, cpar) + targs[cam][frame] = [x, y] for frame in range(num_frames): # write 3D positions: with open( - "testing_fodder/track/res_orig/particles.%d" % (frame + 1), "w" + f"testing_fodder/track/res_orig/particles.{frame+1}", "w", encoding="utf-8" ) as outfile: # Note correspondence to the single target in each frame. outfile.writelines( @@ -48,7 +54,7 @@ 1, part_traject[frame, 0], part_traject[frame, 1], - part_traject[frame, 1], + part_traject[frame, 2], 0, 0, 0, @@ -60,16 +66,17 @@ # write associated targets from all cameras: for cam in range(num_cams): with open( - "testing_fodder/track/newpart/cam%d.%04d_targets" % (cam + 1, frame + 1), + f"testing_fodder/track/newpart/cam{cam+1}.{frame+1:04d}_targets", "w", + encoding="utf-8", ) as outfile: outfile.writelines( [ str(1) + "\n", "{:5d}{:10.3f}{:10.3f}{:5d}{:5d}{:5d}{:10d}{:5d}\n".format( 0, - targs[cam][frame, 0], - targs[cam][frame, 1], + targs[cam][frame][0], + targs[cam][frame][1], 100, 10, 10,