def detector_drift_adjust_aps_1id(imgstacks, slit_cnr_ref, medfilt2_kernel_size=3, medfilt_kernel_size=3, ncore=None, ): """ Adjust each still image based on the slit corners and generate report fig Parameters ---------- imgstacks : np.ndarray tomopy images stacks (axis_0 is the oemga direction) slit_cnr_ref : np.ndarray reference slit corners from white field images medfilt2_kernel_size : int, optional 2D median filter kernel size for slit conner detection medfilt_kernel_size : int, optional 1D median filter kernel size for slit conner detection ncore : int, optional number of cores used for speed up Returns ------- np.ndarray adjusted imgstacks np.ndarray detected corners on each still image np.ndarray transformation matrices used to adjust each image """ ncore = mproc.mp.cpu_count() - 1 if ncore is None else ncore def quick_diff(x): return np.amax(np.absolute(x)) # -- find all projection corners (slow) # NOTE: # Here we are using an iterative approach to find stable slit corners # from each image # 1. calculate all slit corners with the given kernel size, preferably # a small one for speed. # 2. double the kernel size and calculate again, but this time we are # checking whether the slit corners are stable. # 3. find the ids (n_imgs) for those that are difficult, continue # increasing the kernel size until all slit corners are found, or max # number of iterations. # 4. move on to next step. nlist = range(imgstacks.shape[0]) proj_cnrs = _calc_proj_cnrs(imgstacks, ncore, nlist, 'quadrant+', medfilt2_kernel_size, medfilt_kernel_size, ) cnrs_found = np.array([quick_diff(proj_cnrs[n, :, :] - slit_cnr_ref) < 15 for n in nlist]) kernels = [(medfilt2_kernel_size+2*i, medfilt_kernel_size+2*j) for i in range(15) for j in range(15)] counter = 0 while not cnrs_found.all(): nlist = [idx for idx, cnr_found in enumerate(cnrs_found) if not cnr_found] # NOTE: # Check to see if we run out of candidate kernels: if counter > len(kernels): # we are giving up here... for idx, n_img in enumerate(nlist): proj_cnrs[n_img, :, :] = slit_cnr_ref break else: # test with differnt 2D and 1D kernels ks2d, ks1d = kernels[counter] _cnrs = _calc_proj_cnrs(imgstacks, ncore, nlist, 'quadrant+', ks2d, ks1d) for idx, _cnr in enumerate(_cnrs): n_img = nlist[idx] cnr = proj_cnrs[n_img, :, :] # previous results # NOTE: # The detector corner should not be far away from reference # -> adiff < 15 # The detected corner should be stable # -> rdiff < 0.1 (pixel)s adiff = quick_diff(_cnr - slit_cnr_ref) rdiff = quick_diff(_cnr - cnr) if rdiff < 0.1 and adiff < 15: cnrs_found[n_img] = True else: # update results proj_cnrs[n_img, :, :] = _cnr # update results for next iter # next counter += 1 # -- calculate affine transformation (fast) img_correct_F = np.ones((imgstacks.shape[0], 3, 3)) for n_img in range(imgstacks.shape[0]): img_correct_F[n_img, :, :] = calc_affine_transform( proj_cnrs[n_img, :, :], slit_cnr_ref) # -- apply affine transformation (slow) tmp = [] with cf.ProcessPoolExecutor(ncore) as e: for n_img in range(imgstacks.shape[0]): tmp.append(e.submit(affine_transform, # input image imgstacks[n_img, :, :], # rotation matrix img_correct_F[n_img, 0:2, 0:2], # offset vector offset=img_correct_F[n_img, 0:2, 2], ) ) imgstacks = np.stack([me.result() for me in tmp], axis=0) return imgstacks, proj_cnrs, img_correct_F
def detector_drift_adjust_aps_1id( imgstacks, slit_cnr_ref, medfilt2_kernel_size=3, medfilt_kernel_size=3, ncore=None, ): """ Adjust each still image based on the slit corners and generate report fig Parameters ---------- imgstacks : np.ndarray tomopy images stacks (axis_0 is the oemga direction) slit_cnr_ref : np.ndarray reference slit corners from white field images medfilt2_kernel_size : int, optional 2D median filter kernel size for slit conner detection medfilt_kernel_size : int, optional 1D median filter kernel size for slit conner detection ncore : int, optional number of cores used for speed up Returns ------- np.ndarray adjusted imgstacks np.ndarray detected corners on each still image np.ndarray transformation matrices used to adjust each image """ ncore = mproc.mp.cpu_count() - 1 if ncore is None else ncore def quick_diff(x): return np.amax(np.absolute(x)) # -- find all projection corners (slow) # NOTE: # Here we are using an iterative approach to find stable slit corners # from each image # 1. calculate all slit corners with the given kernel size, preferably # a small one for speed. # 2. double the kernel size and calculate again, but this time we are # checking whether the slit corners are stable. # 3. find the ids (n_imgs) for those that are difficult, continue # increasing the kernel size until all slit corners are found, or max # number of iterations. # 4. move on to next step. nlist = range(imgstacks.shape[0]) proj_cnrs = _calc_proj_cnrs( imgstacks, ncore, nlist, 'quadrant+', medfilt2_kernel_size, medfilt_kernel_size, ) cnrs_found = np.array( [quick_diff(proj_cnrs[n, :, :] - slit_cnr_ref) < 15 for n in nlist]) kernels = [(medfilt2_kernel_size + 2 * i, medfilt_kernel_size + 2 * j) for i in range(15) for j in range(15)] counter = 0 while not cnrs_found.all(): nlist = [ idx for idx, cnr_found in enumerate(cnrs_found) if not cnr_found ] # NOTE: # Check to see if we run out of candidate kernels: if counter > len(kernels): # we are giving up here... for idx, n_img in enumerate(nlist): proj_cnrs[n_img, :, :] = slit_cnr_ref break else: # test with differnt 2D and 1D kernels ks2d, ks1d = kernels[counter] _cnrs = _calc_proj_cnrs(imgstacks, ncore, nlist, 'quadrant+', ks2d, ks1d) for idx, _cnr in enumerate(_cnrs): n_img = nlist[idx] cnr = proj_cnrs[n_img, :, :] # previous results # NOTE: # The detector corner should not be far away from reference # -> adiff < 15 # The detected corner should be stable # -> rdiff < 0.1 (pixel)s adiff = quick_diff(_cnr - slit_cnr_ref) rdiff = quick_diff(_cnr - cnr) if rdiff < 0.1 and adiff < 15: cnrs_found[n_img] = True else: # update results proj_cnrs[n_img, :, :] = _cnr # update results for next iter # next counter += 1 # -- calculate affine transformation (fast) img_correct_F = np.ones((imgstacks.shape[0], 3, 3)) for n_img in range(imgstacks.shape[0]): img_correct_F[n_img, :, :] = calc_affine_transform( proj_cnrs[n_img, :, :], slit_cnr_ref) # -- apply affine transformation (slow) tmp = [] with cf.ProcessPoolExecutor(ncore) as e: for n_img in range(imgstacks.shape[0]): tmp.append( e.submit( affine_transform, # input image imgstacks[n_img, :, :], # rotation matrix img_correct_F[n_img, 0:2, 0:2], # offset vector offset=img_correct_F[n_img, 0:2, 2], )) imgstacks = np.stack([me.result() for me in tmp], axis=0) return imgstacks, proj_cnrs, img_correct_F