From bbac103d1b8cc21373a4563e324bbc1f55459d09 Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Wed, 9 Aug 2023 07:54:07 +0500 Subject: [PATCH 1/6] Add upscaling during alignment --- src/vstarstack/library/fine_shift/fine_shift.py | 5 +++-- src/vstarstack/library/fine_shift/image_wave.h | 3 ++- .../library/fine_shift/image_wave_image.c | 8 ++++++-- .../library/fine_shift/image_wave_module.c | 12 ++++++++---- src/vstarstack/tool/fine_shift/align_apply.py | 13 ++++++++++--- src/vstarstack/tool/fine_shift/config.py | 1 + src/vstarstack/tool/fine_shift/fine_shift.py | 2 +- tests/test_fine_shift.py | 4 ++-- 8 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/vstarstack/library/fine_shift/fine_shift.py b/src/vstarstack/library/fine_shift/fine_shift.py index b076719d..ca713f58 100644 --- a/src/vstarstack/library/fine_shift/fine_shift.py +++ b/src/vstarstack/library/fine_shift/fine_shift.py @@ -108,7 +108,8 @@ def process_alignment_by_correlation(self, def apply_alignment(self, dataframe : vstarstack.library.data.DataFrame, - align : dict): + align : dict, + subpixels : int): """Apply alignment descriptor to file""" wave = ImageWave.from_data(align) for channel in dataframe.get_channels(): @@ -116,7 +117,7 @@ def apply_alignment(self, if opts["encoded"]: continue image = image.astype('double') - fixed = wave.apply_shift(image) + fixed = wave.apply_shift(image, subpixels) fixed[np.where(np.isnan(fixed))] = 0 dataframe.replace_channel(fixed, channel) return dataframe diff --git a/src/vstarstack/library/fine_shift/image_wave.h b/src/vstarstack/library/fine_shift/image_wave.h index e01e5bc3..fe166fc7 100644 --- a/src/vstarstack/library/fine_shift/image_wave.h +++ b/src/vstarstack/library/fine_shift/image_wave.h @@ -115,7 +115,8 @@ double image_wave_interpolation(const struct ImageWaveGrid *array, void image_wave_shift_image(struct ImageWave *self, const struct ImageWaveGrid *array, const struct ImageWaveGrid *input_image, - struct ImageWaveGrid *output_image); + struct ImageWaveGrid *output_image, + int subpixels); /* Approximation by targets methods */ diff --git a/src/vstarstack/library/fine_shift/image_wave_image.c b/src/vstarstack/library/fine_shift/image_wave_image.c index edbfd9cf..81e135d7 100644 --- a/src/vstarstack/library/fine_shift/image_wave_image.c +++ b/src/vstarstack/library/fine_shift/image_wave_image.c @@ -44,14 +44,18 @@ static double image_wave_get_pixel(const struct ImageWaveGrid *image, double x, void image_wave_shift_image(struct ImageWave *self, const struct ImageWaveGrid *array, const struct ImageWaveGrid *input_image, - struct ImageWaveGrid *output_image) + struct ImageWaveGrid *output_image, + int subpixels) { int y, x; for (y = 0; y < output_image->h; y++) for (x = 0; x < output_image->w; x++) { double orig_y, orig_x; - image_wave_shift_interpolate(self, array, x, y, &orig_x, &orig_y); + image_wave_shift_interpolate(self, array, + (double)x/subpixels, (double)y/subpixels, + &orig_x, &orig_y); + double val = image_wave_get_pixel(input_image, orig_x, orig_y); image_wave_set_pixel(output_image, x, y, val); } diff --git a/src/vstarstack/library/fine_shift/image_wave_module.c b/src/vstarstack/library/fine_shift/image_wave_module.c index 51ad03de..e375435a 100644 --- a/src/vstarstack/library/fine_shift/image_wave_module.c +++ b/src/vstarstack/library/fine_shift/image_wave_module.c @@ -227,11 +227,12 @@ static PyObject *ImageWave_apply_shift(PyObject *_self, PyObject *args, PyObject *kwds) { + int subpixels; PyArrayObject *image; struct ImageWaveObject *self = (struct ImageWaveObject *)_self; - static char *kwlist[] = {"image", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, - &image)) + static char *kwlist[] = {"image", "subpixels", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, + &image, &subpixels)) { PyErr_SetString(PyExc_ValueError, "invalid function arguments"); Py_INCREF(Py_None); @@ -260,6 +261,9 @@ static PyObject *ImageWave_apply_shift(PyObject *_self, .h = dims[0], }; + dims[1] *= subpixels; + dims[0] *= subpixels; + PyArrayObject *output_image = (PyArrayObject *)PyArray_ZEROS(2, dims, NPY_DOUBLE, 0); struct ImageWaveGrid out = { .array = PyArray_DATA(output_image), @@ -268,7 +272,7 @@ static PyObject *ImageWave_apply_shift(PyObject *_self, .h = dims[0], }; - image_wave_shift_image(&self->wave, &self->wave.array, &img, &out); + image_wave_shift_image(&self->wave, &self->wave.array, &img, &out, subpixels); return (PyObject *)output_image; } diff --git a/src/vstarstack/tool/fine_shift/align_apply.py b/src/vstarstack/tool/fine_shift/align_apply.py index 498156a8..8c7b6aeb 100644 --- a/src/vstarstack/tool/fine_shift/align_apply.py +++ b/src/vstarstack/tool/fine_shift/align_apply.py @@ -44,7 +44,8 @@ def align_file(project : vstarstack.tool.cfg.Project, name : str, input_image_f : str, desc_f : str, - output_image_f : str): + output_image_f : str, + subpixels : int): """Apply alignment to each file""" print(name) if not os.path.exists(input_image_f): @@ -58,7 +59,7 @@ def align_file(project : vstarstack.tool.cfg.Project, aligner = create_aligner(project, w, h) # apply alignment to file - df = aligner.apply_alignment(df, descriptor) + df = aligner.apply_alignment(df, descriptor, subpixels) print(f"{name} - aligned") vstarstack.tool.common.check_dir_exists(output_image_f) @@ -72,9 +73,14 @@ def apply(project: vstarstack.tool.cfg.Project, argv: list): npys = argv[0] aligns = argv[1] outputs = argv[2] + if len(argv) >= 4: + subpixels = int(argv[3]) + else: + subpixels = 1 else: npys = project.config.paths.npy_fixed aligns = project.config.fine_shift.aligns + subpixels = project.config.fine_shift.subpixels outputs = project.config.paths.aligned files = vstarstack.tool.common.listfiles(npys, ".zip") @@ -83,7 +89,8 @@ def apply(project: vstarstack.tool.cfg.Project, argv: list): name, input_image_f, os.path.join(aligns, name + ".json"), - os.path.join(outputs, name + ".zip")) + os.path.join(outputs, name + ".zip"), + subpixels) for name, input_image_f in files] for _ in pool.imap_unordered(_align_file_wrapper, args): pass diff --git a/src/vstarstack/tool/fine_shift/config.py b/src/vstarstack/tool/fine_shift/config.py index e0d7dc6c..e8bc12f3 100644 --- a/src/vstarstack/tool/fine_shift/config.py +++ b/src/vstarstack/tool/fine_shift/config.py @@ -22,6 +22,7 @@ "stretchPenaltyCoefficient" : (float, 0.01), "points_min_len" : (int, 0), "aligns" : (str, "aligns/"), + "subpixels" : (str, 1), } configuration = vstarstack.tool.configuration.Configuration(_module_configuration) diff --git a/src/vstarstack/tool/fine_shift/fine_shift.py b/src/vstarstack/tool/fine_shift/fine_shift.py index fb770e19..de87919b 100644 --- a/src/vstarstack/tool/fine_shift/fine_shift.py +++ b/src/vstarstack/tool/fine_shift/fine_shift.py @@ -32,5 +32,5 @@ def _enable_fine_shift(project : vstarstack.tool.cfg.Project, _argv: list[str]): "npy/ aligns/ [pre_aligns/]"), "apply-align": (vstarstack.tool.fine_shift.align_apply.apply, "apply aligns to images", - "npy/ aligns/ aligned/"), + "npy/ aligns/ aligned/ [subpixels]"), } diff --git a/tests/test_fine_shift.py b/tests/test_fine_shift.py index 6f54e5a3..404303df 100644 --- a/tests/test_fine_shift.py +++ b/tests/test_fine_shift.py @@ -154,7 +154,7 @@ def test_shift_image1(): image1 = df1.get_channel("L")[0].astype('double') wave = ImageWave(image1.shape[1], image1.shape[0], 2, 2, 0.01) - image2 = wave.apply_shift(image1) + image2 = wave.apply_shift(image1, 1) correlation = vstarstack.library.fine_shift.image_wave.image_correlation(image1, image2) assert correlation == 1 @@ -165,6 +165,6 @@ def test_approximate_by_correlation1(): image = df1.get_channel("L")[0].astype('double') image_ref = df2.get_channel("L")[0].astype('double') wave = ImageWave.find_shift_array(image, None, image_ref, None, 5, 3, 4) - image_shifted = wave.apply_shift(image) + image_shifted = wave.apply_shift(image, 1) correlation = vstarstack.library.fine_shift.image_wave.image_correlation(image_shifted, image_ref) assert correlation > 1 - 1e-4 From 3b5cd0edf48f9aaabf134ecd56bb4b51637b6fd3 Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Wed, 9 Aug 2023 13:11:27 +0500 Subject: [PATCH 2/6] Fix configs --- src/vstarstack/library/fine_shift/fine_shift.py | 2 +- src/vstarstack/tool/fine_shift/align_apply.py | 2 +- src/vstarstack/tool/fine_shift/config.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vstarstack/library/fine_shift/fine_shift.py b/src/vstarstack/library/fine_shift/fine_shift.py index ca713f58..68a43259 100644 --- a/src/vstarstack/library/fine_shift/fine_shift.py +++ b/src/vstarstack/library/fine_shift/fine_shift.py @@ -102,7 +102,7 @@ def process_alignment_by_correlation(self, pre_wave_ref = ImageWave.from_data(pre_align_ref) else: pre_wave_ref = None - wave = ImageWave.find_shift_array(image, pre_wave, image_ref, pre_wave_ref, 5, 3, 4) + wave = ImageWave.find_shift_array(image, pre_wave, image_ref, pre_wave_ref, 7, 3, 4) align = wave.data() return align diff --git a/src/vstarstack/tool/fine_shift/align_apply.py b/src/vstarstack/tool/fine_shift/align_apply.py index 8c7b6aeb..20645f35 100644 --- a/src/vstarstack/tool/fine_shift/align_apply.py +++ b/src/vstarstack/tool/fine_shift/align_apply.py @@ -47,7 +47,7 @@ def align_file(project : vstarstack.tool.cfg.Project, output_image_f : str, subpixels : int): """Apply alignment to each file""" - print(name) + print(f"{name}: {input_image_f} : {desc_f} -> {output_image_f} [{subpixels}]") if not os.path.exists(input_image_f): return with open(desc_f, encoding='utf8') as f: diff --git a/src/vstarstack/tool/fine_shift/config.py b/src/vstarstack/tool/fine_shift/config.py index e8bc12f3..6af35ab5 100644 --- a/src/vstarstack/tool/fine_shift/config.py +++ b/src/vstarstack/tool/fine_shift/config.py @@ -22,7 +22,7 @@ "stretchPenaltyCoefficient" : (float, 0.01), "points_min_len" : (int, 0), "aligns" : (str, "aligns/"), - "subpixels" : (str, 1), + "subpixels" : (int, 1), } configuration = vstarstack.tool.configuration.Configuration(_module_configuration) From 003aa147916e011f65f8d22dbb2963597b09eb72 Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Fri, 8 Sep 2023 18:11:02 +0500 Subject: [PATCH 3/6] aligner code refactoring --- .../library/fine_shift/fine_shift.py | 67 ++++++++++--------- src/vstarstack/tool/fine_shift/align_apply.py | 16 +---- .../tool/fine_shift/align_clusters.py | 12 ++-- .../tool/fine_shift/align_correlation.py | 29 +++----- 4 files changed, 52 insertions(+), 72 deletions(-) diff --git a/src/vstarstack/library/fine_shift/fine_shift.py b/src/vstarstack/library/fine_shift/fine_shift.py index 68a43259..ac78a46d 100644 --- a/src/vstarstack/library/fine_shift/fine_shift.py +++ b/src/vstarstack/library/fine_shift/fine_shift.py @@ -29,6 +29,25 @@ def _cluster_average(cluster): class Aligner: """Alignment calculator""" + + def apply_alignment(self, + dataframe : vstarstack.library.data.DataFrame, + align : dict, + subpixels : int): + """Apply alignment descriptor to file""" + wave = ImageWave.from_data(align) + for channel in dataframe.get_channels(): + image, opts = dataframe.get_channel(channel) + if opts["encoded"]: + continue + image = image.astype('double') + fixed = wave.apply_shift(image, subpixels) + fixed[np.where(np.isnan(fixed))] = 0 + dataframe.replace_channel(fixed, channel) + return dataframe + +class ClusterAlignerBuilder: + def __init__(self, W, H, gridW, gridH, spk, num_steps, min_points, dh): self.W = W self.H = H @@ -39,9 +58,7 @@ def __init__(self, W, H, gridW, gridH, spk, num_steps, min_points, dh): self.min_points = min_points self.dh = dh - def process_alignment_by_clusters(self, - name : str, - clusters : list): + def find_alignment(self, name : str, clusters : list) -> dict: """Find alignment of image `name` using clusters""" points = [] targets = [] @@ -67,8 +84,7 @@ def process_alignment_by_clusters(self, descriptor = wave.data() return descriptor - def find_all_alignments_by_clusters(self, - clusters : list): + def find_all_alignments(self, clusters : list) -> dict: """Build alignment descriptor using clusters""" names = [] for cluster in clusters: @@ -81,18 +97,21 @@ def find_all_alignments_by_clusters(self, descs[name] = desc return descs - def process_alignment_by_correlation(self, - image : np.ndarray, - mask : np.ndarray, - pre_align : dict | None, - image_ref : np.ndarray, - mask_ref : np.ndarray, - pre_align_ref : dict | None): +class CorrelationAlignedBuilder: + + def __init__(self, radius : int, maximal_shift : float, subpixels : int): + self.r = radius + self.shift = maximal_shift + self.subp = subpixels + + def find_alignment(self, + image : np.ndarray, + pre_align : dict | None, + image_ref : np.ndarray, + pre_align_ref : dict | None): """Build alignment descriptor of image using correlations""" if image.shape != image_ref.shape: return None - h = image.shape[0] - w = image.shape[1] if pre_align is not None: pre_wave = ImageWave.from_data(pre_align) else: @@ -102,22 +121,8 @@ def process_alignment_by_correlation(self, pre_wave_ref = ImageWave.from_data(pre_align_ref) else: pre_wave_ref = None - wave = ImageWave.find_shift_array(image, pre_wave, image_ref, pre_wave_ref, 7, 3, 4) + wave = ImageWave.find_shift_array(image, pre_wave, + image_ref, pre_wave_ref, + self.r, self.shift, self.subp) align = wave.data() return align - - def apply_alignment(self, - dataframe : vstarstack.library.data.DataFrame, - align : dict, - subpixels : int): - """Apply alignment descriptor to file""" - wave = ImageWave.from_data(align) - for channel in dataframe.get_channels(): - image, opts = dataframe.get_channel(channel) - if opts["encoded"]: - continue - image = image.astype('double') - fixed = wave.apply_shift(image, subpixels) - fixed[np.where(np.isnan(fixed))] = 0 - dataframe.replace_channel(fixed, channel) - return dataframe diff --git a/src/vstarstack/tool/fine_shift/align_apply.py b/src/vstarstack/tool/fine_shift/align_apply.py index 20645f35..6d1ae3c1 100644 --- a/src/vstarstack/tool/fine_shift/align_apply.py +++ b/src/vstarstack/tool/fine_shift/align_apply.py @@ -28,18 +28,6 @@ ncpu = vstarstack.tool.cfg.nthreads -def create_aligner(project: vstarstack.tool.cfg.Project, W: int, H: int): - """Create aligner for the project""" - num_steps = project.config.fine_shift.Nsteps - dh = project.config.fine_shift.dh - gridW = project.config.fine_shift.gridW - gridH = project.config.fine_shift.gridH - spk = project.config.fine_shift.stretchPenaltyCoefficient - min_points = project.config.fine_shift.points_min_len - - aligner = Aligner(W, H, gridW, gridH, spk, num_steps, min_points, dh) - return aligner - def align_file(project : vstarstack.tool.cfg.Project, name : str, input_image_f : str, @@ -54,9 +42,7 @@ def align_file(project : vstarstack.tool.cfg.Project, descriptor = json.load(f) df = vstarstack.library.data.DataFrame.load(input_image_f) - w = df.params["w"] - h = df.params["h"] - aligner = create_aligner(project, w, h) + aligner = Aligner() # apply alignment to file df = aligner.apply_alignment(df, descriptor, subpixels) diff --git a/src/vstarstack/tool/fine_shift/align_clusters.py b/src/vstarstack/tool/fine_shift/align_clusters.py index 55b1387b..9e72a953 100644 --- a/src/vstarstack/tool/fine_shift/align_clusters.py +++ b/src/vstarstack/tool/fine_shift/align_clusters.py @@ -17,7 +17,7 @@ import json import multiprocessing as mp -from vstarstack.library.fine_shift.fine_shift import Aligner +from vstarstack.library.fine_shift.fine_shift import ClusterAlignerBuilder import vstarstack.tool.usage import vstarstack.tool.cfg import vstarstack.tool.configuration @@ -37,8 +37,8 @@ def create_aligner(project: vstarstack.tool.cfg.Project, W: int, H: int): spk = project.config.fine_shift.stretchPenaltyCoefficient min_points = project.config.fine_shift.points_min_len - aligner = Aligner(W, H, gridW, gridH, spk, num_steps, min_points, dh) - return aligner + aligner_factory = ClusterAlignerBuilder(W, H, gridW, gridH, spk, num_steps, min_points, dh) + return aligner_factory def align_file(project : vstarstack.tool.cfg.Project, name : str, @@ -55,14 +55,14 @@ def align_file(project : vstarstack.tool.cfg.Project, df = vstarstack.library.data.DataFrame.load(input_image_f) w = df.params["w"] h = df.params["h"] - aligner = create_aligner(project, w, h) + aligner_factory = create_aligner(project, w, h) # find alignment - desc = aligner.process_alignment_by_clusters(name, clusters) + alignment = aligner_factory.find_alignment(name, clusters) print(f"{name} - align found") vstarstack.tool.common.check_dir_exists(desc_f) with open(desc_f, "w", encoding='utf8') as f: - json.dump(desc, f, ensure_ascii=False, indent=2) + json.dump(alignment, f, ensure_ascii=False, indent=2) def _align_file_wrapper(arg): align_file(*arg) diff --git a/src/vstarstack/tool/fine_shift/align_correlation.py b/src/vstarstack/tool/fine_shift/align_correlation.py index 8af32a2e..a46cb35f 100644 --- a/src/vstarstack/tool/fine_shift/align_correlation.py +++ b/src/vstarstack/tool/fine_shift/align_correlation.py @@ -17,7 +17,7 @@ import json import multiprocessing as mp -from vstarstack.library.fine_shift.fine_shift import Aligner +from vstarstack.library.fine_shift.fine_shift import CorrelationAlignedBuilder import vstarstack.tool.usage import vstarstack.tool.cfg import vstarstack.tool.configuration @@ -30,15 +30,8 @@ def create_aligner(project: vstarstack.tool.cfg.Project, W: int, H: int): """Create aligner for the project""" - num_steps = project.config.fine_shift.Nsteps - dh = project.config.fine_shift.dh - gridW = project.config.fine_shift.gridW - gridH = project.config.fine_shift.gridH - spk = project.config.fine_shift.stretchPenaltyCoefficient - min_points = project.config.fine_shift.points_min_len - - aligner = Aligner(W, H, gridW, gridH, spk, num_steps, min_points, dh) - return aligner + aligner_factory = CorrelationAlignedBuilder(7, 3, 2) + return aligner_factory def align_file(project : vstarstack.tool.cfg.Project, name : str, @@ -59,10 +52,10 @@ def align_file(project : vstarstack.tool.cfg.Project, df_ref = vstarstack.library.data.DataFrame.load(input_image_ref_f) w = df.params["w"] h = df.params["h"] - aligner = create_aligner(project, w, h) + aligner_factory = create_aligner(project, w, h) - light, mask = vstarstack.library.common.df_to_light(df) - light_ref, mask_ref = vstarstack.library.common.df_to_light(df_ref) + light, _ = vstarstack.library.common.df_to_light(df) + light_ref, _ = vstarstack.library.common.df_to_light(df_ref) if pre_align_f is None or not os.path.isfile(pre_align_f): pre_align = None @@ -77,16 +70,12 @@ def align_file(project : vstarstack.tool.cfg.Project, pre_align_ref = json.load(f) # find alignment - align = aligner.process_alignment_by_correlation(light, - mask, - pre_align, - light_ref, - mask_ref, - pre_align_ref) + alignment = aligner_factory.find_alignment(light, pre_align, + light_ref, pre_align_ref) print(f"{name} - align to {name_ref} found") vstarstack.tool.common.check_dir_exists(align_f) with open(align_f, "w", encoding='utf8') as f: - json.dump(align, f, ensure_ascii=False, indent=2) + json.dump(alignment, f, ensure_ascii=False, indent=2) def _align_file_wrapper(arg): align_file(*arg) From de324ee2e7430d352019e220a2c71c8f8926e46c Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Sat, 9 Sep 2023 02:15:13 +0500 Subject: [PATCH 4/6] Smooth correlation shift array --- setup.py | 2 +- src/vstarstack/library/fine_shift/fine_shift.py | 14 +++++++++++++- src/vstarstack/tool/fine_shift/align_apply.py | 4 ++++ .../tool/fine_shift/align_correlation.py | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 9eb17bdf..149a0dc2 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ 'exifread', 'opencv-python', 'scikit-image', - 'scipy', + 'scipy >= 1.11.0', 'imutils', 'matplotlib', ] diff --git a/src/vstarstack/library/fine_shift/fine_shift.py b/src/vstarstack/library/fine_shift/fine_shift.py index ac78a46d..ef9407b3 100644 --- a/src/vstarstack/library/fine_shift/fine_shift.py +++ b/src/vstarstack/library/fine_shift/fine_shift.py @@ -13,6 +13,7 @@ # import numpy as np +import scipy from vstarstack.library.fine_shift.image_wave import ImageWave import vstarstack.library.data @@ -108,7 +109,8 @@ def find_alignment(self, image : np.ndarray, pre_align : dict | None, image_ref : np.ndarray, - pre_align_ref : dict | None): + pre_align_ref : dict | None, + smooth : int | None): """Build alignment descriptor of image using correlations""" if image.shape != image_ref.shape: return None @@ -125,4 +127,14 @@ def find_alignment(self, image_ref, pre_wave_ref, self.r, self.shift, self.subp) align = wave.data() + print(f"smooth = {smooth}") + if smooth is not None: + data = align["data"] + Nw = align["Nw"] + Nh = align["Nh"] + data = np.array(data, dtype='double') + data = data.reshape((Nh, Nw, 2)) + data = scipy.ndimage.gaussian_filter(data, sigma=smooth, axes=(0,1)) + data = list(data.reshape((Nh*Nw*2,))) + align["data"] = data return align diff --git a/src/vstarstack/tool/fine_shift/align_apply.py b/src/vstarstack/tool/fine_shift/align_apply.py index 6d1ae3c1..48aff44c 100644 --- a/src/vstarstack/tool/fine_shift/align_apply.py +++ b/src/vstarstack/tool/fine_shift/align_apply.py @@ -36,8 +36,12 @@ def align_file(project : vstarstack.tool.cfg.Project, subpixels : int): """Apply alignment to each file""" print(f"{name}: {input_image_f} : {desc_f} -> {output_image_f} [{subpixels}]") + if not os.path.exists(input_image_f): return + if not os.path.exists(desc_f): + return + with open(desc_f, encoding='utf8') as f: descriptor = json.load(f) diff --git a/src/vstarstack/tool/fine_shift/align_correlation.py b/src/vstarstack/tool/fine_shift/align_correlation.py index a46cb35f..f8692e74 100644 --- a/src/vstarstack/tool/fine_shift/align_correlation.py +++ b/src/vstarstack/tool/fine_shift/align_correlation.py @@ -71,7 +71,7 @@ def align_file(project : vstarstack.tool.cfg.Project, # find alignment alignment = aligner_factory.find_alignment(light, pre_align, - light_ref, pre_align_ref) + light_ref, pre_align_ref, 3) print(f"{name} - align to {name_ref} found") vstarstack.tool.common.check_dir_exists(align_f) with open(align_f, "w", encoding='utf8') as f: From 7b0f424ddc355cdf10c4b8edc6937ae7318ddfed Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Sat, 9 Sep 2023 04:55:10 +0500 Subject: [PATCH 5/6] Fix memory leaks --- .../library/fine_shift/image_wave_module.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/vstarstack/library/fine_shift/image_wave_module.c b/src/vstarstack/library/fine_shift/image_wave_module.c index e375435a..efba23f0 100644 --- a/src/vstarstack/library/fine_shift/image_wave_module.c +++ b/src/vstarstack/library/fine_shift/image_wave_module.c @@ -299,6 +299,7 @@ static PyObject *ImageWave_data(PyObject *_self, PyObject *args, PyObject *kwds) "h", self->wave.h, "spk", self->wave.stretch_penalty_k, "data", data); + Py_DECREF(data); return result; } @@ -430,6 +431,10 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (PyArray_TYPE(image) != NPY_DOUBLE) { + Py_DECREF(image); + Py_DECREF(ref_image); + Py_DECREF(pre_shift); + Py_DECREF(ref_pre_shift); PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be dtype == double"); Py_INCREF(Py_None); return Py_None; @@ -437,6 +442,10 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (PyArray_TYPE(ref_image) != NPY_DOUBLE) { + Py_DECREF(image); + Py_DECREF(ref_image); + Py_DECREF(pre_shift); + Py_DECREF(ref_pre_shift); PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be dtype == double"); Py_INCREF(Py_None); return Py_None; @@ -460,6 +469,10 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (ref_img.w != img.w || ref_img.h != img.h) { + Py_DECREF(image); + Py_DECREF(ref_image); + Py_DECREF(pre_shift); + Py_DECREF(ref_pre_shift); Py_INCREF(Py_None); return Py_None; } @@ -470,6 +483,10 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (obj == NULL) { + Py_DECREF(image); + Py_DECREF(ref_image); + Py_DECREF(pre_shift); + Py_DECREF(ref_pre_shift); Py_INCREF(Py_None); return Py_None; } @@ -489,6 +506,10 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, &ref_img, ref_pre_align, radius, maximal_shift, subpixels); + Py_DECREF(image); + Py_DECREF(ref_image); + Py_DECREF(pre_shift); + Py_DECREF(ref_pre_shift); return obj; } From 658710dfb233b512e5427e5268a2c7720cb7ad16 Mon Sep 17 00:00:00 2001 From: Vladislav Tsendrovskii Date: Sat, 9 Sep 2023 17:28:31 +0500 Subject: [PATCH 6/6] remove leaks --- requirements.txt | 1 + .../library/fine_shift/image_wave_module.c | 38 +++++-------------- tests/test_fine_shift.py | 4 +- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/requirements.txt b/requirements.txt index fa530ff5..0ecac549 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ scikit-image scipy imutils matplotlib +pytest diff --git a/src/vstarstack/library/fine_shift/image_wave_module.c b/src/vstarstack/library/fine_shift/image_wave_module.c index efba23f0..035be9b9 100644 --- a/src/vstarstack/library/fine_shift/image_wave_module.c +++ b/src/vstarstack/library/fine_shift/image_wave_module.c @@ -280,17 +280,19 @@ static PyObject *ImageWave_data(PyObject *_self, PyObject *args, PyObject *kwds) { struct ImageWaveObject *self = (struct ImageWaveObject *)_self; int xi, yi; - PyObject *data = PyList_New(self->wave.array.w * self->wave.array.h * 2); + PyObject *data = PyList_New(0); for (yi = 0; yi < self->wave.array.h; yi++) for (xi = 0; xi < self->wave.array.w; xi++) { - double vx = image_wave_get_array(&self->wave.array, - xi, yi, 0); - double vy = image_wave_get_array(&self->wave.array, - xi, yi, 1); - - PyList_SetItem(data, yi*self->wave.array.w*2 + xi*2, PyFloat_FromDouble(vx)); - PyList_SetItem(data, yi*self->wave.array.w*2 + xi*2 + 1, PyFloat_FromDouble(vy)); + double vx = image_wave_get_array(&self->wave.array, xi, yi, 0); + double vy = image_wave_get_array(&self->wave.array, xi, yi, 1); + + PyObject *vxv = PyFloat_FromDouble(vx); + PyObject *vyv = PyFloat_FromDouble(vy); + PyList_Append(data, vxv); + PyList_Append(data, vyv); + Py_DECREF(vxv); + Py_DECREF(vyv); } PyObject *result = Py_BuildValue("{s:i,s:i,s:i,s:i,s:d,s:O}", "Nw", self->wave.array.w, @@ -431,10 +433,6 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (PyArray_TYPE(image) != NPY_DOUBLE) { - Py_DECREF(image); - Py_DECREF(ref_image); - Py_DECREF(pre_shift); - Py_DECREF(ref_pre_shift); PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be dtype == double"); Py_INCREF(Py_None); return Py_None; @@ -442,10 +440,6 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (PyArray_TYPE(ref_image) != NPY_DOUBLE) { - Py_DECREF(image); - Py_DECREF(ref_image); - Py_DECREF(pre_shift); - Py_DECREF(ref_pre_shift); PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be dtype == double"); Py_INCREF(Py_None); return Py_None; @@ -469,10 +463,6 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (ref_img.w != img.w || ref_img.h != img.h) { - Py_DECREF(image); - Py_DECREF(ref_image); - Py_DECREF(pre_shift); - Py_DECREF(ref_pre_shift); Py_INCREF(Py_None); return Py_None; } @@ -483,10 +473,6 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, if (obj == NULL) { - Py_DECREF(image); - Py_DECREF(ref_image); - Py_DECREF(pre_shift); - Py_DECREF(ref_pre_shift); Py_INCREF(Py_None); return Py_None; } @@ -506,10 +492,6 @@ static PyObject *ImageWave_find_correlation_array(PyObject *_self, &ref_img, ref_pre_align, radius, maximal_shift, subpixels); - Py_DECREF(image); - Py_DECREF(ref_image); - Py_DECREF(pre_shift); - Py_DECREF(ref_pre_shift); return obj; } diff --git a/tests/test_fine_shift.py b/tests/test_fine_shift.py index 404303df..02033ee5 100644 --- a/tests/test_fine_shift.py +++ b/tests/test_fine_shift.py @@ -12,6 +12,7 @@ # along with this program. If not, see . # +import sys import os import numpy as np @@ -99,7 +100,6 @@ def test_serialize(): assert data["Nh"] == 3 assert len(data["data"]) == 3*3*2 - def test_deserialize(): wave = ImageWave(10, 10, 2, 2, 0.01) targets = [(5.0, 5.0)] @@ -164,7 +164,7 @@ def test_approximate_by_correlation1(): image = df1.get_channel("L")[0].astype('double') image_ref = df2.get_channel("L")[0].astype('double') - wave = ImageWave.find_shift_array(image, None, image_ref, None, 5, 3, 4) + wave = ImageWave.find_shift_array(image, None, image_ref, None, 5, 3, 2) image_shifted = wave.apply_shift(image, 1) correlation = vstarstack.library.fine_shift.image_wave.image_correlation(image_shifted, image_ref) assert correlation > 1 - 1e-4