step = 20 #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Import distortion coefficients (xcenter, ycenter, list_fact) = io.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") (height, width) = mat0.shape mat3D = np.zeros((600, height, width), dtype=np.float32) mat3D[:] = mat0 # Generate unwarped slice with the index of 14 # at different xcenter and ycenter. index = 14 for x_search in range(-search_range, search_range + step, step): for y_search in range(-search_range, search_range + step, step): corrected_slice = post.unwarp_slice_backward( mat3D, xcenter + x_search, ycenter + y_search, list_fact, index) # ---------------------------------------------------------- # Do reconstruction here using other packages: tomopy, astra # ---------------------------------------------------------- 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) time_stop = timeit.default_timer() print("Running time is {} second!".format(time_stop - time_start))
(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) return xcenter, ycenter, list_fact time_start = timeit.default_timer() # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # Initial parameters file_path = "../data/dot_pattern_01.jpg" output_base = "E:/correction/" num_coef = 5 # Number of polynomial coefficients # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # Input print("Load image") mat0 = io.load_image(file_path) # Calculation of distortion coefficients print("Calculate distotion coefficients of a backward model...") (xcenter, ycenter, list_fact) = calc_distor_coef(mat0, num_coef) # Output 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", np.abs(corrected_mat - mat0)) io.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))
# Calculate parameters of backward model from the estimated forward model list_hor_lines = [] for i in range(20, height - 20, 50): list_tmp = [] for j in range(20, width - 20, 50): list_tmp.append([i - ycenter, j - xcenter]) list_hor_lines.append(list_tmp) Amatrix = [] Bmatrix = [] list_expo = np.arange(len(list_ffact), dtype=np.int16) for _, line in enumerate(list_hor_lines): for _, point in enumerate(line): xd = np.float64(point[1]) yd = np.float64(point[0]) rd = np.sqrt(xd * xd + yd * yd) ffactor = np.float64(np.sum(list_ffact * np.power(rd, list_expo))) if ffactor != 0.0: Fb = 1 / ffactor ru = ffactor * rd Amatrix.append(np.power(ru, list_expo)) Bmatrix.append(Fb) Amatrix = np.asarray(Amatrix, dtype=np.float64) Bmatrix = np.asarray(Bmatrix, dtype=np.float64) 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)
# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #============================================================================ # Author: Nghia T. Vo # E-mail: [email protected] #============================================================================ """ Example to show how to apply distortion correction to images of the Hazard Cameras (Hazcams) on the underside of NASA’s Perseverance Mars rover. """ import numpy as np import vounwarp.losa.loadersaver as io import vounwarp.post.postprocessing as post from PIL import Image # Load color image 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") 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)
(height1, width1) = flat.shape if (height != height1) or (width != width): raise ValueError( "Shape of the image and the flat-field are not the same") nmean = np.mean(flat) flat[flat == 0.0] = nmean mat1 = mat0 / flat elif flat_path == "norm": mat1 = prep.normalization_fft(mat0, sigma=5, pad=40) else: mat1 = mat0 # 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) # 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) # Calculate the horizontal slope and the vertical slope of the grid print("3 ---> Calculate the slopes of lines of dots\n") hor_slope = prep.calc_hor_slope(mat1, ratio=0.3) ver_slope = prep.calc_ver_slope(mat1, ratio=0.3) print(" Horizontal slope: {0} Vertical slope: {1}\n".format(hor_slope, ver_slope))
# ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # Load an image print("Load image: {}".format(file_path)) mat0 = io.load_image(file_path) (height, width) = mat0.shape # Correct non-uniform background. Use sigma = 5 mat1 = prep.normalization_fft(mat0, sigma=5) # Binarize the image. # 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) # 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) print("Median size of dots: {0}\nMedian distance between two dots: {1}".format( dot_size, dot_dist)) # 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) # 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.
import vounwarp.losa.loadersaver as io import vounwarp.post.postprocessing as post # Load image mat0 = io.load_image("Sol0_1st_color.png") output_base = "figs/" (height, width) = mat0.shape mat0 = mat0 / np.max(mat0) # Create line pattern line_pattern = np.zeros((height, width), dtype=np.float32) for i in range(50, height - 50, 40): line_pattern[i - 1:i + 2] = 1.0 # Estimate parameters by visual inspection. # Coarse estimation xcenter = width / 2.0 + 110.0 ycenter = height / 2.0 - 20.0 list_pow = np.asarray([1.0, 10**(-4), 10**(-7), 10**(-10), 10**(-13)]) # Fine estimation list_coef = np.asarray([1.0, 4.0, 5.0, 17.0, 3.0]) list_ffact = list_pow * list_coef 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))