From fa9e04091d2b663bb0ba5d9879d0157c5c30339c Mon Sep 17 00:00:00 2001 From: nghia-vo Date: Fri, 13 Dec 2024 15:35:38 -0500 Subject: [PATCH] Add methods for selecting good peaks & chessboard edge detection --- discorpy/losa/loadersaver.py | 4 - discorpy/prep/linepattern.py | 316 ++++++++++++++---- discorpy/prep/preprocessing.py | 29 +- discorpy/proc/processing.py | 62 ++-- docs/source/usage/codes/demo_01.py | 28 +- docs/source/usage/codes/demo_02.py | 30 +- docs/source/usage/codes/demo_03.py | 32 +- docs/source/usage/codes/demo_04.py | 26 +- docs/source/usage/codes/demo_05.py | 32 +- docs/source/usage/codes/demo_06.py | 42 +-- docs/source/usage/codes/demo_07.py | 8 +- docs/source/usage/codes/demo_08.py | 28 +- docs/source/usage/demo_01.rst | 30 +- docs/source/usage/demo_02.rst | 30 +- docs/source/usage/demo_03.rst | 32 +- docs/source/usage/demo_04.rst | 26 +- docs/source/usage/demo_05.rst | 28 +- docs/source/usage/demo_06.rst | 34 +- docs/source/usage/demo_07.rst | 8 +- docs/source/usage/demo_08.rst | 28 +- docs/source/usage/tips.rst | 14 +- ...tion_correction_for_Perseverance_camera.md | 22 +- .../apply_correction_to_images.py | 6 +- .../backward_mapping.py | 10 +- .../forward_model_estimation.py | 6 +- examples/example_01.py | 62 ++-- examples/example_02.py | 10 +- examples/example_03.py | 32 +- examples/example_04.py | 10 +- examples/example_05.py | 8 +- examples/line_pattern/example_01.py | 26 +- examples/readthedocs_demo/demo_01.py | 28 +- examples/readthedocs_demo/demo_02.py | 30 +- examples/readthedocs_demo/demo_03.py | 32 +- examples/readthedocs_demo/demo_04.py | 26 +- examples/readthedocs_demo/demo_05.py | 32 +- examples/readthedocs_demo/demo_06.py | 42 +-- examples/readthedocs_demo/demo_07.py | 8 +- examples/readthedocs_demo/demo_08.py | 28 +- examples/unwarp.py | 36 +- tests/test_linepattern.py | 25 ++ 41 files changed, 779 insertions(+), 567 deletions(-) diff --git a/discorpy/losa/loadersaver.py b/discorpy/losa/loadersaver.py index 966d057..7b09fbe 100644 --- a/discorpy/losa/loadersaver.py +++ b/discorpy/losa/loadersaver.py @@ -809,16 +809,12 @@ def save_metadata_json(file_path, xcenter, ycenter, list_fact, overwrite=True): str Updated file path. """ - # Get resolved file path and set to JSON suffix file_path = __get_path(file_path, check_exist=False).resolve() if file_path.suffix.lower() != '.json': file_path = file_path.with_suffix('.json') _create_folder(str(file_path)) - if not overwrite: file_path = _create_file_name(str(file_path)) - - # Create metadata dictionary metadata = { 'xcenter': float(xcenter), 'ycenter': float(ycenter), diff --git a/discorpy/prep/linepattern.py b/discorpy/prep/linepattern.py index 7fb6006..13b90f3 100644 --- a/discorpy/prep/linepattern.py +++ b/discorpy/prep/linepattern.py @@ -21,17 +21,24 @@ # ============================================================================ """ -Module of pre-processing methods for handling a line-pattern image: - -- Determine the slopes and distances between lines. -- Extract points belong to a line. -- Convert a chessboard image to a line-pattern image. - +Module of pre-processing methods for handling line-pattern images and +chessboard images: + +- Determine the slopes and distances between lines in horizontal and + vertical directions. +- Convert a chessboard image to a line-pattern image. +- Extract line profiles across an image. +- Get points belonging to a line by locating local extrema. +- Get points belonging to the edges of a chessboard image by converting + a line profile into a list of slopes, calculated using a linear fit of + neighboring points. +- Select good points using Gaussian peak fitting. """ import numpy as np import scipy.ndimage as ndi from skimage.transform import radon +from scipy.optimize import curve_fit import discorpy.prep.preprocessing as prep @@ -64,8 +71,119 @@ def locate_subpixel_point(list_point, option="min"): return pos +def __gauss_function(x, a, b, c, d): + y = a * np.exp(-np.power((x - c) / (2 * b ** 2), 2)) + d + return y + + +def _get_gauss_peak_fit(list_data): + """ + Fit a Gaussian to 1d-array and return fitted result, peak position, and a + successful flag. + """ + npoint = len(list_data) + list_x = np.arange(npoint) - npoint // 2 + check = False + try: + init_guess = [1.0, 1.0, 0.0, 0.0] + parameters = curve_fit(__gauss_function, list_x, list_data, + p0=init_guess)[0] + a = parameters[0] + b, c = parameters[1], parameters[2] + d = parameters[3] + fit_data = __gauss_function(list_x, a, b, c, d) + check = True + except (RuntimeError, ValueError): + fit_data = list_data + c = list_x[0] + return fit_data, c, check + + +def select_good_peaks(list_data, peaks, tol=0.1, radius=11, sigma=0): + """ + Select good peaks from the input data based on Gaussian fitting and + tolerance criteria. + + Parameters + ---------- + list_data : array_like + 1d-array. + peaks : list of int + Indices of candidate peaks in the data. + tol : float, optional + Tolerance for peak fitting accuracy. + radius : int, optional + Radius around each peak to consider for fitting. + sigma : float, optional + Standard deviation for Gaussian smoothing. + + Returns + ------- + list of int + Indices of the selected good peaks. + """ + if sigma > 0: + list_data = ndi.gaussian_filter1d(list_data, sigma) + good_peaks = [] + npoint = len(list_data) + for p in peaks: + start = max(0, p - radius) + stop = min(npoint, p + radius + 1) + if (stop - start) > 3: + list_sub = list_data[start:stop] + nmax = np.max(list_sub) + if nmax != 0.0: + list_norm = list_sub / nmax + fit_data, delta_x, check = _get_gauss_peak_fit(list_norm) + num = np.max(np.abs(fit_data - list_norm)) + if check and abs(delta_x) < radius and num < tol: + good_peaks.append(p) + return np.asarray(good_peaks) + + +def sliding_window_slope(list_data, size=3, norm=True): + """ + Compute the absolute slopes of a linear fit within a sliding window + across the input data, normalized by the mean slope if norm is True. + + Parameters + ---------- + list_data : array-like + 1d-array. + size : int, optional + Size of the sliding window for the linear fit. + norm : bool, optional + Normalize the result by the mean slope if True. + + Returns + ------- + array_like + Normalized absolute slopes for each data point. + """ + npoint = len(list_data) + if npoint < 3: + raise ValueError("Data size must be larger than 2") + size = int(np.clip(size, 3, npoint)) + if size % 2 == 0: + size += 1 + radius = size // 2 + padded_data = np.pad(list_data, (radius, radius), 'edge') + x_list = np.arange(size) + slopes = np.zeros_like(list_data) + for i in range(len(list_data)): + local_data = padded_data[i:i + size] + slopes[i] = np.polyfit(x_list, local_data, 1)[0] + slopes = np.abs(slopes) + if norm is True: + nmean = np.mean(slopes) + if nmean != 0.0: + slopes = slopes / nmean + return slopes + + def get_local_extrema_points(list_data, option="min", radius=7, sensitive=0.1, - denoise=True, norm=True, subpixel=True): + denoise=True, norm=True, subpixel=True, + select_peaks=False, **kwargs): """ Get a list of local extremum points from a 1D array. @@ -86,6 +204,10 @@ def get_local_extrema_points(list_data, option="min", radius=7, sensitive=0.1, Apply background normalization to the array. subpixel : bool, optional Locate points with subpixel accuracy. + select_peaks : bool, optional + To select good points based on Gaussian fitting. + **kwargs : optional + Additional parameters for the method 'select_good_peaks' Returns ------- @@ -99,7 +221,7 @@ def get_local_extrema_points(list_data, option="min", radius=7, sensitive=0.1, if option == "max": list_data = np.max(list_data) - list_data num_point = len(list_data) - radius = np.clip(radius, 1, num_point // 4) + radius = int(np.clip(radius, 1, num_point // 4)) if norm is True: xlist = np.arange(num_point) mat_comb = np.asarray(np.vstack((xlist, list_data))) @@ -126,10 +248,18 @@ def get_local_extrema_points(list_data, option="min", radius=7, sensitive=0.1, nmean = np.mean(list_sort[-radius:]) num2 = np.abs((val - nmean) / nmean) if nmean != 0 else 0.0 if num1 == 0.0 and num2 > sensitive: - if subpixel is True: - pos = i - 1 + locate_subpixel_point(list_data[i - 1:i + 2], - option="min") points.append(pos) + if select_peaks is True: + points = select_good_peaks(np.max(list_data) - list_data, points, + radius=radius, **kwargs) + if subpixel is True: + points_sub = [] + if len(points) > 0: + for i in points: + pos_sub = i - 1 + locate_subpixel_point(list_data[i - 1:i + 2], + option="min") + points_sub.append(pos_sub) + return np.asarray(points_sub) return np.asarray(points) @@ -160,11 +290,12 @@ def _make_circle_mask(width, ratio): def calc_slope_distance_hor_lines(mat, ratio=0.3, search_range=30.0, radius=9, sensitive=0.1, bgr="bright", denoise=True, - norm=True, subpixel=True): + norm=True, subpixel=True, chessboard=False, + select_peaks=False, **kwargs): """ Calculate the representative distance between horizontal lines and the representative slope of these lines using the ROI around the middle of a - line-pattern image. + line-pattern image or a chessboard image. Parameters ---------- @@ -181,11 +312,17 @@ def calc_slope_distance_hor_lines(mat, ratio=0.3, search_range=30.0, radius=9, bgr : {"bright", "dark"} Specify the brightness of the background against the lines. denoise : bool, optional - Applying a smoothing filter if True. + Apply a smoothing filter if True. norm : bool, optional Apply background normalization to the array. subpixel : bool, optional Locate points with subpixel accuracy. + chessboard : bool, optional + If True, converts the input chessboard image to a line-pattern image. + select_peaks : bool, optional + To select good points based on Gaussian fitting. + **kwargs : optional + Additional parameters for the method 'select_good_peaks' Returns ------- @@ -194,6 +331,8 @@ def calc_slope_distance_hor_lines(mat, ratio=0.3, search_range=30.0, radius=9, distance : float Distance between horizontal lines. """ + if chessboard is True: + mat = convert_chessboard_to_linepattern(mat) if denoise is True: mat = ndi.gaussian_filter(mat, 3) mat_roi = prep._select_roi(mat, ratio, square=True) @@ -215,7 +354,9 @@ def calc_slope_distance_hor_lines(mat, ratio=0.3, search_range=30.0, radius=9, option="max", radius=radius, denoise=denoise, norm=norm, subpixel=subpixel, - sensitive=sensitive) + sensitive=sensitive, + select_peaks=select_peaks, + **kwargs) if len(list_ext_point) > 3: distance = np.median(np.abs(np.diff(list_ext_point))) else: @@ -225,11 +366,12 @@ def calc_slope_distance_hor_lines(mat, ratio=0.3, search_range=30.0, radius=9, def calc_slope_distance_ver_lines(mat, ratio=0.3, search_range=30.0, radius=9, sensitive=0.1, bgr="bright", denoise=True, - norm=True, subpixel=True): + norm=True, subpixel=True, chessboard=False, + select_peaks=False, **kwargs): """ Calculate the representative distance between vertical lines and the representative slope of these lines using the ROI around the middle of a - line-pattern image. + line-pattern image or a chessboard image. Parameters ---------- @@ -249,6 +391,12 @@ def calc_slope_distance_ver_lines(mat, ratio=0.3, search_range=30.0, radius=9, Applying a smoothing filter if True. subpixel : bool, optional Locate points with subpixel accuracy. + chessboard : bool, optional + If True, converts the input chessboard image to a line-pattern image. + select_peaks : bool, optional + To select good points based on Gaussian fitting. + **kwargs : optional + Additional parameters for the method 'select_good_peaks' Returns ------- @@ -257,6 +405,8 @@ def calc_slope_distance_ver_lines(mat, ratio=0.3, search_range=30.0, radius=9, distance : float Distance between vertical lines. """ + if chessboard is True: + mat = convert_chessboard_to_linepattern(mat) if denoise is True: mat = ndi.gaussian_filter(mat, 3) mat_roi = prep._select_roi(mat, ratio, square=True) @@ -278,7 +428,9 @@ def calc_slope_distance_ver_lines(mat, ratio=0.3, search_range=30.0, radius=9, option="max", radius=radius, denoise=denoise, norm=norm, subpixel=subpixel, - sensitive=sensitive) + sensitive=sensitive, + select_peaks=select_peaks, + **kwargs) if len(list_ext_point) > 3: distance = np.median(np.abs(np.diff(list_ext_point))) else: @@ -404,29 +556,67 @@ def get_tilted_profile(mat, index, angle_deg, direction): return xlist, ylist, profile +def convert_chessboard_to_linepattern(mat, smooth=True, bgr="bright", + sigma=3): + """ + Convert a chessboard image to a line-pattern image. + + Parameters + ---------- + mat : array_like + 2D array. + smooth : bool, optional + Apply a gaussian smoothing filter if True. + bgr : {'bright', 'dark'} + Select the background of the output image. + sigma : int + Sigma of the Gaussian window, if smooth is True. + + Returns + ------- + array_like + Line-pattern image. + """ + if smooth is True: + mat = ndi.gaussian_filter(mat, sigma, mode="nearest") + mat_line = np.mean(np.abs(np.gradient(mat)), axis=0) + if smooth is True: + mat_line = np.pad(mat_line[4:-4, 4:-4], 4, mode="edge") + else: + mat_line = np.pad(mat_line[2:-2, 2:-2], 2, mode="edge") + if bgr == "bright": + mat_line = np.max(mat_line) - mat_line + mat_line = mat_line / np.mean(np.abs(mat_line)) + return mat_line + + def get_cross_points_hor_lines(mat, slope_ver, dist_ver, ratio=1.0, norm=True, offset=0, bgr="bright", radius=7, - sensitive=0.1, denoise=True, subpixel=True): + sensitive=0.1, denoise=True, subpixel=True, + chessboard=False, select_peaks=False, **kwargs): """ - Get points on horizontal lines of a line-pattern image by intersecting with - a list of generated vertical-lines. + Get points on horizontal lines of a line-pattern image, or a chessboard + image, by intersecting with a list of generated vertical-lines. Parameters ---------- mat : array_like 2D array. slope_ver : float - Slope in Radian of generated vertical lines. + Representative slope of vertical lines, can be calculated by using the + 'calc_slope_distance_ver_lines' method. dist_ver : float - Distance between two adjacent generated lines. + Representative distance between vertical lines, can be calculated by + using the 'calc_slope_distance_ver_lines' method. ratio : float - To adjust the distance between generated lines to get more/less lines. + To adjust the distance (=ratio * dist_ver) between generated lines + to create more or fewer lines. norm : bool, optional Apply background normalization to the array. offset : int Starting index of generated lines. bgr : {"bright", "dark"} - Specify the brightness of the background against the lines. + Specify the brightness of the background relative to the lines. radius : int Search radius. Used to locate extremum points. sensitive : float @@ -436,6 +626,13 @@ def get_cross_points_hor_lines(mat, slope_ver, dist_ver, ratio=1.0, norm=True, Applying a smoothing filter if True. subpixel : bool, optional Locate points with subpixel accuracy. + chessboard : bool, optional + If True, cross points are located by finding local maxima of slopes + of local linear fits of the generated lines. + select_peaks : bool, optional + To select good points based on Gaussian fitting. + **kwargs : optional + Additional parameters for the method 'select_good_peaks' Returns ------- @@ -452,17 +649,21 @@ def get_cross_points_hor_lines(mat, slope_ver, dist_ver, ratio=1.0, norm=True, angle = np.arctan(slope_ver) min_row, max_row = _calc_index_range(height, width, np.rad2deg(angle), direction="vertical") - offset = np.clip(offset, 0, min(height, width) // 3) + offset = int(np.clip(offset, 0, min(height, width) // 3)) list_points = [] for i in np.arange(min_row + offset, max_row - offset, ratio * dist_ver): xlist, ylist, profile = get_tilted_profile(mat, i, np.rad2deg(angle), direction="vertical") scale = np.sqrt((xlist[-1] - xlist[0]) ** 2 + (ylist[-1] - ylist[0]) ** 2) / (height - 1) + if chessboard is True: + profile = sliding_window_slope(profile, size=3) rlist = get_local_extrema_points(profile, option="max", radius=radius, sensitive=sensitive, denoise=not denoise, norm=not norm, - subpixel=subpixel) * scale + subpixel=subpixel, + select_peaks=select_peaks, + **kwargs) * scale xlist1 = rlist * np.sin(angle) + xlist[0] ylist1 = rlist * np.cos(angle) + ylist[0] list_points.extend(np.asarray(list(zip(ylist1, xlist1)))) @@ -471,21 +672,25 @@ def get_cross_points_hor_lines(mat, slope_ver, dist_ver, ratio=1.0, norm=True, def get_cross_points_ver_lines(mat, slope_hor, dist_hor, ratio=1.0, norm=True, offset=0, bgr="bright", radius=7, - sensitive=0.1, denoise=True, subpixel=True): + sensitive=0.1, denoise=True, subpixel=True, + chessboard=False, select_peaks=False, **kwargs): """ - Get points on vertical lines of a line-pattern image by intersecting with - a list of generated horizontal-lines. + Get points on vertical lines of a line-pattern image, or a chessboard + image, by intersecting with a list of generated horizontal-lines. Parameters ---------- mat : array_like 2D array. slope_hor : float - Slope in Radian of generated horizontal lines. + Representative slope of horizontal lines, can be calculated by using + the 'calc_slope_distance_hor_lines' method. dist_hor : float - Distance between two adjacent generated lines. + Representative distance between horizontal lines, can be calculated by + using the 'calc_slope_distance_hor_lines' method. ratio : float - To adjust the distance between generated lines to get more/less lines. + To adjust the distance (=ratio * dist_hor) between generated lines + to create more or fewer lines. norm : bool, optional Apply background normalization to the array. offset : int @@ -501,6 +706,13 @@ def get_cross_points_ver_lines(mat, slope_hor, dist_hor, ratio=1.0, norm=True, Applying a smoothing filter if True. subpixel : bool, optional Locate points with subpixel accuracy. + chessboard : bool, optional + If True, cross points are located by finding local maxima of slopes + of local linear fits of the generated lines. + select_peaks : bool, optional + To select good points based on Gaussian fitting. + **kwargs : optional + Additional parameters for the method 'select_good_peaks' Returns ------- @@ -517,49 +729,23 @@ def get_cross_points_ver_lines(mat, slope_hor, dist_hor, ratio=1.0, norm=True, angle = np.arctan(slope_hor) min_col, max_col = _calc_index_range(height, width, -np.rad2deg(angle), direction="horizontal") - offset = np.clip(offset, 0, min(height, width) // 8) + offset = int(np.clip(offset, 0, min(height, width) // 8)) list_points = [] for i in np.arange(min_col + offset, max_col - offset, ratio * dist_hor): xlist, ylist, profile = get_tilted_profile(mat, i, -np.rad2deg(angle), direction="horizontal") scale = np.sqrt((xlist[-1] - xlist[0]) ** 2 + (ylist[-1] - ylist[0]) ** 2) / (width - 1) + if chessboard is True: + profile = sliding_window_slope(profile, size=3) rlist = get_local_extrema_points(profile, option="max", radius=radius, sensitive=sensitive, denoise=not denoise, norm=not norm, - subpixel=subpixel) * scale + subpixel=subpixel, + select_peaks=select_peaks, + **kwargs) * scale xlist1 = rlist * np.cos(angle) + xlist[0] ylist1 = rlist * np.sin(angle) + ylist[0] list_points.extend(np.asarray(list(zip(ylist1, xlist1)))) return np.asarray(list_points) - -def convert_chessboard_to_linepattern(mat, smooth=False, bgr="bright"): - """ - Convert a chessboard image to a line-pattern image. - - Parameters - ---------- - mat : array_like - 2D array. - smooth : bool, optional - Apply a gaussian smoothing filter if True. - bgr : {'bright', 'dark'} - Select the background of the output image. - - Returns - ------- - array_like - Line-pattern image. - """ - if smooth is True: - mat = ndi.gaussian_filter(mat, 1, mode="nearest") - mat_line = np.mean(np.abs(np.gradient(mat)), axis=0) - if smooth is True: - mat_line = np.pad(mat_line[4:-4, 4:-4], 4, mode="edge") - else: - mat_line = np.pad(mat_line[2:-2, 2:-2], 2, mode="edge") - if bgr == "bright": - mat_line = np.max(mat_line) - mat_line - mat_line = mat_line / np.mean(np.abs(mat_line)) - return mat_line diff --git a/discorpy/prep/preprocessing.py b/discorpy/prep/preprocessing.py index cace705..a328c27 100644 --- a/discorpy/prep/preprocessing.py +++ b/discorpy/prep/preprocessing.py @@ -617,8 +617,8 @@ def group_dots_hor_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, Returns ------- list of array_like - List of 2D arrays. Each list is the coordinates (y, x) of dot-centroids - belong to the same group. Length of each list may be different. + List of 2D arrays. Each array is (y, x)-coordinates of points belong + to the same group. Length of each list may be different. """ mat = np.asarray(mat) if mat.shape[-1] > 2: @@ -655,7 +655,7 @@ def group_dots_hor_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, if len(dots_selected) > 1: list_lines.append(dots_selected) list_len = [len(i) for i in list_lines] - len_accepted = np.int16(accepted_ratio * np.max(list_len)) + len_accepted = int(accepted_ratio * np.max(list_len)) lines_selected = [line for line in list_lines if len(line) > len_accepted] lines_selected = sorted( lines_selected, key=lambda list_: np.mean(list_[:, 0])) @@ -663,7 +663,7 @@ def group_dots_hor_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, def group_dots_ver_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, - accepted_ratio=0.65): + accepted_ratio=0.75): """ Group dots into vertical lines. @@ -687,8 +687,8 @@ def group_dots_ver_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, Returns ------- list of array_like - List of 2D arrays. Each list is the coordinates (y, x) of dot-centroids - belong to the same group. Length of each list may be different. + List of 2D arrays. Each array is (y,x)-coordinates of points belong + to the same group. Length of each list may be different. """ mat = np.asarray(mat) if mat.shape[-1] > 2: @@ -717,7 +717,6 @@ def group_dots_ver_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, dot1 = dot2 dots_selected = np.vstack((dots_selected, dot2)) pos_get.append(i) - list_pos = np.arange(0, len(list_dots_left), dtype=np.int32) pos_get = np.asarray(pos_get, dtype=np.int32) list_pos_left = np.asarray( @@ -728,7 +727,7 @@ def group_dots_ver_lines(mat, slope, dot_dist, ratio=0.3, num_dot_miss=6, dots_selected = np.fliplr(dots_selected) # Swap back list_lines.append(dots_selected) list_length = [len(i) for i in list_lines] - len_accepted = np.int16(accepted_ratio * np.max(list_length)) + len_accepted = int(accepted_ratio * np.max(list_length)) lines_selected = [line for line in list_lines if len(line) > len_accepted] lines_selected = sorted( lines_selected, key=lambda list_: np.mean(list_[:, 1])) @@ -763,7 +762,10 @@ def remove_residual_dots_hor(list_lines, slope, residual=2.5): - list_[:, 0]) * np.cos(np.arctan(slope))) dots_left = np.asarray( [dot for i, dot in enumerate(list_) if error[i] < residual]) - list_lines2.append(dots_left) + if len(dots_left) > 0: + list_lines2.append(dots_left) + if len(list_lines2) == 0: + raise ValueError("No dots left. Check the input or residual !!!") return list_lines2 @@ -797,8 +799,11 @@ def remove_residual_dots_ver(list_lines, slope, residual=2.5): - list_[:, 0]) * np.cos(np.arctan(slope))) dots_left = np.asarray( [dot for i, dot in enumerate(list_) if error[i] < residual]) - dots_left = np.fliplr(dots_left) # Swap back - list_lines2.append(dots_left) + if len(dots_left) > 0: + dots_left = np.fliplr(dots_left) # Swap back + list_lines2.append(dots_left) + if len(list_lines2) == 0: + raise ValueError("No dots left. Check the input or residual !!!") return list_lines2 @@ -832,7 +837,7 @@ def calculate_threshold(mat, bgr="bright", snr=2.0): xlist = np.arange(0, npoint, 1.0) ndrop = int(0.25 * npoint) (slope, intercept) = np.polyfit(xlist[ndrop:-ndrop - 1], - list_dsp[ndrop:-ndrop - 1], 1) + list_dsp[ndrop:-ndrop - 1], 1)[:2] y_end = intercept + slope * xlist[-1] noise_level = np.abs(y_end - intercept) if bgr == "bright": diff --git a/discorpy/proc/processing.py b/discorpy/proc/processing.py index 1f1b8e6..bde8ee4 100644 --- a/discorpy/proc/processing.py +++ b/discorpy/proc/processing.py @@ -27,7 +27,7 @@ """ Module of processing methods: -- Fit lines of dots to parabolas, find the center of distortion. +- Fit lines of points to parabolas, find the center of distortion. - Calculate undistorted intercepts of gridlines. - Calculate distortion coefficients of the backward model, the forward model, and the backward-from-forward model. @@ -42,23 +42,23 @@ def _para_fit_hor(list_lines, xcenter, ycenter): """ - Fit horizontal lines of dots to parabolas. + Fit horizontal lines of points to parabolas. Parameters ---------- list_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each line. + List of (y,x)-coordinates of points on each line. xcenter : float - Center of distortion in x-direction. + Center of distortion in the x-direction. ycenter : float - Center of distortion in y-direction. + Center of distortion in the y-direction. Returns ------- list_coef : list of 1D arrays - List of the coefficients of each parabola (y=ax**2+bx+c). + List of coefficients of each parabola (y=ax**2+bx+c). list_slines : list of 2D arrays - List of the shifted (y,x)-coordinates of dot-centroids on each line. + List of shifted (y,x)-coordinates of points on each line. """ num_line = len(list_lines) list_coef = np.zeros((num_line, 3), dtype=np.float32) @@ -75,23 +75,23 @@ def _para_fit_hor(list_lines, xcenter, ycenter): def _para_fit_ver(list_lines, xcenter, ycenter): """ - Fit vertical lines of dots to parabolas. + Fit vertical lines of points to parabolas. Parameters ---------- list_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each line. + List of (y,x)-coordinates of points on each line. xcenter : float - Center of distortion in x-direction. + Center of distortion in the x-direction. ycenter : float - Center of distortion in y-direction. + Center of distortion in the y-direction. Returns ------- list_coef : list of 1D arrays - List of the coefficients of each parabola (x=ay**2+by+c). + List of coefficients of each parabola (x=ay**2+by+c). list_slines : list of 2D arrays - List of the shifted (y,x)-coordinates of dot-centroids on each line. + List of shifted (y,x)-coordinates of points on each line. """ num_line = len(list_lines) list_coef = np.zeros((num_line, 3), dtype=np.float32) @@ -113,16 +113,16 @@ def find_cod_coarse(list_hor_lines, list_ver_lines): Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of (y,x)-coordinates of points on each vertical line. Returns ------- xcenter : float - Center of distortion in x-direction. + Center of distortion in the x-direction. ycenter : float - Center of distortion in y-direction. + Center of distortion in the y-direction. """ (list_coef_hor, list_hor_lines) = _para_fit_hor(list_hor_lines, 0.0, 0.0) (list_coef_ver, list_ver_lines) = _para_fit_ver(list_ver_lines, 0.0, 0.0) @@ -195,9 +195,9 @@ def _calc_metric(list_hor_lines, list_ver_lines, xcenter, ycenter, Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Center of distortion in x-direction. ycenter : float @@ -250,15 +250,15 @@ def find_cod_fine(list_hor_lines, list_ver_lines, xcenter, ycenter, dot_dist): Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Coarse estimation of the CoD in x-direction. ycenter : float Coarse estimation of the CoD in y-direction. dot_dist : float - Median distance of two nearest dots. + Median distance of two nearest points. Returns ------- @@ -349,9 +349,9 @@ def _calc_undistor_intercept(list_hor_lines, list_ver_lines, xcenter, ycenter, Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Center of distortion in x-direction. ycenter : float @@ -375,7 +375,7 @@ def _calc_undistor_intercept(list_hor_lines, list_ver_lines, xcenter, ycenter, check = _check_missing_lines(list_coef_hor, list_coef_ver, threshold=threshold) if check: - msg = "!!! Parameters of the methods of grouping dots need to be " \ + msg = "!!! Parameters of the methods of grouping points need to be " \ "adjusted !!!\n!!! Check if there are missing lines or adjust " \ "the threshold value !!!" raise ValueError(msg) @@ -414,9 +414,9 @@ def calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Center of distortion in x-direction. ycenter : float @@ -478,9 +478,9 @@ def calc_coef_forward(list_hor_lines, list_ver_lines, xcenter, ycenter, Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Center of distortion in x-direction. ycenter : float @@ -548,9 +548,9 @@ def calc_coef_backward_from_forward(list_hor_lines, list_ver_lines, xcenter, Parameters ---------- list_hor_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each horizontal line. + List of the (y,x)-coordinates of points on each horizontal line. list_ver_lines : list of 2D arrays - List of the (y,x)-coordinates of dot-centroids on each vertical line. + List of the (y,x)-coordinates of points on each vertical line. xcenter : float Center of distortion in x-direction. ycenter : float diff --git a/docs/source/usage/codes/demo_01.py b/docs/source/usage/codes/demo_01.py index 38fff32..73e4c16 100644 --- a/docs/source/usage/codes/demo_01.py +++ b/docs/source/usage/codes/demo_01.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -8,7 +8,7 @@ file_path = "../../data/dot_pattern_01.jpg" output_base = "E:/output_demo_01/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Segment dots mat1 = prep.binarization(mat0) @@ -18,7 +18,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -33,17 +33,17 @@ # Optional: remove vertical outliers list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) # Check residual of dots on lines list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Optional: correct perspective effect. Only available from Discorpy 1.4 @@ -56,7 +56,7 @@ list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) # Save the results for later use. -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -67,21 +67,21 @@ list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) # Calculate the residual of the unwarpped points. list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. Convert to lower-bit if need to. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/docs/source/usage/codes/demo_02.py b/docs/source/usage/codes/demo_02.py index cb4932e..ca8e209 100644 --- a/docs/source/usage/codes/demo_02.py +++ b/docs/source/usage/codes/demo_02.py @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -9,7 +9,7 @@ file_path = "../../data/dot_pattern_02.jpg" output_base = "E:/output_demo_02/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Segment dots mat1 = prep.binarization(mat0) @@ -19,7 +19,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -32,15 +32,15 @@ list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, hor_slope) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) print("Horizontal slope: {0}. Vertical slope: {1}".format(hor_slope, ver_slope)) @@ -83,15 +83,15 @@ list_hor_lines, list_ver_lines = proc.regenerate_grid_points_parabola( list_hor_lines, list_ver_lines, perspective=True) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines_regenerated.png", +losa.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines_regenerated.png", +losa.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines, height, width) (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -104,16 +104,16 @@ list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Load coefficients from previous calculation if need to -# (xcenter, ycenter, list_fact) = io.load_metadata_txt( +# (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. # Convert to lower-bit data before saving to tiff if need to. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/docs/source/usage/codes/demo_03.py b/docs/source/usage/codes/demo_03.py index 0ae6bc9..837c375 100644 --- a/docs/source/usage/codes/demo_03.py +++ b/docs/source/usage/codes/demo_03.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -8,17 +8,17 @@ file_path = "../../data/dot_pattern_04.jpg" output_base = "E:/output_demo_03/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Correct non-uniform background. mat1 = prep.normalization_fft(mat0, sigma=20) -io.save_image(output_base + "/image_normed.tif", mat1) +losa.save_image(output_base + "/image_normed.tif", mat1) # Segment dots. threshold = prep.calculate_threshold(mat1, bgr="bright", snr=3.0) mat1 = prep.binarization(mat1, ratio=0.5, thres=threshold) -io.save_image(output_base + "/image_binarized.tif", mat1) +losa.save_image(output_base + "/image_binarized.tif", mat1) # Calculate the median dot size and distance between them. (dot_size, dot_dist) = prep.calc_size_distance(mat1) @@ -26,7 +26,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.8) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1, ratio=0.8) -io.save_image(output_base + "/image_cleaned.tif", mat1) +losa.save_image(output_base + "/image_cleaned.tif", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) @@ -45,15 +45,15 @@ residual=2.0) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Regenerate grid points after correcting the perspective effect. @@ -64,7 +64,7 @@ (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -79,17 +79,17 @@ list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit-tif. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/docs/source/usage/codes/demo_04.py b/docs/source/usage/codes/demo_04.py index a4e339c..7a9d806 100644 --- a/docs/source/usage/codes/demo_04.py +++ b/docs/source/usage/codes/demo_04.py @@ -1,4 +1,4 @@ -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -11,7 +11,7 @@ num_coef = 5 # Number of polynomial coefficients print("1-> Load image: {}".format(file_path)) -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape print("2-> Calculate slope and distance between lines!!!") @@ -23,8 +23,8 @@ print("3-> Extract reference-points !!!!") list_points_hor_lines = lprep.get_cross_points_hor_lines(mat0, slope_ver, dist_ver, ratio=0.5, sensitive=0.1) list_points_ver_lines = lprep.get_cross_points_ver_lines(mat0, slope_hor, dist_hor, ratio=0.5, sensitive=0.1) -io.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) -io.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) +losa.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) +losa.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) print("4-> Group points into lines !!!!") @@ -33,8 +33,8 @@ # Optional: remove residual dots list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, slope_hor, 2.0) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) -io.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) +losa.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) +losa.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) print("5-> Correct perspective effect !!!!") @@ -44,10 +44,10 @@ # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_horizontal_points_before.png", +losa.save_residual_plot(output_base + "/residual_horizontal_points_before.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_vertical_points_before.png", +losa.save_residual_plot(output_base + "/residual_vertical_points_before.png", list_ver_data, height, width) print("6-> Calculate the centre of distortion !!!!") @@ -63,14 +63,14 @@ list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/residual_horizontal_points_after.png", +losa.save_residual_plot(output_base + "/residual_horizontal_points_after.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/residual_vertical_points_after.png", +losa.save_residual_plot(output_base + "/residual_vertical_points_after.png", list_ver_data, height, width) # Output print("8-> Apply correction to image !!!!") corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) -io.save_image(output_base + "/difference.tif", mat0 - corrected_mat) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) +losa.save_image(output_base + "/difference.tif", mat0 - corrected_mat) print("!!! Done !!!!") diff --git a/docs/source/usage/codes/demo_05.py b/docs/source/usage/codes/demo_05.py index 34a94da..bb729ec 100644 --- a/docs/source/usage/codes/demo_05.py +++ b/docs/source/usage/codes/demo_05.py @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -10,7 +10,7 @@ file_path = "../../data/dot_pattern_06.jpg" output_base = "E:/output_demo_05/" num_coef = 4 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Normalize background @@ -18,7 +18,7 @@ # Segment dots threshold = prep.calculate_threshold(mat1, bgr="bright", snr=1.5) mat1 = prep.binarization(mat1, thres=threshold) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the median dot size and distance between them. (dot_size, dot_dist) = prep.calc_size_distance(mat1) @@ -36,13 +36,13 @@ accepted_ratio=0.6) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines0, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines0, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Optional: for checking perspective distortion @@ -83,16 +83,16 @@ list_hor_lines0, list_ver_lines0, perspective=True) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines_regenerated.png", +losa.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines1, height, width) -io.save_plot_image(output_base + "/vertical_lines_regenerated.png", +losa.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines1, height, width) # Calculate parameters of the radial correction model (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines1, list_ver_lines1) list_fact = proc.calc_coef_backward(list_hor_lines1, list_ver_lines1, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -120,14 +120,14 @@ # Check the residual of unwarped lines: list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Unwarp the image mat_rad_corr = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results -io.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) -io.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) +losa.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) +losa.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) # ------------------------------------- # For perspective distortion correction @@ -147,5 +147,5 @@ image_pers_corr = post.correct_perspective_image(mat_rad_corr, pers_coef) # Save results np.savetxt(output_base + "/perspective_coefficients.txt", np.transpose([pers_coef])) -io.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) -io.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) +losa.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) +losa.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) diff --git a/docs/source/usage/codes/demo_06.py b/docs/source/usage/codes/demo_06.py index 3111745..60ba7ca 100644 --- a/docs/source/usage/codes/demo_06.py +++ b/docs/source/usage/codes/demo_06.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -9,12 +9,12 @@ file_path = "../../data/laptop_camera/chessboard.jpg" output_base = "E:/output_demo_06/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Convert the chessboard image to a line-pattern image mat1 = lprep.convert_chessboard_to_linepattern(mat0) -io.save_image(output_base + "/line_pattern_converted.jpg", mat1) +losa.save_image(output_base + "/line_pattern_converted.jpg", mat1) # Calculate slope and distance between lines slope_hor, dist_hor = lprep.calc_slope_distance_hor_lines(mat1, radius=15, sensitive=0.5) @@ -35,9 +35,9 @@ subpixel=True) if len(list_points_hor_lines) == 0 or len(list_points_ver_lines) == 0: raise ValueError("No reference-points detected !!! Please adjust parameters !!!") -io.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, +losa.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, height, width, color="red") -io.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, +losa.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, height, width, color="blue") # Group points into lines @@ -50,13 +50,13 @@ list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Regenerate grid points after correcting the perspective effect. @@ -67,7 +67,7 @@ (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -82,42 +82,42 @@ list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. -io.save_image(output_base + "/corrected_image.jpg", corrected_mat) -io.save_image(output_base + "/difference.jpg", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.jpg", corrected_mat) +losa.save_image(output_base + "/difference.jpg", corrected_mat - mat0) # ---------------------------------------- # Load original color image for correction # ------------------------------------------ # Load coefficients from previous calculation if need to -# (xcenter, ycenter, list_fact) = io.load_metadata_txt( +# (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") -img = io.load_image(file_path, average=False) +img = losa.load_image(file_path, average=False) img_corrected = np.copy(img) # Unwarped each color channel of the image for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_fact) # Save the unwarped image. -io.save_image(output_base + "/corrected_image_color.jpg", img_corrected) +losa.save_image(output_base + "/corrected_image_color.jpg", img_corrected) # Load a test image and correct it. -img = io.load_image("../../data/laptop_camera/test_image.jpg", average=False) +img = losa.load_image("../../data/laptop_camera/test_image.jpg", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_fact) -io.save_image(output_base + "/test_image_corrected.jpg", img_corrected) +losa.save_image(output_base + "/test_image_corrected.jpg", img_corrected) diff --git a/docs/source/usage/codes/demo_07.py b/docs/source/usage/codes/demo_07.py index 35332dd..b3bc34d 100644 --- a/docs/source/usage/codes/demo_07.py +++ b/docs/source/usage/codes/demo_07.py @@ -1,12 +1,12 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post # Load image file_path = "../../data/demo/perspective_demo.jpg" output_base = "E:/output_demo_07/" -mat = io.load_image(file_path, average=False) +mat = losa.load_image(file_path, average=False) # Provide the coordinates of 4-points. They can be in xy-order or yx-order, this info # needs to be consistent with other functions. In this example, it's in the xy-order. @@ -23,7 +23,7 @@ mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef) -io.save_image(output_base + "/corrected_image.jpg", mat_cor) +losa.save_image(output_base + "/corrected_image.jpg", mat_cor) # The region of interest may be out of the field of view or rotated. # We can rotate the output image, offset, and scale it by changing the target @@ -58,5 +58,5 @@ mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef2, order=3) -io.save_image(output_base + "/adjusted_image.jpg", mat_cor) +losa.save_image(output_base + "/adjusted_image.jpg", mat_cor) print("!!! Done !!!") \ No newline at end of file diff --git a/docs/source/usage/codes/demo_08.py b/docs/source/usage/codes/demo_08.py index 6c91688..bf62fdf 100644 --- a/docs/source/usage/codes/demo_08.py +++ b/docs/source/usage/codes/demo_08.py @@ -1,6 +1,6 @@ import os import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post import scipy.ndimage as ndi @@ -8,7 +8,7 @@ file_path = "../../data/percy_cam/F_R_hazcam.png" output_base = "E:/output_demo_08/" -mat0 = io.load_image(file_path, average=True) +mat0 = losa.load_image(file_path, average=True) mat0 = mat0 / np.max(mat0) (height, width) = mat0.shape @@ -46,7 +46,7 @@ def scan_coef(idx, start, stop, step, list_coef, list_power, output_base0, mat0, ycenter + pad, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "coef_{0}_val_{1:4.2f}".format(idx, list_coef_est[idx]) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -54,7 +54,7 @@ def scan_coef(idx, start, stop, step, list_coef, list_power, output_base0, mat0, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, output_base0, mat0, mat_pad, pad, axis="x", ntime=1, backward=True): @@ -72,7 +72,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "xcenter_{0:7.2f}".format(xcenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -80,7 +80,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter+num, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) else: for num in np.arange(start, stop + step, step): line_img_warped = post.unwarp_image_backward(mat_pad, xcenter + pad, @@ -88,7 +88,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "ycenter_{0:7.2f}".format(ycenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -96,7 +96,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter+num, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) ## Scan the 4th coefficient scan_coef(4, 0, 30, 1, list_coef, list_power, output_base, mat0, mat_pad, pad) @@ -140,7 +140,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points=ref_points) # Load the color image -img = io.load_image(file_path, average=False) +img = losa.load_image(file_path, average=False) img_corrected = np.copy(img) # Unwarped each color channel of the image @@ -149,20 +149,20 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ycenter, list_bfact) # Save the unwarped image. -io.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) +losa.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) # Correct other images from the same camera -img = io.load_image("../../data/percy_cam/rock_core1.png", average=False) +img = losa.load_image("../../data/percy_cam/rock_core1.png", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) -io.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) +losa.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) -img = io.load_image("../../data/percy_cam/rock_core2.png", average=False) +img = losa.load_image("../../data/percy_cam/rock_core2.png", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) -io.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) +losa.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) diff --git a/docs/source/usage/demo_01.rst b/docs/source/usage/demo_01.rst index e6df74d..855add6 100644 --- a/docs/source/usage/demo_01.rst +++ b/docs/source/usage/demo_01.rst @@ -12,7 +12,7 @@ acquired at Beamline I12, Diamond Light Source. .. code-block:: python import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -21,7 +21,7 @@ acquired at Beamline I12, Diamond Light Source. file_path = "../../data/dot_pattern_01.jpg" output_base = "E:/output_demo_01/" num_coef = 5 # Number of polynomial coefficients - mat0 = io.load_image(file_path) # Load image + mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape .. figure:: figs/demo_01/fig1.jpg @@ -45,7 +45,7 @@ acquired at Beamline I12, Diamond Light Source. mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) - io.save_image(output_base + "/segmented_dots.jpg", mat1) # Save image for checking + losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Save image for checking # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -79,8 +79,8 @@ acquired at Beamline I12, Diamond Light Source. # Optional: remove vertical outliers list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) + losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) + losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) # Optional: correct perspective effect. Only available from Discorpy 1.4 # list_hor_lines, list_ver_lines = proc.regenerate_grid_points_parabola( @@ -105,9 +105,9 @@ acquired at Beamline I12, Diamond Light Source. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/hor_residual_before_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_before_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) .. figure:: figs/demo_01/fig4.png @@ -134,7 +134,7 @@ acquired at Beamline I12, Diamond Light Source. list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) # Save the results for later use. - io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", + losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -155,17 +155,17 @@ acquired at Beamline I12, Diamond Light Source. list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) # Save the results for checking - io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, + losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) - io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, + losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) # Calculate the residual of the unwarpped points. list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking - io.save_residual_plot(output_base + "/hor_residual_after_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_after_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) @@ -194,13 +194,13 @@ acquired at Beamline I12, Diamond Light Source. .. code-block:: python # Load coefficients from previous calculation if need to - # (xcenter, ycenter, list_fact) = io.load_metadata_txt( + # (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. Convert to lower-bit if need to. - io.save_image(output_base + "/corrected_image.tif", corrected_mat) - io.save_image(output_base + "/difference.tif", corrected_mat - mat0) + losa.save_image(output_base + "/corrected_image.tif", corrected_mat) + losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) .. figure:: figs/demo_01/fig7.jpg :name: fig_29 diff --git a/docs/source/usage/demo_02.rst b/docs/source/usage/demo_02.rst index 74a0f62..12928cd 100644 --- a/docs/source/usage/demo_02.rst +++ b/docs/source/usage/demo_02.rst @@ -16,7 +16,7 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff import numpy as np import matplotlib.pyplot as plt - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -25,7 +25,7 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff file_path = "../../data/dot_pattern_02.jpg" output_base = "E:/output_demo_02/" num_coef = 5 # Number of polynomial coefficients - mat0 = io.load_image(file_path) # Load image + mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Segment dots mat1 = prep.binarization(mat0) @@ -35,7 +35,7 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) - io.save_image(output_base + "/segmented_dots.jpg", mat1) + losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -46,13 +46,13 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, hor_slope) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) + losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) + losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/hor_residual_before_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_before_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) print("Horizontal slope: {0}. Vertical slope: {1}".format(hor_slope, ver_slope)) @@ -141,9 +141,9 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff list_hor_lines, list_ver_lines = proc.regenerate_grid_points_parabola( list_hor_lines, list_ver_lines, perspective=True) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines, + losa.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines, + losa.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines, height, width) .. figure:: figs/demo_02/fig4.png @@ -174,7 +174,7 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) - io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", + losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -184,18 +184,18 @@ acquired at Beamline I13 Diamond Light Source, which has a small perspective eff list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) - io.save_residual_plot(output_base + "/hor_residual_after_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_after_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Load coefficients from previous calculation if need to - # (xcenter, ycenter, list_fact) = io.load_metadata_txt( + # (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. Convert to lower-bit if need to. - io.save_image(output_base + "/corrected_image.tif", corrected_mat) - io.save_image(output_base + "/difference.tif", corrected_mat - mat0) + losa.save_image(output_base + "/corrected_image.tif", corrected_mat) + losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) .. figure:: figs/demo_02/fig6.png :name: fig_36 diff --git a/docs/source/usage/demo_03.rst b/docs/source/usage/demo_03.rst index 1c3edf6..64845eb 100644 --- a/docs/source/usage/demo_03.rst +++ b/docs/source/usage/demo_03.rst @@ -15,7 +15,7 @@ which was acquired at Beamline I13, Diamond Light Source. :emphasize-lines: 15 import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -24,12 +24,12 @@ which was acquired at Beamline I13, Diamond Light Source. file_path = "../../data/dot_pattern_04.jpg" output_base = "E:/output_demo_03/" num_coef = 5 # Number of polynomial coefficients - mat0 = io.load_image(file_path) # Load image + mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Correct non-uniform background. mat1 = prep.normalization_fft(mat0, sigma=20) - io.save_image(output_base + "/image_normed.tif", mat1) + losa.save_image(output_base + "/image_normed.tif", mat1) .. figure:: figs/demo_03/fig1.jpg :name: fig_40 @@ -49,7 +49,7 @@ which was acquired at Beamline I13, Diamond Light Source. # Segment dots. threshold = prep.calculate_threshold(mat1, bgr="bright", snr=3.0) mat1 = prep.binarization(mat1, ratio=0.5, thres=threshold) - io.save_image(output_base + "/image_binarized.tif", mat1) + losa.save_image(output_base + "/image_binarized.tif", mat1) - There are lots of non-dot objects left after the binarization step (:numref:`fig_41` (a)). They can be removed further (:numref:`fig_41` (b)) by tweaking parameters of @@ -65,7 +65,7 @@ which was acquired at Beamline I13, Diamond Light Source. mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.8) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1, ratio=0.8) - io.save_image(output_base + "/image_cleaned.tif", mat1) + losa.save_image(output_base + "/image_cleaned.tif", mat1) .. figure:: figs/demo_03/fig2.jpg :name: fig_41 @@ -99,15 +99,15 @@ which was acquired at Beamline I13, Diamond Light Source. residual=2.0) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, + losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, + losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/hor_residual_before_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_before_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) .. figure:: figs/demo_03/fig3.png @@ -154,7 +154,7 @@ which was acquired at Beamline I13, Diamond Light Source. (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) - io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", + losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -174,20 +174,20 @@ which was acquired at Beamline I13, Diamond Light Source. list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking - io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", + losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) - io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", + losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) - io.save_residual_plot(output_base + "/hor_residual_after_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_after_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit-tif. - io.save_image(output_base + "/corrected_image.tif", corrected_mat) - io.save_image(output_base + "/difference.tif", corrected_mat - mat0) + losa.save_image(output_base + "/corrected_image.tif", corrected_mat) + losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) .. figure:: figs/demo_03/fig6.png :name: fig_45 diff --git a/docs/source/usage/demo_04.rst b/docs/source/usage/demo_04.rst index 99b6cfd..6c1280f 100644 --- a/docs/source/usage/demo_04.rst +++ b/docs/source/usage/demo_04.rst @@ -13,7 +13,7 @@ collected at Beamline I13 Diamond Light Source. .. code-block:: python :emphasize-lines: 22-23 - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -26,7 +26,7 @@ collected at Beamline I13 Diamond Light Source. num_coef = 5 # Number of polynomial coefficients print("1-> Load image: {}".format(file_path)) - mat0 = io.load_image(file_path) + mat0 = losa.load_image(file_path) (height, width) = mat0.shape print("2-> Calculate slope and distance between lines!!!") @@ -56,8 +56,8 @@ collected at Beamline I13 Diamond Light Source. print("3-> Extract reference-points !!!!") list_points_hor_lines = lprep.get_cross_points_hor_lines(mat0, slope_ver, dist_ver, ratio=0.5, sensitive=0.1) list_points_ver_lines = lprep.get_cross_points_ver_lines(mat0, slope_hor, dist_hor, ratio=0.5, sensitive=0.1) - io.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) - io.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) + losa.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) + losa.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) .. figure:: figs/demo_04/fig2.png :name: fig_50 @@ -77,8 +77,8 @@ collected at Beamline I13 Diamond Light Source. # Optional: remove residual dots list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, slope_hor, 2.0) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) - io.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) + losa.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) + losa.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) .. figure:: figs/demo_04/fig3.png :name: fig_51 @@ -99,10 +99,10 @@ collected at Beamline I13 Diamond Light Source. # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/residual_horizontal_points_before.png", + losa.save_residual_plot(output_base + "/residual_horizontal_points_before.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/residual_vertical_points_before.png", + losa.save_residual_plot(output_base + "/residual_vertical_points_before.png", list_ver_data, height, width) print("6-> Calculate the centre of distortion !!!!") @@ -118,16 +118,16 @@ collected at Beamline I13 Diamond Light Source. list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) - io.save_residual_plot(output_base + "/residual_horizontal_points_after.png", + losa.save_residual_plot(output_base + "/residual_horizontal_points_after.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/residual_vertical_points_after.png", + losa.save_residual_plot(output_base + "/residual_vertical_points_after.png", list_ver_data, height, width) # Output print("8-> Apply correction to image !!!!") corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) - io.save_image(output_base + "/corrected_image.tif", corrected_mat) - io.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) - io.save_image(output_base + "/difference.tif", mat0 - corrected_mat) + losa.save_image(output_base + "/corrected_image.tif", corrected_mat) + losa.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) + losa.save_image(output_base + "/difference.tif", mat0 - corrected_mat) print("!!! Done !!!!") diff --git a/docs/source/usage/demo_05.rst b/docs/source/usage/demo_05.rst index 68d6054..2d5f79c 100644 --- a/docs/source/usage/demo_05.rst +++ b/docs/source/usage/demo_05.rst @@ -13,7 +13,7 @@ The image suffers both types of distortions. import numpy as np import matplotlib.pyplot as plt - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -22,7 +22,7 @@ The image suffers both types of distortions. file_path = "../../data/dot_pattern_06.jpg" output_base = "E:/output_demo_05/" num_coef = 4 # Number of polynomial coefficients - mat0 = io.load_image(file_path) # Load image + mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Normalize background @@ -30,7 +30,7 @@ The image suffers both types of distortions. # Segment dots threshold = prep.calculate_threshold(mat1, bgr="bright", snr=1.5) mat1 = prep.binarization(mat1, thres=threshold) - io.save_image(output_base + "/segmented_dots.jpg", mat1) + losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the median dot size and distance between them. (dot_size, dot_dist) = prep.calc_size_distance(mat1) @@ -48,13 +48,13 @@ The image suffers both types of distortions. accepted_ratio=0.6) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) - io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) + losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) + losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines0, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines0, 0.0, 0.0) - io.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, + losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, + losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) .. figure:: figs/demo_05/fig1.jpg @@ -157,7 +157,7 @@ The image suffers both types of distortions. (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines1, list_ver_lines1) list_fact = proc.calc_coef_backward(list_hor_lines1, list_ver_lines1, xcenter, ycenter, num_coef) - io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", + losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -181,16 +181,16 @@ The image suffers both types of distortions. # Check the residual of unwarped lines: list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) - io.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, + losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, + losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Unwarp the image mat_rad_corr = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results - io.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) - io.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) + losa.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) + losa.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) .. figure:: figs/demo_05/fig6.png :name: fig_61 @@ -228,8 +228,8 @@ The image suffers both types of distortions. image_pers_corr = post.correct_perspective_image(mat_rad_corr, pers_coef) # Save results np.savetxt(output_base + "/perspective_coefficients.txt", np.transpose([pers_coef])) - io.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) - io.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) + losa.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) + losa.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) .. figure:: figs/demo_05/fig8.png :name: fig_63 diff --git a/docs/source/usage/demo_06.rst b/docs/source/usage/demo_06.rst index 8aea759..70d6147 100644 --- a/docs/source/usage/demo_06.rst +++ b/docs/source/usage/demo_06.rst @@ -16,7 +16,7 @@ Laptop. The pincushion distortion is visible in the image. .. code-block:: python import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -26,12 +26,12 @@ Laptop. The pincushion distortion is visible in the image. file_path = "../../data/laptop_camera/chessboard.jpg" output_base = "E:/output_demo_06/" num_coef = 5 # Number of polynomial coefficients - mat0 = io.load_image(file_path) # Load image + mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Convert the chessboard image to a line-pattern image mat1 = lprep.convert_chessboard_to_linepattern(mat0) - io.save_image(output_base + "/line_pattern_converted.jpg", mat1) + losa.save_image(output_base + "/line_pattern_converted.jpg", mat1) # Calculate slope and distance between lines slope_hor, dist_hor = lprep.calc_slope_distance_hor_lines(mat1, radius=15, sensitive=0.5) @@ -68,9 +68,9 @@ Laptop. The pincushion distortion is visible in the image. subpixel=True) if len(list_points_hor_lines) == 0 or len(list_points_ver_lines) == 0: raise ValueError("No reference-points detected !!! Please adjust parameters !!!") - io.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, + losa.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, height, width, color="red") - io.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, + losa.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, height, width, color="blue") # Group points into lines @@ -84,13 +84,13 @@ Laptop. The pincushion distortion is visible in the image. list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) # Save output for checking - io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) - io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) + losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) + losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) - io.save_residual_plot(output_base + "/hor_residual_before_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_before_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) .. figure:: figs/demo_06/fig2.png @@ -133,7 +133,7 @@ Laptop. The pincushion distortion is visible in the image. (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) - io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", + losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -148,13 +148,13 @@ Laptop. The pincushion distortion is visible in the image. list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking - io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", + losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) - io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", + losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) - io.save_residual_plot(output_base + "/hor_residual_after_correction.png", + losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) - io.save_residual_plot(output_base + "/ver_residual_after_correction.png", + losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) .. figure:: figs/demo_06/fig5.png @@ -183,16 +183,16 @@ Laptop. The pincushion distortion is visible in the image. .. code-block:: python # Load coefficients from previous calculation - (xcenter, ycenter, list_fact) = io.load_metadata_txt( + (xcenter, ycenter, list_fact) = losa.load_metadata_txt( output_base + "/coefficients_radial_distortion.txt") # Load an image and correct it. - img = io.load_image("../../data/laptop_camera/test_image.jpg", average=False) + img = losa.load_image("../../data/laptop_camera/test_image.jpg", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_fact) - io.save_image(output_base + "/test_image_corrected.jpg", img_corrected) + losa.save_image(output_base + "/test_image_corrected.jpg", img_corrected) .. figure:: figs/demo_06/fig7.jpg :name: fig_71 diff --git a/docs/source/usage/demo_07.rst b/docs/source/usage/demo_07.rst index 9b8ae8e..e82c78a 100644 --- a/docs/source/usage/demo_07.rst +++ b/docs/source/usage/demo_07.rst @@ -15,14 +15,14 @@ look like a scanned one. .. code-block:: python import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post # Load image file_path = "../../data/demo/perspective_demo.jpg" output_base = "./output_demo_07/" - mat = io.load_image(file_path, average=False) + mat = losa.load_image(file_path, average=False) # Provide the coordinates of 4-points. They can be in xy-order or yx-order, this info # needs to be consistent with other functions. In this example, it's in the xy-order. @@ -52,7 +52,7 @@ look like a scanned one. mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef) - io.save_image(output_base + "/corrected_image.jpg", mat_cor) + losa.save_image(output_base + "/corrected_image.jpg", mat_cor) .. figure:: figs/demo_07/fig2.jpg :name: fig_73 @@ -97,7 +97,7 @@ look like a scanned one. mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef2, order=3) - io.save_image(output_base + "/adjusted_image.jpg", mat_cor) + losa.save_image(output_base + "/adjusted_image.jpg", mat_cor) .. figure:: figs/demo_07/fig3.jpg :name: fig_74 diff --git a/docs/source/usage/demo_08.rst b/docs/source/usage/demo_08.rst index 16741f0..4e02ce7 100644 --- a/docs/source/usage/demo_08.rst +++ b/docs/source/usage/demo_08.rst @@ -18,7 +18,7 @@ how to do that on images acquired by the front-right hazard-camera of the import os import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post import scipy.ndimage as ndi @@ -26,7 +26,7 @@ how to do that on images acquired by the front-right hazard-camera of the file_path = "../../data/percy_cam/F_R_hazcam.png" output_base = "E:/output_demo_08/" - mat0 = io.load_image(file_path, average=True) + mat0 = losa.load_image(file_path, average=True) mat0 = mat0 / np.max(mat0) (height, width) = mat0.shape @@ -81,7 +81,7 @@ how to do that on images acquired by the front-right hazard-camera of the ycenter + pad, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "coef_{0}_val_{1:4.2f}".format(idx, list_coef_est[idx]) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -89,7 +89,7 @@ how to do that on images acquired by the front-right hazard-camera of the ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, output_base0, mat0, mat_pad, pad, axis="x", ntime=1, backward=True): @@ -107,7 +107,7 @@ how to do that on images acquired by the front-right hazard-camera of the list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "xcenter_{0:7.2f}".format(xcenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -115,7 +115,7 @@ how to do that on images acquired by the front-right hazard-camera of the ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter+num, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) else: for num in np.arange(start, stop + step, step): line_img_warped = post.unwarp_image_backward(mat_pad, xcenter + pad, @@ -123,7 +123,7 @@ how to do that on images acquired by the front-right hazard-camera of the list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "ycenter_{0:7.2f}".format(ycenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -131,7 +131,7 @@ how to do that on images acquired by the front-right hazard-camera of the ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter+num, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) ## Scan the 4th coefficient @@ -181,7 +181,7 @@ how to do that on images acquired by the front-right hazard-camera of the list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) # Load the color image - img = io.load_image(file_path, average=False) + img = losa.load_image(file_path, average=False) img_corrected = np.copy(img) # Unwarped each color channel of the image @@ -190,7 +190,7 @@ how to do that on images acquired by the front-right hazard-camera of the ycenter, list_bfact) # Save the unwarped image. - io.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) + losa.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) .. figure:: figs/demo_08/fig2.jpg :name: fig_76 @@ -206,17 +206,17 @@ how to do that on images acquired by the front-right hazard-camera of the .. code-block:: python # Correct other images from the same camera: - img = io.load_image("../../data/percy_cam/rock_core1.png", average=False) + img = losa.load_image("../../data/percy_cam/rock_core1.png", average=False) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) - io.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) + losa.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) - img = io.load_image("../../data/percy_cam/rock_core2.png", average=False) + img = losa.load_image("../../data/percy_cam/rock_core2.png", average=False) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) - io.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) + losa.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) .. figure:: figs/demo_08/fig3.jpg :name: fig_77 diff --git a/docs/source/usage/tips.rst b/docs/source/usage/tips.rst index afbc95c..8cd78b5 100644 --- a/docs/source/usage/tips.rst +++ b/docs/source/usage/tips.rst @@ -8,14 +8,14 @@ Useful tips .. code-block:: python import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post file_path = "../../data/percy_cam/F_R_hazcam.png" output_base = "E:/output/unwarping/" - img = io.load_image(file_path, average=False) + img = losa.load_image(file_path, average=False) # Define a function for convenient use. def unwarp_color_image(img, xcenter, ycenter, list_bfact, mode='reflect'): if len(img.shape) != 3: @@ -29,7 +29,7 @@ Useful tips # Suppose that we get xcenter, ycenter, list_bfact (backward mode) to this point img_corrected = unwarp_color_image(img, xcenter, ycenter, list_bfact) - io.save_image(output_base + "/corrected_F_R_hazcam.png", img_corrected) + losa.save_image(output_base + "/corrected_F_R_hazcam.png", img_corrected) 2) Find the coordinates of a point in one space given its corresponding coordinates in another space. Suppose that we get distortion coefficients of @@ -39,11 +39,11 @@ Useful tips .. code-block:: python import numpy as np - import discorpy.losa.loadersaver as io + import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post - img = io.load_image("E:/data/image.jpg", average=True) + img = losa.load_image("E:/data/image.jpg", average=True) # Suppose that we get coefficients of the backward model (xcenter, yxenter, list_bfact). # We need to find the forward transformation using the given backward model. (height, width) = img.shape @@ -91,7 +91,7 @@ Useful tips img_pad = np.pad(img, ((pad_top, pad_bot), (pad_left, pad_right), (0, 0)), mode="constant") img_corrected = unwarp_color_image(img_pad, xcenter + pad_left, ycenter + pad_top, list_bfact, mode='constant') - io.save_image(output_base + "/F_R_hazcam_unwarped_padding.jpg", img_corrected) + losa.save_image(output_base + "/F_R_hazcam_unwarped_padding.jpg", img_corrected) .. image:: figs/tips/img1.jpg :width: 100 % @@ -113,7 +113,7 @@ Useful tips img_tmp = post.unwarp_image_backward(img_tmp, xcenter1, ycenter1, list_bfact1) img_corrected.append(img_tmp) img_corrected = np.moveaxis(np.asarray(img_corrected), 0, 2) - io.save_image(output_base + "/F_R_hazcam_unwarped_zoom.jpg", img_corrected) + losa.save_image(output_base + "/F_R_hazcam_unwarped_zoom.jpg", img_corrected) .. image:: figs/tips/img2.jpg :width: 100 % diff --git a/examples/Perseverance_distortion_correction/Distortion_correction_for_Perseverance_camera.md b/examples/Perseverance_distortion_correction/Distortion_correction_for_Perseverance_camera.md index c44a7ac..1406b97 100644 --- a/examples/Perseverance_distortion_correction/Distortion_correction_for_Perseverance_camera.md +++ b/examples/Perseverance_distortion_correction/Distortion_correction_for_Perseverance_camera.md @@ -16,11 +16,11 @@ and overlay on the original image to check by eyes. ```python import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post # Load image -mat0 = io.load_image("Sol0_1st_color.png") +mat0 = losa.load_image("Sol0_1st_color.png") output_base = "figs/" (height, width) = mat0.shape mat0 = mat0 / np.max(mat0) @@ -43,17 +43,17 @@ pad = width mat_pad = np.pad(line_pattern, pad, mode='edge') mat_cor = post.unwarp_image_backward(mat_pad, xcenter + pad, ycenter + pad, list_ffact) mat_cor = mat_cor[pad:pad + height, pad:pad + width] -io.save_image(output_base + "/overlay.jpg", (mat0 + 0.5*mat_cor)) +losa.save_image(output_base + "/overlay.jpg", (mat0 + 0.5*mat_cor)) ``` From the estimated parameters of the forward model, we can calculate parameters of a backward model which will be used for image correction. ```python import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post # Load image -mat0 = io.load_image("Sol0_1st_color.png") +mat0 = losa.load_image("Sol0_1st_color.png") output_base = "figs/" (height, width) = mat0.shape mat0 = mat0 / np.max(mat0) @@ -92,15 +92,15 @@ list_bfact = np.linalg.lstsq(Amatrix, Bmatrix, rcond=1e-64)[0] # Apply distortion correction corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) -io.save_image(output_base + "/after.png", corrected_mat) -io.save_image(output_base + "/before.png", mat0) -io.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_bfact) +losa.save_image(output_base + "/after.png", corrected_mat) +losa.save_image(output_base + "/before.png", mat0) +losa.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_bfact) ``` Knowing the parameters of the backward model, distortion correction can easily be applied to other images of that camera. ```python import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post from PIL import Image @@ -109,11 +109,11 @@ file_path = "Sol0_1st_color.png" output_base = "figs/" mat = np.asarray(Image.open(file_path), dtype=np.float32) # Import distortion coefficients -(xcenter, ycenter, list_fact) = io.load_metadata_txt("figs/coefficients.txt") +(xcenter, ycenter, list_fact) = losa.load_metadata_txt("figs/coefficients.txt") for i in range(mat.shape[-1]): mat[:, :, i] = post.unwarp_image_backward(mat[:, :, i], xcenter, ycenter, list_fact) -io.save_image(output_base + "/Sol0_1st_color_correction.png", mat) +losa.save_image(output_base + "/Sol0_1st_color_correction.png", mat) ``` ![Overlay Image](figs/Sol0_1st_color_correction.png) diff --git a/examples/Perseverance_distortion_correction/apply_correction_to_images.py b/examples/Perseverance_distortion_correction/apply_correction_to_images.py index 385a8fb..41673b3 100644 --- a/examples/Perseverance_distortion_correction/apply_correction_to_images.py +++ b/examples/Perseverance_distortion_correction/apply_correction_to_images.py @@ -22,7 +22,7 @@ Cameras (Hazcams) on the underside of NASA’s Perseverance Mars rover. """ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post from PIL import Image @@ -31,9 +31,9 @@ output_base = "figs/" mat = np.asarray(Image.open(file_path), dtype=np.float32) # Import distortion coefficients -(xcenter, ycenter, list_fact) = io.load_metadata_txt("figs/coefficients.txt") +(xcenter, ycenter, list_fact) = losa.load_metadata_txt("figs/coefficients.txt") for i in range(mat.shape[-1]): mat[:, :, i] = post.unwarp_image_backward(mat[:, :, i], xcenter, ycenter, list_fact) -io.save_image(output_base + "/Sol0_1st_color_correction.png", mat) \ No newline at end of file +losa.save_image(output_base + "/Sol0_1st_color_correction.png", mat) \ No newline at end of file diff --git a/examples/Perseverance_distortion_correction/backward_mapping.py b/examples/Perseverance_distortion_correction/backward_mapping.py index e0c2101..8c216ec 100644 --- a/examples/Perseverance_distortion_correction/backward_mapping.py +++ b/examples/Perseverance_distortion_correction/backward_mapping.py @@ -23,11 +23,11 @@ NASA’s Perseverance Mars rover. """ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post # Load image -mat0 = io.load_image("Sol0_1st_color.png") +mat0 = losa.load_image("Sol0_1st_color.png") output_base = "figs/" (height, width) = mat0.shape mat0 = mat0 / np.max(mat0) @@ -66,7 +66,7 @@ # Apply distortion correction corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) -io.save_image(output_base + "/after.png", corrected_mat) -io.save_image(output_base + "/before.png", mat0) -io.save_metadata_txt( +losa.save_image(output_base + "/after.png", corrected_mat) +losa.save_image(output_base + "/before.png", mat0) +losa.save_metadata_txt( output_base + "/coefficients.txt", xcenter, ycenter, list_bfact) \ No newline at end of file diff --git a/examples/Perseverance_distortion_correction/forward_model_estimation.py b/examples/Perseverance_distortion_correction/forward_model_estimation.py index 3308976..7f19972 100644 --- a/examples/Perseverance_distortion_correction/forward_model_estimation.py +++ b/examples/Perseverance_distortion_correction/forward_model_estimation.py @@ -26,11 +26,11 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post # Load image -mat0 = io.load_image("Sol0_1st_color.png") +mat0 = losa.load_image("Sol0_1st_color.png") output_base = "figs/" (height, width) = mat0.shape mat0 = mat0 / np.max(mat0) @@ -54,4 +54,4 @@ mat_cor = post.unwarp_image_backward(mat_pad, xcenter + pad, ycenter + pad, list_ffact) mat_cor = mat_cor[pad:pad + height, pad:pad + width] -io.save_image(output_base + "/overlay.jpg", (mat0 + 0.5*mat_cor)) +losa.save_image(output_base + "/overlay.jpg", (mat0 + 0.5*mat_cor)) diff --git a/examples/example_01.py b/examples/example_01.py index 5076bf8..eba2e36 100644 --- a/examples/example_01.py +++ b/examples/example_01.py @@ -23,7 +23,7 @@ import timeit import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -46,7 +46,7 @@ # Load an image, get shape print("Load image: {}".format(file_path)) -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape # Optional step: correct non-uniform background for global thresholding method. @@ -67,7 +67,7 @@ raise ValueError( "Number of objects detected is not enough !!! Parameters of" " the binarization method need to be adjusted!!!") -io.save_image(output_base + "/binarized_image.tif", mat1) +losa.save_image(output_base + "/binarized_image.tif", mat1) # Calculate the median dot size and the median distance of two nearest dots # using the middle part of the image (30%). This is based on an assumption @@ -79,12 +79,12 @@ # Select dots with size in the range of [dot_size - dot_size*ratio; dot_size + # dot_size*ratio] mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.3) -io.save_image(output_base + "/cleaned_1_image.tif", mat1) +losa.save_image(output_base + "/cleaned_1_image.tif", mat1) # Select dots with the ratio between the major axis and the minor axis (of a # fitted ellipse) in the range of (1; 1 + ratio). mat1 = prep.select_dots_based_ratio(mat1, ratio=0.5) -io.save_image(output_base + "/cleaned_2_image.tif", mat1) +losa.save_image(output_base + "/cleaned_2_image.tif", mat1) # Calculate the horizontal slope and the vertical slope of the grid using the # middle part of the image (30%). @@ -102,9 +102,9 @@ num_dot_miss=6, accepted_ratio=0.7) list_ver_lines = prep.group_dots_ver_lines(mat1, ver_slope, dot_dist, ratio=0.3, num_dot_miss=6, accepted_ratio=0.7) -io.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, +losa.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, +losa.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, height, width) # Optional step: Remove residual dots. @@ -114,9 +114,9 @@ list_hor_lines, hor_slope, residual=2.0) list_ver_lines = prep.remove_residual_dots_ver( list_ver_lines, ver_slope, residual=2.0) -io.save_plot_image(output_base + "/horizontal_dots_refined.png", +losa.save_plot_image(output_base + "/horizontal_dots_refined.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_dots_refined.png", +losa.save_plot_image(output_base + "/vertical_dots_refined.png", list_ver_lines, height, width) time_stop = timeit.default_timer() print("Group dots into horizontal lines and vertical lines in {}" @@ -124,10 +124,10 @@ # Optional step: check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_horizontal_dots_before.png", +losa.save_residual_plot(output_base + "/residual_horizontal_dots_before.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_vertical_dots_before.png", +losa.save_residual_plot(output_base + "/residual_vertical_dots_before.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) check2 = post.check_distortion(list_ver_data) @@ -162,12 +162,12 @@ # Apply distortion correction corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image_bw.tif", corrected_mat) -io.save_image(output_base + "/diff_corrected_image_bw.tif", +losa.save_image(output_base + "/corrected_image_bw.tif", corrected_mat) +losa.save_image(output_base + "/diff_corrected_image_bw.tif", np.abs(corrected_mat - mat0)) -io.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, +losa.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, list_fact) -# io.save_metadata_json(output_base + "/coefficients_bw.json", xcenter, ycenter, +# losa.save_metadata_json(output_base + "/coefficients_bw.json", xcenter, ycenter, # list_fact) # Check the correction results @@ -177,10 +177,10 @@ list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_horizontal_dots_after_BW_correction.png", list_hor_data, height, width) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_vertical_dots_after_BW_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) @@ -202,12 +202,12 @@ # Apply distortion correction using nearest interpolation. Note that there's # vacant pixel problem if the distortion is of the barrel type. corrected_mat = post.unwarp_image_forward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image_fw.tif", corrected_mat) -io.save_image(output_base + "/diff_corrected_image_fw.tif", +losa.save_image(output_base + "/corrected_image_fw.tif", corrected_mat) +losa.save_image(output_base + "/diff_corrected_image_fw.tif", np.abs(corrected_mat - mat0)) -io.save_metadata_txt(output_base + "coefficients_fw.txt", xcenter, ycenter, +losa.save_metadata_txt(output_base + "coefficients_fw.txt", xcenter, ycenter, list_fact) -# io.save_metadata_json(output_base + "coefficients_fw.json", xcenter, ycenter, +# losa.save_metadata_json(output_base + "coefficients_fw.json", xcenter, ycenter, # list_fact) # Check the correction results @@ -215,16 +215,16 @@ list_fact) list_uver_lines = post.unwarp_line_forward(list_ver_lines, xcenter, ycenter, list_fact) -io.save_plot_image(output_base + "/horizontal_dots_unwarped.png", +losa.save_plot_image(output_base + "/horizontal_dots_unwarped.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/vertical_dots_unwarped.png", +losa.save_plot_image(output_base + "/vertical_dots_unwarped.png", list_uver_lines, height, width) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_horizontal_dots_after_FW_correction.png", list_hor_data, height, width) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_vertical_dots_after_FW_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) @@ -246,12 +246,12 @@ # Apply distortion correction corrected_mat = post.unwarp_image_backward( mat0, xcenter, ycenter, list_bfact) -io.save_image(output_base + "/corrected_image_bwfw.tif", corrected_mat) -io.save_image(output_base + "/diff_corrected_image_bwfw.tif", +losa.save_image(output_base + "/corrected_image_bwfw.tif", corrected_mat) +losa.save_image(output_base + "/diff_corrected_image_bwfw.tif", np.abs(corrected_mat - mat0)) -io.save_metadata_txt( +losa.save_metadata_txt( output_base + "/coefficients_bwfw.txt", xcenter, ycenter, list_bfact) -# io.save_metadata_json( +# losa.save_metadata_json( # output_base + "/coefficients_bwfw.json", xcenter, ycenter, list_bfact) # Check the correction results list_uhor_lines = post.unwarp_line_backward( @@ -260,10 +260,10 @@ list_ver_lines, xcenter, ycenter, list_bfact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_horizontal_dots_after_BWFW_correction.png", list_hor_data, height, width) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_vertical_dots_after_BWFW_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) diff --git a/examples/example_02.py b/examples/example_02.py index f5ffd3e..b88f57c 100644 --- a/examples/example_02.py +++ b/examples/example_02.py @@ -23,7 +23,7 @@ import timeit import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -72,16 +72,16 @@ def calc_distor_coef(mat, num_coef, perspective=False): # ----------------------------------------------------------------------------- # Input print("Load image") -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) # Calculation of distortion coefficients print("Calculate distortion coefficients of a backward model...") (xcenter, ycenter, list_fact) = calc_distor_coef(mat0, num_coef, perspective=perspective) # Output corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) -io.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, list_fact) time_stop = timeit.default_timer() print("Done!!!\nRunning time is {} second !".format(time_stop - time_start)) diff --git a/examples/example_03.py b/examples/example_03.py index 1939d8b..3faad06 100644 --- a/examples/example_03.py +++ b/examples/example_03.py @@ -23,7 +23,7 @@ import numpy as np import timeit -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -47,7 +47,7 @@ # Load an image print("Load image: {}".format(file_path)) -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape # Correct non-uniform background. Use sigma = 5 @@ -57,7 +57,7 @@ # For tiny dots, you may need to set the threshold manually and add a parameter # denoise=False. mat1 = prep.binarization(mat1, ratio=0.5, thres=None) -io.save_image(output_base + "/binarized_image.tif", mat1) +losa.save_image(output_base + "/binarized_image.tif", mat1) # Calculate the median dot-size and the median distance of two nearest dots. (dot_size, dot_dist) = prep.calc_size_distance(mat1, ratio=0.3) @@ -67,14 +67,14 @@ # Select dots with a certain range of size. # Ratio is changed to 0.9 as the size of binary dots varies significantly. mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.9) -io.save_image(output_base + "/cleaned_1_image.tif", mat1) +losa.save_image(output_base + "/cleaned_1_image.tif", mat1) # Select dots with a certain ratio between the major and the minor axis # Strong distortion at the edges of the image makes round-shape dots become # elliptical dots, so the acceptable variation is changed to be larger, # ratio=1.0. mat1 = prep.select_dots_based_ratio(mat1, ratio=1.0) -io.save_image(output_base + "/cleaned_2_image.tif", mat1) +losa.save_image(output_base + "/cleaned_2_image.tif", mat1) # Calculate the horizontal slope and the vertical slope of the grid. hor_slope = prep.calc_hor_slope(mat1, ratio=0.3) @@ -92,19 +92,19 @@ residual=2.0) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope, residual=2.0) -io.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, +losa.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, +losa.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, height, width) # Following steps are straightforward: # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_hor_before_correction.png", +losa.save_residual_plot(output_base + "/residual_hor_before_correction.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_ver_before_correction.png", +losa.save_residual_plot(output_base + "/residual_ver_before_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) check2 = post.check_distortion(list_ver_data) @@ -139,10 +139,10 @@ # Apply distortion correction corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/diff_corrected_image.tif", +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/diff_corrected_image.tif", np.abs(corrected_mat - mat0)) -io.save_metadata_txt(output_base + "/distortion_coefficients_bw.txt", xcenter, +losa.save_metadata_txt(output_base + "/distortion_coefficients_bw.txt", xcenter, ycenter, list_bfact) # Check the correction results. @@ -150,15 +150,15 @@ list_ffact) list_uver_lines = post.unwarp_line_forward(list_ver_lines, xcenter, ycenter, list_ffact) -io.save_plot_image(output_base + "/horizontal_dots_unwarped.png", +losa.save_plot_image(output_base + "/horizontal_dots_unwarped.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/vertical_dots_unwarped.png", +losa.save_plot_image(output_base + "/vertical_dots_unwarped.png", list_uver_lines, height, width) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/residual_hor_after_correction.png", +losa.save_residual_plot(output_base + "/residual_hor_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/residual_ver_after_correction.png", +losa.save_residual_plot(output_base + "/residual_ver_after_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) check2 = post.check_distortion(list_ver_data) diff --git a/examples/example_04.py b/examples/example_04.py index 6d959d3..9a75a8f 100644 --- a/examples/example_04.py +++ b/examples/example_04.py @@ -23,7 +23,7 @@ import timeit import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -73,13 +73,13 @@ def calc_distor_coef(mat, num_coef, perspective=False): #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Input -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape # Calculation of distortion coefficients (xcenter, ycenter, list_fact) = calc_distor_coef(mat0, num_coef, perspective=perspective) -io.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, +losa.save_metadata_txt(output_base + "/coefficients_bw.txt", xcenter, ycenter, list_fact) # Generate a 3D dataset for demonstration. @@ -97,8 +97,8 @@ def calc_distor_coef(mat, num_coef, perspective=False): for i in range(start_index, stop_index): name = "0000" + str(i) output_name = output_base + "/before/slice_" + name[-5:] + ".tif" - io.save_image(output_name, mat3D[:, i, :]) + losa.save_image(output_name, mat3D[:, i, :]) output_name = output_base + "/after/unwarped_slice_" + name[-5:] + ".tif" - io.save_image(output_name, corrected_slices[:, i - start_index, :]) + losa.save_image(output_name, corrected_slices[:, i - start_index, :]) time_stop = timeit.default_timer() print("Running time is {} second!".format(time_stop - time_start)) diff --git a/examples/example_05.py b/examples/example_05.py index 362f12b..ad50d98 100644 --- a/examples/example_05.py +++ b/examples/example_05.py @@ -23,7 +23,7 @@ import timeit import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.post.postprocessing as post @@ -47,11 +47,11 @@ #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Import distortion coefficients -(xcenter, ycenter, list_fact) = io.load_metadata_txt(file_path) +(xcenter, ycenter, list_fact) = losa.load_metadata_txt(file_path) # Generate a 3D dataset for demonstration. # Replace this step with a real 3D data in your codes. -mat0 = io.load_image("../data/dot_pattern_05.jpg") +mat0 = losa.load_image("../data/dot_pattern_05.jpg") (height, width) = mat0.shape mat3D = np.zeros((600, height, width), dtype=np.float32) mat3D[:] = mat0 @@ -69,7 +69,7 @@ output_name = output_base + "/xcenter_"\ + "{:5.2f}".format(xcenter + x_search) + "_ycenter_"\ + "{:5.2f}".format(ycenter + y_search) + ".tif" - io.save_image(output_name, corrected_slice) + losa.save_image(output_name, corrected_slice) time_stop = timeit.default_timer() print("Running time is {} second!".format(time_stop - time_start)) diff --git a/examples/line_pattern/example_01.py b/examples/line_pattern/example_01.py index c5fc57b..2aa218f 100644 --- a/examples/line_pattern/example_01.py +++ b/examples/line_pattern/example_01.py @@ -6,7 +6,7 @@ """ import timeit -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -23,7 +23,7 @@ # Load a line-pattern image. print("1-> Load image: {}".format(file_path)) -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape # Optional: Normalizing background @@ -38,8 +38,8 @@ print("3-> Extract reference-points !!!!") list_points_hor_lines = lprep.get_cross_points_hor_lines(mat0, slope_ver, dist_ver, ratio=1.0, sensitive=0.1) list_points_ver_lines = lprep.get_cross_points_ver_lines(mat0, slope_hor, dist_hor, ratio=1.0, sensitive=0.1) -io.save_plot_points(output_base + "/hor_points.png", list_points_hor_lines, height, width) -io.save_plot_points(output_base + "/ver_points.png", list_points_ver_lines, height, width) +losa.save_plot_points(output_base + "/hor_points.png", list_points_hor_lines, height, width) +losa.save_plot_points(output_base + "/ver_points.png", list_points_ver_lines, height, width) print("4-> Group points into lines !!!!") @@ -54,15 +54,15 @@ # Optional: correct perspective effect. list_hor_lines, list_ver_lines = proc.regenerate_grid_points_parabola( list_hor_lines, list_ver_lines, perspective=True) -io.save_plot_image(output_base + "/hor_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/ver_lines.png", list_ver_lines, height, width) +losa.save_plot_image(output_base + "/hor_lines.png", list_hor_lines, height, width) +losa.save_plot_image(output_base + "/ver_lines.png", list_ver_lines, height, width) # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_horizontal_points_before.png", +losa.save_residual_plot(output_base + "/residual_horizontal_points_before.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_vertical_points_before.png", +losa.save_residual_plot(output_base + "/residual_vertical_points_before.png", list_ver_data, height, width) print("6-> Calculate the centre of distortion !!!!") @@ -75,9 +75,9 @@ # Output print("8-> Apply correction to image !!!!") corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) -io.save_image(output_base + "/difference.tif", mat0 - corrected_mat) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) +losa.save_image(output_base + "/difference.tif", mat0 - corrected_mat) # Check the correction results list_uhor_lines = post.unwarp_line_backward( @@ -86,10 +86,10 @@ list_ver_lines, xcenter, ycenter, list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_horizontal_points_after.png", list_hor_data, height, width) -io.save_residual_plot( +losa.save_residual_plot( output_base + "/residual_vertical_points_after.png", list_ver_data, height, width) print("!!! Done !!!!") diff --git a/examples/readthedocs_demo/demo_01.py b/examples/readthedocs_demo/demo_01.py index 38fff32..73e4c16 100644 --- a/examples/readthedocs_demo/demo_01.py +++ b/examples/readthedocs_demo/demo_01.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -8,7 +8,7 @@ file_path = "../../data/dot_pattern_01.jpg" output_base = "E:/output_demo_01/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Segment dots mat1 = prep.binarization(mat0) @@ -18,7 +18,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -33,17 +33,17 @@ # Optional: remove vertical outliers list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) # Check residual of dots on lines list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Optional: correct perspective effect. Only available from Discorpy 1.4 @@ -56,7 +56,7 @@ list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) # Save the results for later use. -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -67,21 +67,21 @@ list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) # Calculate the residual of the unwarpped points. list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. Convert to lower-bit if need to. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/examples/readthedocs_demo/demo_02.py b/examples/readthedocs_demo/demo_02.py index cb4932e..ca8e209 100644 --- a/examples/readthedocs_demo/demo_02.py +++ b/examples/readthedocs_demo/demo_02.py @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -9,7 +9,7 @@ file_path = "../../data/dot_pattern_02.jpg" output_base = "E:/output_demo_02/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Segment dots mat1 = prep.binarization(mat0) @@ -19,7 +19,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) ver_slope = prep.calc_ver_slope(mat1) @@ -32,15 +32,15 @@ list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, hor_slope) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) print("Horizontal slope: {0}. Vertical slope: {1}".format(hor_slope, ver_slope)) @@ -83,15 +83,15 @@ list_hor_lines, list_ver_lines = proc.regenerate_grid_points_parabola( list_hor_lines, list_ver_lines, perspective=True) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines_regenerated.png", +losa.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines_regenerated.png", +losa.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines, height, width) (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -104,16 +104,16 @@ list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Load coefficients from previous calculation if need to -# (xcenter, ycenter, list_fact) = io.load_metadata_txt( +# (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit numpy array. # Convert to lower-bit data before saving to tiff if need to. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/examples/readthedocs_demo/demo_03.py b/examples/readthedocs_demo/demo_03.py index 0ae6bc9..837c375 100644 --- a/examples/readthedocs_demo/demo_03.py +++ b/examples/readthedocs_demo/demo_03.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -8,17 +8,17 @@ file_path = "../../data/dot_pattern_04.jpg" output_base = "E:/output_demo_03/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Correct non-uniform background. mat1 = prep.normalization_fft(mat0, sigma=20) -io.save_image(output_base + "/image_normed.tif", mat1) +losa.save_image(output_base + "/image_normed.tif", mat1) # Segment dots. threshold = prep.calculate_threshold(mat1, bgr="bright", snr=3.0) mat1 = prep.binarization(mat1, ratio=0.5, thres=threshold) -io.save_image(output_base + "/image_binarized.tif", mat1) +losa.save_image(output_base + "/image_binarized.tif", mat1) # Calculate the median dot size and distance between them. (dot_size, dot_dist) = prep.calc_size_distance(mat1) @@ -26,7 +26,7 @@ mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.8) # Remove non-elliptical objects mat1 = prep.select_dots_based_ratio(mat1, ratio=0.8) -io.save_image(output_base + "/image_cleaned.tif", mat1) +losa.save_image(output_base + "/image_cleaned.tif", mat1) # Calculate the slopes of horizontal lines and vertical lines. hor_slope = prep.calc_hor_slope(mat1) @@ -45,15 +45,15 @@ residual=2.0) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Regenerate grid points after correcting the perspective effect. @@ -64,7 +64,7 @@ (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -79,17 +79,17 @@ list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. Note that the output is 32-bit-tif. -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/difference.tif", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/difference.tif", corrected_mat - mat0) diff --git a/examples/readthedocs_demo/demo_04.py b/examples/readthedocs_demo/demo_04.py index a4e339c..7a9d806 100644 --- a/examples/readthedocs_demo/demo_04.py +++ b/examples/readthedocs_demo/demo_04.py @@ -1,4 +1,4 @@ -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -11,7 +11,7 @@ num_coef = 5 # Number of polynomial coefficients print("1-> Load image: {}".format(file_path)) -mat0 = io.load_image(file_path) +mat0 = losa.load_image(file_path) (height, width) = mat0.shape print("2-> Calculate slope and distance between lines!!!") @@ -23,8 +23,8 @@ print("3-> Extract reference-points !!!!") list_points_hor_lines = lprep.get_cross_points_hor_lines(mat0, slope_ver, dist_ver, ratio=0.5, sensitive=0.1) list_points_ver_lines = lprep.get_cross_points_ver_lines(mat0, slope_hor, dist_hor, ratio=0.5, sensitive=0.1) -io.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) -io.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) +losa.save_plot_points(output_base + "/extracted_hor_points.png", list_points_hor_lines, height, width) +losa.save_plot_points(output_base + "/extracted_ver_points.png", list_points_ver_lines, height, width) print("4-> Group points into lines !!!!") @@ -33,8 +33,8 @@ # Optional: remove residual dots list_hor_lines = prep.remove_residual_dots_hor(list_hor_lines, slope_hor, 2.0) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) -io.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) +losa.save_plot_image(output_base + "/grouped_hor_lines.png", list_hor_lines, height, width) +losa.save_plot_image(output_base + "/grouped_ver_lines.png", list_ver_lines, height, width) print("5-> Correct perspective effect !!!!") @@ -44,10 +44,10 @@ # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_horizontal_points_before.png", +losa.save_residual_plot(output_base + "/residual_horizontal_points_before.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_vertical_points_before.png", +losa.save_residual_plot(output_base + "/residual_vertical_points_before.png", list_ver_data, height, width) print("6-> Calculate the centre of distortion !!!!") @@ -63,14 +63,14 @@ list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_fact) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/residual_horizontal_points_after.png", +losa.save_residual_plot(output_base + "/residual_horizontal_points_after.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/residual_vertical_points_after.png", +losa.save_residual_plot(output_base + "/residual_vertical_points_after.png", list_ver_data, height, width) # Output print("8-> Apply correction to image !!!!") corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) -io.save_image(output_base + "/difference.tif", mat0 - corrected_mat) +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_metadata_txt(output_base + "/coefficients.txt", xcenter, ycenter, list_fact) +losa.save_image(output_base + "/difference.tif", mat0 - corrected_mat) print("!!! Done !!!!") diff --git a/examples/readthedocs_demo/demo_05.py b/examples/readthedocs_demo/demo_05.py index 34a94da..bb729ec 100644 --- a/examples/readthedocs_demo/demo_05.py +++ b/examples/readthedocs_demo/demo_05.py @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -10,7 +10,7 @@ file_path = "../../data/dot_pattern_06.jpg" output_base = "E:/output_demo_05/" num_coef = 4 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Normalize background @@ -18,7 +18,7 @@ # Segment dots threshold = prep.calculate_threshold(mat1, bgr="bright", snr=1.5) mat1 = prep.binarization(mat1, thres=threshold) -io.save_image(output_base + "/segmented_dots.jpg", mat1) +losa.save_image(output_base + "/segmented_dots.jpg", mat1) # Calculate the median dot size and distance between them. (dot_size, dot_dist) = prep.calc_size_distance(mat1) @@ -36,13 +36,13 @@ accepted_ratio=0.6) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines0, height, width) +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines0, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines0, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines0, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Optional: for checking perspective distortion @@ -83,16 +83,16 @@ list_hor_lines0, list_ver_lines0, perspective=True) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines_regenerated.png", +losa.save_plot_image(output_base + "/horizontal_lines_regenerated.png", list_hor_lines1, height, width) -io.save_plot_image(output_base + "/vertical_lines_regenerated.png", +losa.save_plot_image(output_base + "/vertical_lines_regenerated.png", list_ver_lines1, height, width) # Calculate parameters of the radial correction model (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines1, list_ver_lines1) list_fact = proc.calc_coef_backward(list_hor_lines1, list_ver_lines1, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -120,14 +120,14 @@ # Check the residual of unwarped lines: list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Unwarp the image mat_rad_corr = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results -io.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) -io.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) +losa.save_image(output_base + "/image_radial_corrected.jpg", mat_rad_corr) +losa.save_image(output_base + "/radial_difference.jpg", mat_rad_corr - mat0) # ------------------------------------- # For perspective distortion correction @@ -147,5 +147,5 @@ image_pers_corr = post.correct_perspective_image(mat_rad_corr, pers_coef) # Save results np.savetxt(output_base + "/perspective_coefficients.txt", np.transpose([pers_coef])) -io.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) -io.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) +losa.save_image(output_base + "/image_radial_perspective_corrected.jpg", image_pers_corr) +losa.save_image(output_base + "/perspective_difference.jpg", image_pers_corr - mat_rad_corr) diff --git a/examples/readthedocs_demo/demo_06.py b/examples/readthedocs_demo/demo_06.py index 3111745..60ba7ca 100644 --- a/examples/readthedocs_demo/demo_06.py +++ b/examples/readthedocs_demo/demo_06.py @@ -1,5 +1,5 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.prep.linepattern as lprep import discorpy.proc.processing as proc @@ -9,12 +9,12 @@ file_path = "../../data/laptop_camera/chessboard.jpg" output_base = "E:/output_demo_06/" num_coef = 5 # Number of polynomial coefficients -mat0 = io.load_image(file_path) # Load image +mat0 = losa.load_image(file_path) # Load image (height, width) = mat0.shape # Convert the chessboard image to a line-pattern image mat1 = lprep.convert_chessboard_to_linepattern(mat0) -io.save_image(output_base + "/line_pattern_converted.jpg", mat1) +losa.save_image(output_base + "/line_pattern_converted.jpg", mat1) # Calculate slope and distance between lines slope_hor, dist_hor = lprep.calc_slope_distance_hor_lines(mat1, radius=15, sensitive=0.5) @@ -35,9 +35,9 @@ subpixel=True) if len(list_points_hor_lines) == 0 or len(list_points_ver_lines) == 0: raise ValueError("No reference-points detected !!! Please adjust parameters !!!") -io.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, +losa.save_plot_points(output_base + "/ref_points_horizontal.png", list_points_hor_lines, height, width, color="red") -io.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, +losa.save_plot_points(output_base + "/ref_points_vertical.png", list_points_ver_lines, height, width, color="blue") # Group points into lines @@ -50,13 +50,13 @@ list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, slope_ver, 2.0) # Save output for checking -io.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) +losa.save_plot_image(output_base + "/horizontal_lines.png", list_hor_lines, height, width) +losa.save_plot_image(output_base + "/vertical_lines.png", list_ver_lines, height, width) list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/hor_residual_before_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_before_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_before_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_before_correction.png", list_ver_data, height, width) # Regenerate grid points after correcting the perspective effect. @@ -67,7 +67,7 @@ (xcenter, ycenter) = proc.find_cod_coarse(list_hor_lines, list_ver_lines) list_fact = proc.calc_coef_backward(list_hor_lines, list_ver_lines, xcenter, ycenter, num_coef) -io.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", +losa.save_metadata_txt(output_base + "/coefficients_radial_distortion.txt", xcenter, ycenter, list_fact) print("X-center: {0}. Y-center: {1}".format(xcenter, ycenter)) print("Coefficients: {0}".format(list_fact)) @@ -82,42 +82,42 @@ list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) # Save the results for checking -io.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", +losa.save_plot_image(output_base + "/unwarpped_horizontal_lines.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/unwarpped_vertical_lines.png", +losa.save_plot_image(output_base + "/unwarpped_vertical_lines.png", list_uver_lines, height, width) -io.save_residual_plot(output_base + "/hor_residual_after_correction.png", +losa.save_residual_plot(output_base + "/hor_residual_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/ver_residual_after_correction.png", +losa.save_residual_plot(output_base + "/ver_residual_after_correction.png", list_ver_data, height, width) # Correct the image corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_fact) # Save results. -io.save_image(output_base + "/corrected_image.jpg", corrected_mat) -io.save_image(output_base + "/difference.jpg", corrected_mat - mat0) +losa.save_image(output_base + "/corrected_image.jpg", corrected_mat) +losa.save_image(output_base + "/difference.jpg", corrected_mat - mat0) # ---------------------------------------- # Load original color image for correction # ------------------------------------------ # Load coefficients from previous calculation if need to -# (xcenter, ycenter, list_fact) = io.load_metadata_txt( +# (xcenter, ycenter, list_fact) = losa.load_metadata_txt( # output_base + "/coefficients_radial_distortion.txt") -img = io.load_image(file_path, average=False) +img = losa.load_image(file_path, average=False) img_corrected = np.copy(img) # Unwarped each color channel of the image for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_fact) # Save the unwarped image. -io.save_image(output_base + "/corrected_image_color.jpg", img_corrected) +losa.save_image(output_base + "/corrected_image_color.jpg", img_corrected) # Load a test image and correct it. -img = io.load_image("../../data/laptop_camera/test_image.jpg", average=False) +img = losa.load_image("../../data/laptop_camera/test_image.jpg", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_fact) -io.save_image(output_base + "/test_image_corrected.jpg", img_corrected) +losa.save_image(output_base + "/test_image_corrected.jpg", img_corrected) diff --git a/examples/readthedocs_demo/demo_07.py b/examples/readthedocs_demo/demo_07.py index 35332dd..b3bc34d 100644 --- a/examples/readthedocs_demo/demo_07.py +++ b/examples/readthedocs_demo/demo_07.py @@ -1,12 +1,12 @@ import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post # Load image file_path = "../../data/demo/perspective_demo.jpg" output_base = "E:/output_demo_07/" -mat = io.load_image(file_path, average=False) +mat = losa.load_image(file_path, average=False) # Provide the coordinates of 4-points. They can be in xy-order or yx-order, this info # needs to be consistent with other functions. In this example, it's in the xy-order. @@ -23,7 +23,7 @@ mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef) -io.save_image(output_base + "/corrected_image.jpg", mat_cor) +losa.save_image(output_base + "/corrected_image.jpg", mat_cor) # The region of interest may be out of the field of view or rotated. # We can rotate the output image, offset, and scale it by changing the target @@ -58,5 +58,5 @@ mat_cor = np.zeros_like(mat) for i in range(mat_cor.shape[-1]): mat_cor[:, :, i] = post.correct_perspective_image(mat[:, :, i], list_coef2, order=3) -io.save_image(output_base + "/adjusted_image.jpg", mat_cor) +losa.save_image(output_base + "/adjusted_image.jpg", mat_cor) print("!!! Done !!!") \ No newline at end of file diff --git a/examples/readthedocs_demo/demo_08.py b/examples/readthedocs_demo/demo_08.py index 6c91688..bf62fdf 100644 --- a/examples/readthedocs_demo/demo_08.py +++ b/examples/readthedocs_demo/demo_08.py @@ -1,6 +1,6 @@ import os import numpy as np -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.proc.processing as proc import discorpy.post.postprocessing as post import scipy.ndimage as ndi @@ -8,7 +8,7 @@ file_path = "../../data/percy_cam/F_R_hazcam.png" output_base = "E:/output_demo_08/" -mat0 = io.load_image(file_path, average=True) +mat0 = losa.load_image(file_path, average=True) mat0 = mat0 / np.max(mat0) (height, width) = mat0.shape @@ -46,7 +46,7 @@ def scan_coef(idx, start, stop, step, list_coef, list_power, output_base0, mat0, ycenter + pad, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "coef_{0}_val_{1:4.2f}".format(idx, list_coef_est[idx]) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -54,7 +54,7 @@ def scan_coef(idx, start, stop, step, list_coef, list_power, output_base0, mat0, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, output_base0, mat0, mat_pad, pad, axis="x", ntime=1, backward=True): @@ -72,7 +72,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "xcenter_{0:7.2f}".format(xcenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -80,7 +80,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter+num, ycenter, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) else: for num in np.arange(start, stop + step, step): line_img_warped = post.unwarp_image_backward(mat_pad, xcenter + pad, @@ -88,7 +88,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, list_ffact) line_img_warped = line_img_warped[pad:pad + height, pad:pad + width] name = "ycenter_{0:7.2f}".format(ycenter + num) - io.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) + losa.save_image(output_base + "/forward/img_" + name + ".jpg", mat0 + 0.5 * line_img_warped) if backward is True: # Transform to the backward model for correction hlines = np.int16(np.linspace(0, height, 40)) @@ -96,7 +96,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points = [[i - ycenter, j - xcenter] for i in hlines for j in vlines] list_bfact = proc.transform_coef_backward_and_forward(list_ffact, ref_points=ref_points) img_unwarped = post.unwarp_image_backward(mat0, xcenter, ycenter+num, list_bfact) - io.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) + losa.save_image(output_base + "/backward/img_" + name + ".jpg", img_unwarped) ## Scan the 4th coefficient scan_coef(4, 0, 30, 1, list_coef, list_power, output_base, mat0, mat_pad, pad) @@ -140,7 +140,7 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ref_points=ref_points) # Load the color image -img = io.load_image(file_path, average=False) +img = losa.load_image(file_path, average=False) img_corrected = np.copy(img) # Unwarped each color channel of the image @@ -149,20 +149,20 @@ def scan_center(xcenter, ycenter, start, stop, step, list_coef, list_power, ycenter, list_bfact) # Save the unwarped image. -io.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) +losa.save_image(output_base + "/F_R_hazcam_unwarped.png", img_corrected) # Correct other images from the same camera -img = io.load_image("../../data/percy_cam/rock_core1.png", average=False) +img = losa.load_image("../../data/percy_cam/rock_core1.png", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) -io.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) +losa.save_image(output_base + "/rock_core1_unwarped.png", img_corrected) -img = io.load_image("../../data/percy_cam/rock_core2.png", average=False) +img = losa.load_image("../../data/percy_cam/rock_core2.png", average=False) img_corrected = np.copy(img) for i in range(img.shape[-1]): img_corrected[:, :, i] = post.unwarp_image_backward(img[:, :, i], xcenter, ycenter, list_bfact) -io.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) +losa.save_image(output_base + "/rock_core2_unwarped.png", img_corrected) diff --git a/examples/unwarp.py b/examples/unwarp.py index 1cb2a71..62bcf4a 100644 --- a/examples/unwarp.py +++ b/examples/unwarp.py @@ -30,7 +30,7 @@ warnings.filterwarnings("ignore") from scipy import ndimage as ndi -import discorpy.losa.loadersaver as io +import discorpy.losa.loadersaver as losa import discorpy.prep.preprocessing as prep import discorpy.proc.processing as proc import discorpy.post.postprocessing as post @@ -74,24 +74,24 @@ print("1 ---> Load file: {}".format(file_path)) _, file_ext = os.path.splitext(file_path) if (file_ext == ".hdf") or (file_ext == ".nxs"): - mat0 = io.load_hdf_file(file_path, key_path=key_path_hdf, index=None, + mat0 = losa.load_hdf_file(file_path, key_path=key_path_hdf, index=None, axis=0) if len(mat0.shape) == 3: mat0 = np.mean(mat0, axis=0) else: - mat0 = io.load_image(file_path) + mat0 = losa.load_image(file_path) (height, width) = mat0.shape # Load flat-field if (flat_path != "none") and (flat_path != "norm"): _, file_ext = os.path.splitext(flat_path) if (file_ext == ".hdf") or (file_ext == ".nxs"): - flat = io.load_hdf_file(flat_path, key_path=key_path_hdf, index=None, + flat = losa.load_hdf_file(flat_path, key_path=key_path_hdf, index=None, axis=0) if len(flat.shape) == 3: flat = np.mean(flat, axis=0) else: - flat = io.load_image(flat_path) + flat = losa.load_image(flat_path) (height1, width1) = flat.shape if (height != height1) or (width != width): raise ValueError( @@ -107,14 +107,14 @@ # Binarize print("2 ---> Binarize and clean the dot-pattern image") mat1 = prep.binarization(mat1, ratio=0.3, thres=None) -io.save_image(output_base + "/binarized_image.tif", mat1) +losa.save_image(output_base + "/binarized_image.tif", mat1) # Calculate dot size, distance of two nearest dots (dot_size, dot_dist) = prep.calc_size_distance(mat1, ratio=0.5) # Select dots with a certain size mat1 = prep.select_dots_based_size(mat1, dot_size, ratio=0.5) # Select dots with a certain ratio between major and minor axis mat1 = prep.select_dots_based_ratio(mat1, ratio=0.3) -io.save_image(output_base + "/cleaned_image.tif", mat1) +losa.save_image(output_base + "/cleaned_image.tif", mat1) # Calculate the horizontal slope and the vertical slope of the grid print("3 ---> Calculate the slopes of lines of dots\n") @@ -136,18 +136,18 @@ residual=2.0) list_ver_lines = prep.remove_residual_dots_ver(list_ver_lines, ver_slope, residual=2.0) -io.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, +losa.save_plot_image(output_base + "/group_horizontal_dots.png", list_hor_lines, height, width) -io.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, +losa.save_plot_image(output_base + "/group_vertical_dots.png", list_ver_lines, height, width) print("6 ---> Calculate residuals before distortion correction") # Check if the distortion is significant. list_hor_data = post.calc_residual_hor(list_hor_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_hor_before_correction.png", +losa.save_residual_plot(output_base + "/residual_hor_before_correction.png", list_hor_data, height, width) list_ver_data = post.calc_residual_ver(list_ver_lines, 0.0, 0.0) -io.save_residual_plot(output_base + "/residual_ver_before_correction.png", +losa.save_residual_plot(output_base + "/residual_ver_before_correction.png", list_ver_data, height, width) # check1 = post.check_distortion(list_hor_data) @@ -187,9 +187,9 @@ # Apply distortion correction print("9 ---> Apply distortion correction") corrected_mat = post.unwarp_image_backward(mat0, xcenter, ycenter, list_bfact) -io.save_image(output_base + "/corrected_image.tif", corrected_mat) -io.save_image(output_base + "/original_image.tif", mat0) -io.save_metadata_txt(output_base + "/distortion_coefficients_bw.txt", xcenter, +losa.save_image(output_base + "/corrected_image.tif", corrected_mat) +losa.save_image(output_base + "/original_image.tif", mat0) +losa.save_metadata_txt(output_base + "/distortion_coefficients_bw.txt", xcenter, ycenter, list_bfact) # Check the correction results print("10---> Evaluate the correction results") @@ -197,15 +197,15 @@ list_bfact) list_uver_lines = post.unwarp_line_backward(list_ver_lines, xcenter, ycenter, list_bfact) -io.save_plot_image(output_base + "/horizontal_dots_unwarped.png", +losa.save_plot_image(output_base + "/horizontal_dots_unwarped.png", list_uhor_lines, height, width) -io.save_plot_image(output_base + "/vertical_dots_unwarped.png", +losa.save_plot_image(output_base + "/vertical_dots_unwarped.png", list_uver_lines, height, width) list_hor_data = post.calc_residual_hor(list_uhor_lines, xcenter, ycenter) list_ver_data = post.calc_residual_ver(list_uver_lines, xcenter, ycenter) -io.save_residual_plot(output_base + "/residual_hor_after_correction.png", +losa.save_residual_plot(output_base + "/residual_hor_after_correction.png", list_hor_data, height, width) -io.save_residual_plot(output_base + "/residual_ver_after_correction.png", +losa.save_residual_plot(output_base + "/residual_ver_after_correction.png", list_ver_data, height, width) check1 = post.check_distortion(list_hor_data) check2 = post.check_distortion(list_ver_data) diff --git a/tests/test_linepattern.py b/tests/test_linepattern.py index 62003fe..1eb60b8 100644 --- a/tests/test_linepattern.py +++ b/tests/test_linepattern.py @@ -50,6 +50,31 @@ def setUp(self): self.dist = step self.num_hline, self.num_vline = num_hline, num_vline + def test_select_good_peaks(self): + list_data = np.array([0, 1.5, 5, 1.5, 0, 0, 3, 10, 3, 0]) + peaks = np.asarray([2, 7]) + tol, radius, sigma = 0.1, 3, 0 + result = lipa.select_good_peaks(list_data, peaks, tol=tol, + radius=radius, sigma=sigma) + np.testing.assert_array_equal(result, peaks) + self.assertTrue(len(result) == 2) + tol, radius, sigma = 0.2, 3, 1 + result = lipa.select_good_peaks(list_data, peaks, tol=tol, + radius=radius, sigma=sigma) + np.testing.assert_array_equal(result, peaks) + self.assertTrue(len(result) == 2) + + def test_sliding_window_slope(self): + list_data = np.array([0, 1, 2, 3, 4, 5], dtype=np.float32) + size, norm = 3, False + result = lipa.sliding_window_slope(list_data, size=size, norm=norm) + expected = np.array([0.5, 1.0, 1.0, 1.0, 1.0, 0.5]) + np.testing.assert_almost_equal(result, expected, decimal=1) + size, norm = 3, True + result = lipa.sliding_window_slope(list_data, size=size, norm=norm) + expected = np.array([0.6, 1.2, 1.2, 1.2, 1.2, 0.6]) + np.testing.assert_almost_equal(result, expected, decimal=1) + def test_get_local_extrema_points(self): f_alias = lipa.get_local_extrema_points size = 800