diff --git a/pyptv/calibration_gui.py b/pyptv/calibration_gui.py index 9227d32..69e0eed 100644 --- a/pyptv/calibration_gui.py +++ b/pyptv/calibration_gui.py @@ -32,7 +32,7 @@ # from chaco.tools.simple_zoom import SimpleZoom from pyptv.text_box_overlay import TextBoxOverlay -from pyptv.code_editor import codeEditor +from pyptv.code_editor import oriEditor, addparEditor from pyptv.quiverplot import QuiverPlot @@ -47,6 +47,7 @@ from pyptv import ptv, parameter_gui, parameters as par +from scipy.optimize import minimize # ------------------------------------------- class ClickerTool(ImageInspectorTool): @@ -340,6 +341,7 @@ class CalibrationGUI(HasTraits): button_checkpoint = Button() button_ap_figures = Button() button_edit_ori_files = Button() + button_edit_addpar_files = Button() button_test = Button() # --------------------------------------------------- @@ -480,6 +482,11 @@ def __init__(self, active_path: Path): label="Edit ori files", show_label=False, ), + Item( + name="button_edit_addpar_files", + label="Edit addpar files", + show_label=False, + ), show_left=False, ), ), @@ -872,8 +879,9 @@ def _button_fine_orient_fired(self): op.shear, ] + # set flags for cc, xh, yh only flags = [] - for name, op_name in zip(names, op_names): + for name, op_name in zip(names[:3], op_names[:3]): if op_name == 1: flags.append(name) @@ -968,24 +976,99 @@ def _button_fine_orient_fired(self): else: targs = self.sorted_targs[i_cam] - try: - residuals, targ_ix, err_est = full_calibration( - self.cals[i_cam], - self.cal_points["pos"], - targs, - self.cpar, - flags, - ) - except BaseException as exc: - raise ValueError("full calibration failed\n") from exc - # save the results + # try: + print(f"First calibrate only external and flags: {flags} \n") + residuals, targ_ix, err_est = full_calibration( + self.cals[i_cam], + self.cal_points["pos"], + targs, + self.cpar, + flags, + ) + + # this chunk optimizes for radial distortion + if np.any(op_names[3:6]): + sol = minimize(self._residuals_k, + self.cals[i_cam].get_radial_distortion(), + args=(self.cals[i_cam], + all_known, + all_detected, + self.cpar + ), + method='Nelder-Mead', + tol=1e-11, + options={'disp':True}, + ) + radial = sol.x + self.cals[i_cam].set_radial_distortion(radial) + else: + radial = self.cals[i_cam].get_radial_distortion() + + if np.any(op_names[5:8]): + # now decentering + sol = minimize(self._residuals_p, + self.cals[i_cam].get_decentering(), + args=(self.cals[i_cam], + all_known, + all_detected, + self.cpar + ), + method='Nelder-Mead', + tol=1e-11, + options={'disp':True}, + ) + decentering = sol.x + self.cals[i_cam].set_decentering(decentering) + else: + decentering = self.cals[i_cam].get_decentering() + + if np.any(op_names[8:]): + # now affine + sol = minimize(self._residuals_s, + self.cals[i_cam].get_affine(), + args=(self.cals[i_cam], + all_known, + all_detected, + self.cpar + ), + method='Nelder-Mead', + tol=1e-11, + options={'disp':True}, + ) + affine = sol.x + self.cals[i_cam].set_affine_trans(affine) + + else: + affine = self.cals[i_cam].get_affine() + + + # Now project and estimate full residuals + self._project_cal_points(i_cam) + + residuals = self._residuals_combined( + np.r_[radial, decentering, affine], + self.cals[i_cam], + all_known, + all_detected, + self.cpar + ) + + residuals /= 100 + + targ_ix = np.arange(len(all_detected)) + + # save the results from self.cals[i_cam] self._write_ori(i_cam, addpar_flag=True) - # Plot the output - # self.reset_plots() + # x, y = [], [] + # for r, t in zip(residuals, targ_ix): + # if t != -999: + # pos = targs[t].pos() + # x.append(pos[0]) + # y.append(pos[1]) x, y = [], [] - for r, t in zip(residuals, targ_ix): + for t in targ_ix: if t != -999: pos = targs[t].pos() x.append(pos[0]) @@ -1012,6 +1095,78 @@ def _button_fine_orient_fired(self): self.status_text = "Orientation finished." + # def _error_function(self, x, cal, XYZ, xy, cpar): + # """Error function for scipy.optimize.minimize. + + # Args: + # x (array-like): Array of parameters. + # cal (Calibration): Calibration object. + # XYZ (array-like): 3D coordinates. + # xy (array-like): 2D image coordinates. + # cpar (CPar): Camera parameters. + + # Returns: + # float: Error value. + # """ + # residuals = self._residuals_radial(x, cal, XYZ, xy, cpar) + # return np.sum(residuals**2) + + def _residuals_k(self, x, cal, XYZ, xy, cpar): + """Residuals due to radial distortion + + Args: + x (array-like): Array of parameters. + cal (Calibration): Calibration object. + XYZ (array-like): 3D coordinates. + xy (array-like): 2D image coordinates. + cpar (CPar): Camera parameters. + + Returns: + residuals: Distortion in pixels + """ + + cal.set_radial_distortion(x) + targets = convert_arr_metric_to_pixel( + image_coordinates(XYZ, cal, cpar.get_multimedia_params()), + cpar + ) + residuals = xy[:,1:] - targets + return np.sum(residuals**2) + + def _residuals_p(self, x, cal, XYZ, xy, cpar): + """Residuals due to decentering """ + cal.set_decentering(x) + targets = convert_arr_metric_to_pixel( + image_coordinates(XYZ, cal, cpar.get_multimedia_params()), + cpar + ) + residuals = xy[:,1:] - targets + return np.sum(residuals**2) + + def _residuals_s(self, x, cal, XYZ, xy, cpar): + """Residuals due to decentering """ + cal.set_affine_trans(x) + targets = convert_arr_metric_to_pixel( + image_coordinates(XYZ, cal, cpar.get_multimedia_params()), + cpar + ) + residuals = xy[:,1:] - targets + return np.sum(residuals**2) + + def _residuals_combined(self, x, cal, XYZ, xy, cpar): + """Combined residuals """ + + cal.set_radial_distortion(x[:3]) + cal.set_decentering(x[3:5]) + cal.set_affine_trans(x[5:]) + + targets = convert_arr_metric_to_pixel( + image_coordinates(XYZ, cal, cpar.get_multimedia_params()), + cpar + ) + residuals = xy[:,1:] - targets + return residuals + def _write_ori(self, i_cam, addpar_flag=False): """Writes ORI and ADDPAR files for a single calibration result of i_cam @@ -1116,9 +1271,14 @@ def reset_show_images(self): cam._plot.request_redraw() def _button_edit_ori_files_fired(self): - editor = codeEditor(path=self.par_path) + editor = oriEditor(path=self.par_path) + editor.edit_traits(kind="livemodal") + + def _button_edit_addpar_files_fired(self): + editor = addparEditor(path=self.par_path) editor.edit_traits(kind="livemodal") + def drawcross(self, str_x, str_y, x, y, color1, size1, i_cam=None): """ @@ -1174,6 +1334,7 @@ def _read_cal_points(self): with open(self.calParams.fixp_name, 'r') as file: first_line = file.readline() + print(first_line) if ',' in first_line: delimiter=',' elif '\t' in first_line: @@ -1198,6 +1359,7 @@ def _read_cal_points(self): if len(sys.argv) == 1: active_path = Path("../test_cavity/parametersRun1") + active_path = Path("/home/user/Downloads/rbc300/parametersMultiPlane") else: active_path = Path(sys.argv[0]) diff --git a/pyptv/code_editor.py b/pyptv/code_editor.py index 91f09b7..6f9cab5 100644 --- a/pyptv/code_editor.py +++ b/pyptv/code_editor.py @@ -28,41 +28,47 @@ def get_path(filename): ) -def get_code(path): - f = open(path, "r") +def get_code(path: Path): + """ Read the code from the file """ + + # print(f"Read from {path}: {path.exists()}") + with open(path, "r", encoding="utf-8") as f: + retCode = f.read() + + # print(retCode) - retCode = f.read() - f.close() return retCode -class oriEditor(HasTraits): - file_Path = File - ori_Code = Code() - ori_Save = Button(label="Save") +class codeEditor(HasTraits): + file_Path = Path + _Code = Code() + save_button = Button(label="Save") buttons_group = Group( - Item(name="file_Path", style="simple", show_label=False, width=0.3), - Item(name="ori_Save", show_label=False), + Item(name="file_Path", style="simple", show_label=True, width=0.3), + Item(name="save_button", show_label=True), orientation="horizontal", ) traits_view = View( Group( - Item(name="ori_Code", show_label=False, height=300, width=650), + Item(name="_Code", show_label=False, height=300, width=650), buttons_group, ) ) - def _ori_Save_fired(self, filename, code): - f = open(self.file_Path, "w") - f.write(self.ori_Code) - f.close() - - def __init__(self, file_path): + def _save_button_fired(self): + with open(self.file_Path, "w", encoding="utf-8") as f: + # print(f"Saving to {self.file_Path}") + # print(f"Code: {self._Code}") + f.write(self._Code) + + print(f"Saved to {self.file_Path}") + + def __init__(self, file_path: Path): self.file_Path = file_path - self.ori_Code = get_code(file_path) - + self._Code = get_code(file_path) -class codeEditor(HasTraits): +class oriEditor(HasTraits): # number of images n_img = Int() @@ -86,6 +92,47 @@ class codeEditor(HasTraits): title="Camera's orientation files", ) + def __init__(self, path: Path): + """ Initialize by reading parameters and filling the editor windows """ + # load ptv_par + ptvParams = par.PtvParams(path=path) + ptvParams.read() + self.n_img = ptvParams.n_img + + # load cal_ori + calOriParams = par.CalOriParams(self.n_img) + calOriParams.read() + + for i in range(self.n_img): + self.oriEditors.append( + codeEditor(Path(calOriParams.img_ori[i])) + ) + + +class addparEditor(HasTraits): + + # number of images + n_img = Int() + + addparEditors = List + + # view + traits_view = View( + Item( + "addparEditors", + style="custom", + editor=ListEditor( + use_notebook=True, + deletable=False, + dock_style="tab", + page_name=".file_Path", + ), + show_label=False, + ), + buttons=["Cancel"], + title="Camera's additional parameters files", + ) + def __init__(self, path): """ Initialize by reading parameters and filling the editor windows """ # load ptv_par @@ -98,6 +145,6 @@ def __init__(self, path): calOriParams.read() for i in range(self.n_img): - self.oriEditors.append( - oriEditor(calOriParams.img_ori[i]) + self.addparEditors.append( + codeEditor(Path(calOriParams.img_ori[i].replace('ori', 'addpar'))) ) diff --git a/pyptv/optimize_calibration.ipynb b/pyptv/optimize_calibration.ipynb new file mode 100644 index 0000000..a1efda9 --- /dev/null +++ b/pyptv/optimize_calibration.ipynb @@ -0,0 +1,445 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "# Jupyter notebook version of calibration" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "# from Yosef Meller's PBI\n", + "\n", + "import shutil\n", + "import numpy as np\n", + "import numpy.random as rnd\n", + "from optv.calibration import Calibration\n", + "from optv.imgcoord import image_coordinates\n", + "from optv.transforms import convert_arr_metric_to_pixel\n", + "from optv.segmentation import target_recognition\n", + "from optv.imgcoord import image_coordinates\n", + "from optv.transforms import convert_arr_metric_to_pixel\n", + "from optv.orientation import match_detection_to_ref\n", + "from optv.orientation import external_calibration, full_calibration\n", + "from optv.calibration import Calibration\n", + "from optv.tracking_framebuf import TargetArray\n", + "\n", + "\n", + "from pyptv import ptv, parameter_gui, parameters as par" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "par_path = Path(\"/home/user/Downloads/rbc300/parametersMultiPlain\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "def get_pos(inters, R, angs):\n", + " # Transpose of http://planning.cs.uiuc.edu/node102.html\n", + " # Also consider the angles are reversed when moving from camera frame to\n", + " # global frame.\n", + " s = np.sin(angs)\n", + " c = np.cos(angs)\n", + " pos = inters + R*np.r_[ s[1], -c[1]*s[0], c[1]*c[0] ]\n", + " return pos\n", + "\n", + "def get_polar_rep(pos, angs):\n", + " \"\"\"\n", + " Returns the point of intersection with zero Z plane, and distance from it.\n", + " \"\"\"\n", + " s = np.sin(angs)\n", + " c = np.cos(angs)\n", + " zdir = -np.r_[ s[1], -c[1]*s[0], c[1]*c[0] ]\n", + " \n", + " c = -pos[2]/zdir[2]\n", + " inters = pos + c*zdir\n", + " R = np.linalg.norm(inters - pos)\n", + " \n", + " return inters[:2], R\n", + " \n", + "def gen_calib(inters, R, angs, glass_vec, prim_point, radial_dist, decent):\n", + " pos = get_pos(inters, R, angs)\n", + " return Calibration(pos, angs, prim_point, radial_dist, decent, \n", + " np.r_[1, 0], glass_vec)\n", + "\n", + "def fitness(solution, calib_targs, calib_detect, glass_vec, cpar):\n", + " \"\"\"\n", + " Checks the fitness of an evolutionary solution of calibration values to \n", + " target points. Fitness is the sum of squares of the distance from each \n", + " guessed point to the closest neighbor.\n", + " \n", + " Arguments:\n", + " solution - array, concatenated: position of intersection with Z=0 plane; 3 \n", + " angles of exterior calibration; primary point (xh,yh,cc); 3 radial\n", + " distortion parameters; 2 decentering parameters.\n", + " calib_targs - a (p,3) array of p known points on the calibration target.\n", + " calib_detect - a (d,2) array of d detected points in the calibration \n", + " target.\n", + " cpar - a ControlParams object with image data.\n", + " \"\"\"\n", + " # Breakdown of of agregate solution vector:\n", + " inters = np.zeros(3)\n", + " inters[:2] = solution[:2]\n", + " R = solution[2]\n", + " angs = solution[3:6] \n", + " prim_point = solution[6:9]\n", + " rad_dist = solution[9:12]\n", + " decent = solution[12:14]\n", + " \n", + " # Compare known points' projections to detections:\n", + " cal = gen_calib(inters, R, angs, glass_vec, prim_point, rad_dist, decent)\n", + " known_proj = image_coordinates(calib_targs, cal, \n", + " cpar.get_multimedia_params())\n", + " known_2d = convert_arr_metric_to_pixel(known_proj, cpar)\n", + " dists = np.linalg.norm(\n", + " known_2d[None,:,:] - calib_detect[:,None,:], axis=2).min(axis=0)\n", + " \n", + " return np.sum(dists**2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os\n", + "working_folder = Path(\"/home/user/Downloads/rbc300\")\n", + "working_folder.exists()\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/user/Downloads/rbc300\n" + ] + } + ], + "source": [ + "os.chdir(working_folder)\n", + "print(os.getcwd())\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "calOriParams = par.CalOriParams(path = working_folder / \"parameters\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "def g(f):\n", + " \"\"\" Returns a line without white spaces \"\"\"\n", + " return f.readline().strip()\n", + "\n", + "def read(filepath, n_img = 4):\n", + " with open(filepath, \"r\") as f:\n", + "\n", + " fixp_name = Path(g(f))\n", + " fixp_name.exists()\n", + "\n", + " img_cal_name = []\n", + " img_ori = []\n", + " for i in range(n_img):\n", + " img_cal_name.append(g(f))\n", + " img_ori.append(g(f))\n", + "\n", + " tiff_flag = int(g(f)) != 0 # <-- overwrites the above\n", + " pair_flag = int(g(f)) != 0\n", + " chfield = int(g(f))\n", + "\n", + "\n", + " # test if files are present, issue warnings\n", + " for i in range(n_img):\n", + " Path(img_cal_name[i]).exists()\n", + " Path(img_ori[i]).exists()\n", + "\n", + " return fixp_name, img_cal_name, img_ori, tiff_flag, pair_flag, chfield\n" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(['calibration_images/c0/calib_c0.tif',\n", + " 'calibration_images/c1/calib_c1.tif',\n", + " 'calibration_images/c2/calib_c2.tif',\n", + " 'calibration_images/c3/calib_c3.tif'],\n", + " ['cal/cam1.tif.ori',\n", + " 'cal/cam2.tif.ori',\n", + " 'cal/cam3.tif.ori',\n", + " 'cal/cam4.tif.ori'])" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fixp_name, img_cal_name, img_ori, tiff_flag, pair_flag, chfield = read(working_folder / \"parametersMultiPlane\" / \"cal_ori.par\")\n", + "img_cal_name, img_ori" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[PosixPath('/home/user/Downloads/rbc300/parameters/multi_planes.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/criteria.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/track.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/detect_plate.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/sequence.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/shaking.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/man_ori.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/orient.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/targ_rec.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/examine.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/cal_ori.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/unsharp_mask.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/ptv.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/pft_version.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/dumbbell.par'),\n", + " PosixPath('/home/user/Downloads/rbc300/parameters/sortgrid.par')]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(calOriParams.path.rglob('*.par'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# for f in calOriParams.img_ori[:4]:\n", + "# print(f\"Backing up {f}\")\n", + "# shutil.copyfile(f, f + \".bck\")\n", + "# g = f.replace(\"ori\", \"addpar\")\n", + "# shutil.copyfile(g, g + \".bck\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "op = par.OrientParams()\n", + "op.read()\n", + "\n", + "# recognized names for the flags:\n", + "names = [\n", + " \"cc\",\n", + " \"xh\",\n", + " \"yh\",\n", + " \"k1\",\n", + " \"k2\",\n", + " \"k3\",\n", + " \"p1\",\n", + " \"p2\",\n", + " \"scale\",\n", + " \"shear\",\n", + "]\n", + "op_names = [\n", + " op.cc,\n", + " op.xh,\n", + " op.yh,\n", + " op.k1,\n", + " op.k2,\n", + " op.k3,\n", + " op.p1,\n", + " op.p2,\n", + " op.scale,\n", + " op.shear,\n", + "]\n", + "\n", + "flags = []\n", + "for name, op_name in zip(names, op_names):\n", + " if op_name == 1:\n", + " flags.append(name)\n", + "\n", + "for i_cam in range(self.n_cams): # iterate over all cameras\n", + "\n", + " if self.epar.Combine_Flag:\n", + "\n", + " self.status_text = \"Multiplane calibration.\"\n", + " \"\"\" Performs multiplane calibration, in which for all cameras the\n", + " pre-processed planes in multi_plane.par combined.\n", + " Overwrites the ori and addpar files of the cameras specified\n", + " in cal_ori.par of the multiplane parameter folder\n", + " \"\"\"\n", + "\n", + " all_known = []\n", + " all_detected = []\n", + "\n", + " for i in range(\n", + " self.MultiParams.n_planes\n", + " ): # combine all single planes\n", + "\n", + " # c = self.calParams.img_ori[i_cam][-9] # Get camera id\n", + " # not all ends with a number\n", + " c = re.findall(\"\\\\d+\", self.calParams.img_ori[i_cam])[0]\n", + "\n", + " file_known = (\n", + " self.MultiParams.plane_name[i] + c + \".tif.fix\"\n", + " )\n", + " file_detected = (\n", + " self.MultiParams.plane_name[i] + c + \".tif.crd\"\n", + " )\n", + "\n", + " # Load calibration point information from plane i\n", + " try:\n", + " known = np.loadtxt(file_known)\n", + " detected = np.loadtxt(file_detected)\n", + " except BaseException:\n", + " raise IOError(\n", + " \"reading {} or {} failed\".format(\n", + " file_known, file_detected\n", + " )\n", + " )\n", + "\n", + " if np.any(detected == -999):\n", + " raise ValueError(\n", + " (\n", + " \"Using undetected points in {} will cause \"\n", + " + \"silliness. Quitting.\"\n", + " ).format(file_detected)\n", + " )\n", + "\n", + " num_known = len(known)\n", + " num_detect = len(detected)\n", + "\n", + " if num_known != num_detect:\n", + " raise ValueError(\n", + " f\"Number of detected points {num_known} does not match\"\n", + " \" number of known points {num_detect} for \\\n", + " {file_known}, {file_detected}\")\n", + "\n", + " if len(all_known) > 0:\n", + " detected[:, 0] = (\n", + " all_detected[-1][-1, 0]\n", + " + 1\n", + " + np.arange(len(detected))\n", + " )\n", + "\n", + " # Append to list of total known and detected points\n", + " all_known.append(known)\n", + " all_detected.append(detected)\n", + "\n", + " # Make into the format needed for full_calibration.\n", + " all_known = np.vstack(all_known)[:, 1:]\n", + " all_detected = np.vstack(all_detected)\n", + "\n", + " # this is the main difference in the multiplane mode\n", + " # that we fill the targs and cal_points by the\n", + " # combined information\n", + "\n", + " targs = TargetArray(len(all_detected))\n", + " for tix in range(len(all_detected)):\n", + " targ = targs[tix]\n", + " det = all_detected[tix]\n", + "\n", + " targ.set_pnr(tix)\n", + " targ.set_pos(det[1:])\n", + "\n", + " self.cal_points = np.empty((all_known.shape[0],)).astype(\n", + " dtype=[(\"id\", \"i4\"), (\"pos\", \"3f8\")]\n", + " )\n", + " self.cal_points[\"pos\"] = all_known\n", + " else:\n", + " targs = self.sorted_targs[i_cam]\n", + "\n", + "\n", + " residuals, targ_ix, err_est = full_calibration(\n", + " self.cals[i_cam],\n", + " self.cal_points[\"pos\"],\n", + " targs,\n", + " self.cpar,\n", + " flags,\n", + " )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pyptv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pyptv/parameters.py b/pyptv/parameters.py index b8ca3bb..590e62b 100644 --- a/pyptv/parameters.py +++ b/pyptv/parameters.py @@ -23,10 +23,13 @@ def g(f): class Parameters(HasTraits): # default path of the directory of the param files - default_path = Path("parameters") + default_path = Path(par_dir_prefix) def __init__(self, path: Path=default_path): HasTraits.__init__(self) + if isinstance(path, str): + path = Path(path) + self.path = path.resolve() self.exp_path = self.path.parent diff --git a/pyptv/ptv.py b/pyptv/ptv.py index bf29525..649d3d0 100644 --- a/pyptv/ptv.py +++ b/pyptv/ptv.py @@ -3,6 +3,7 @@ from optv.calibration import Calibration from optv.correspondences import correspondences, MatchedCoords from optv.image_processing import preprocess_image +from optv.imgcoord import image_coordinates from optv.orientation import ( point_positions, external_calibration, @@ -14,11 +15,14 @@ TrackingParams, SequenceParams, TargetParams, + MultimediaParams, ) from optv.segmentation import target_recognition from optv.tracking_framebuf import CORRES_NONE, read_targets, TargetArray from optv.tracker import Tracker, default_naming from optv.epipolar import epipolar_curve +from optv.transforms import convert_arr_metric_to_pixel + from skimage.io import imread from pyptv import parameters as par @@ -539,4 +543,4 @@ def py_multiplanecalibration(exp): # Save the results exp._write_ori(i_cam, addpar_flag=True) # addpar_flag to save addpar file - print("End multiplane") + print("End multiplane") \ No newline at end of file diff --git a/pyptv/pyptv_gui.py b/pyptv/pyptv_gui.py index 8d08ef4..c2c6a9d 100644 --- a/pyptv/pyptv_gui.py +++ b/pyptv/pyptv_gui.py @@ -396,7 +396,9 @@ def copy_set_params(self, editor, object): paramset = object print(f" Copying set of parameters \n") print(f"paramset is {paramset.name}") - print(f"paramset id is {int(paramset.name.split('Run')[-1])}") + if 'Run' in paramset.name: + print(f"paramset id is {int(paramset.name.split('Run')[-1])}") + # print(f"paramset id is {int(paramset.name.split('Run')[-1])}") # print(f"experiment is {experiment}\n") i = 1