def export_vp_stack(self, type='png', downscale=None): # print status self.sta.status_msg('Write viewpoint image stack', self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) # downscale image downscale = True if downscale is None else downscale views_stacked_img = misc.img_resize(self.views_stacked_img.copy(), 1 / self._M) \ if downscale else self.views_stacked_img.copy() # normalization p_lo = np.percentile(misc.rgb2gray(self.central_view), 0.05) p_hi = np.percentile(misc.rgb2gray(self.central_view), 99.995) views_stacked_img = misc.Normalizer(views_stacked_img, min=p_lo, max=p_hi).uint8_norm() # export all viewpoints in single image views_stacked_path = os.path.join( self.cfg.exp_path, 'views_stacked_img_' + str(self._M) + 'px') misc.save_img_file(views_stacked_img, file_path=views_stacked_path, file_type=type) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) return True
def crop_imgs(folder, coords_lists): img_tiles, files = list(), list() exts = ('tif', 'tiff', 'png') misc.mkdir_p(os.path.join(folder, 'auto-crop')) files = [ f for f in os.listdir(folder) if f.endswith(exts) and not f.startswith('.') ] files.sort() for i, file in enumerate(files): coords_nested = coords_lists[i] for j, coords in enumerate(coords_nested): if coords[0] != 0 and coords[1] != 0: cy, cx, h, w = coords img = misc.load_img_file(os.path.join(folder, file)) tile = img[cy - h // 2:cy + h // 2, cx - w // 2:cx + w // 2, ...] img_tiles.append(tile) fn, ext = os.path.splitext(file) misc.save_img_file(tile, os.path.join(folder, 'auto-crop', fn + '_crop' + str(j)), 'png', tag=True) return img_tiles, files
def export_thumbnail(self, type='tiff'): # export central viewpoint as thumbnail image fp = os.path.join(self.cfg.exp_path, 'thumbnail') misc.save_img_file(self.central_view, file_path=fp, file_type=type) return True
def export_viewpoints(self, type='tiff'): # print status self.sta.status_msg('Write viewpoint images', self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) ptc_leng = self.cfg.params[self.cfg.ptc_leng] # create folder folderpath = os.path.join(self.cfg.exp_path, 'viewpoints_'+str(ptc_leng)+'px') misc.mkdir_p(folderpath) # normalize image array to 16-bit unsigned integer vp_img_arr = Normalizer(self.vp_img_arr).uint16_norm() # export viewpoint images as image files for j in range(ptc_leng): for i in range(ptc_leng): misc.save_img_file(vp_img_arr[j, i], os.path.join(folderpath, str(j) + '_' + str(i)), file_type=type) # print status percentage = (((j*self._M+i+1)/self._M**2)*100) self.sta.progress(percentage, self.cfg.params[self.cfg.opt_prnt]) return True
def desaturate_clipped(img_arr, gains=None): b, r, g1, g2 = gains if gains is not None else [1., 1., 1., 1.] awb_list = [r, g1, b] comp_arr = np.zeros(img_arr.shape, dtype=img_arr.dtype) mask = np.zeros(img_arr.shape[:2]) alpha = np.amin(img_arr / np.amax(img_arr, axis=2)[..., np.newaxis], axis=2) thresh = .99 for i in range(img_arr.shape[2]): comp_arr[..., i] = (1 - alpha) * (img_arr[..., i]) + alpha * ( img_arr[..., i] / awb_list[i]) # determine indices of other two channels ch1, ch2 = [u for u, v in enumerate(awb_list) if v != awb_list[i]] # only consider pixels in mask which have sufficient intensity distance mask[(img_arr[..., i] > img_arr[..., i].max() * thresh) & (img_arr[..., ch1] > img_arr[..., i].max() * thresh) & (img_arr[..., ch2] > img_arr[..., i].max() * thresh)] = 1 import os misc.save_img_file(mask, os.getcwd() + 'mask.png') img_arr[mask > 0] = comp_arr[mask > 0] return img_arr
def export_refo_stack(self, type=None): refo_stack = Normalizer(np.asarray(self._refo_stack)).uint16_norm() # create folder string = '' if self.cfg.params[self.cfg.opt_refo] == 2 or self.cfg.params[ self.cfg.opt_refi]: string = 'subpixel_' elif self.cfg.params[self.cfg.opt_refo] == 1 or self.cfg.params[ self.cfg.opt_view]: string = '' folder_path = os.path.join(self.cfg.exp_path, 'refo_' + string + str(self._M) + 'px') misc.mkdir_p(folder_path) for i, refo_img in enumerate(refo_stack): # get depth plane number for filename a = range(*self.cfg.params[self.cfg.ran_refo])[i] # account for sub-pixel precise depth value a = round(float(a) / self._M, 2) if self.cfg.params[self.cfg.opt_refi] else a # write image file misc.save_img_file(refo_img, os.path.join(folder_path, str(a)), file_type=type) return True
def export_refo_stack(refo_stack, cfg, type='tiff'): refo_stack = misc.uint16_norm(refo_stack) patch_len = cfg.params[cfg.ptc_leng] # create folder string = '' if cfg.params[cfg.opt_refo] == 2 or cfg.params[cfg.opt_refi]: string = 'subpixel_' elif cfg.params[cfg.opt_refo] == 1 or cfg.params[cfg.opt_view]: string = '' folder_path = os.path.join(cfg.params[cfg.lfp_path].split('.')[0], 'refo_' + string + str(patch_len) + 'px') misc.mkdir_p(folder_path) for i, refo_img in enumerate(refo_stack): # get depth plane number for filename a = range(*cfg.params[cfg.ran_refo])[i] # account for sub-pixel precise depth value a = round(float(a)/patch_len, 2) if cfg.params[cfg.opt_refi] else a # write image file misc.save_img_file(refo_img, os.path.join(folder_path, str(a)), type=type) return True
def export_thumbnail(vp_img_arr, cfg, type='tiff'): # export central viewpoint as thumbnail image misc.save_img_file(vp_img_arr[cfg.params[cfg.ptc_leng]//2+1, cfg.params[cfg.ptc_leng]//2+1], os.path.join(cfg.params[cfg.lfp_path].split('.')[0], 'thumbnail'), type=type) return True
def scheimpflug_from_stack(self): a_start, a_stop = (0, len(self.refo_stack)) if len(self.refo_stack[0].shape) == 3: m, n, p = self.refo_stack[0].shape else: m, n, p = (self.refo_stack[0].shape[0], self.refo_stack[0].shape[1], 1) scheimpflug_img = np.zeros([m, n, p]) # map generation a_x = np.linspace( 0, a_stop - a_start, n + 2, dtype='int')[1:-1] # flooring via integer type while excluding a_y = np.linspace(0, a_stop - a_start, m + 2, dtype='int')[1:-1] a_map_x = np.outer(np.ones(m, dtype='int'), a_x) a_map_y = np.outer(a_y, np.ones(n, dtype='int')) # vertical orientation (default) a_map = a_map_y # horizontal orientation if self.cfg.params[self.cfg.opt_pflu] == c.PFLU_VALS[1]: a_map = a_map_x # diagonal orientation elif self.cfg.params[self.cfg.opt_pflu] == (c.PFLU_VALS[2] or c.PFLU_VALS[3]): # swap refocusing directions if option set if self.cfg.params[self.cfg.opt_pflu] == c.PFLU_VALS[3]: a_map_x, a_map_y = a_map_x[::-1], a_map_y[::-1] a_map = np.mean(np.stack([a_map_x, a_map_y]), dtype='int', axis=0) for y in range(m): for x in range(n): scheimpflug_img[y, x] = self.refo_stack[a_map[y, x]][y, x] # check interrupt status if self.sta.interrupt: return False # print status percentage = (((y * n + x + 1) / (m * n)) * 100) self.sta.progress(percentage, self.cfg.params[self.cfg.opt_prnt]) # write image file to hard drive a_ran = self.cfg.params[self.cfg.ran_refo] fn = 'scheimpflug_' + str(a_ran[0]) + '_' + str( a_ran[-1]) + '_' + self.cfg.params[self.cfg.opt_pflu] + '.png' misc.save_img_file( misc.Normalizer(scheimpflug_img).uint16_norm(), os.path.join(self.fp, fn)) return True
def export_thumbnail(self, type='tiff'): thumb = misc.Normalizer(self.central_view.copy()).type_norm() # export central viewpoint as thumbnail image fp = os.path.join(self.cfg.exp_path, 'thumbnail') misc.save_img_file(thumb, file_path=fp, file_type=type, tag=self.cfg.params[self.cfg.opt_dbug]) return True
def rectify_candidates_bayer(self, bay_img=None, n=2, sig_lev=4): # status message self.sta.status_msg('Hot pixel detection', self.cfg.params[self.cfg.opt_prnt]) bay_img = self._bay_img.copy() if bay_img is None else bay_img cum_img = np.zeros(bay_img[0::2, 0::2].shape) for c in range(4): i, j = c // 2, c % 2 # progress update percent = c / 4 self.sta.progress(percent * 100, self.cfg.params[self.cfg.opt_prnt]) # deduct median filtered image med_img = medfilt(bay_img[i::2, j::2].copy(), kernel_size=(3, 3)) m_img = bay_img[i::2, j::2].copy() / bay_img[ i::2, j::2].max() - med_img.copy() / med_img.max() new_img = self.rectify_candidates_channel( channel=bay_img[i::2, j::2].copy(), ref_img=m_img, med_img=med_img, n=n, sig_lev=sig_lev + 2) diff_img = bay_img[i::2, j::2].copy() - new_img cum_img[diff_img != 0] = 1 bay_img[i::2, j::2] = new_img # check interrupt status if self.sta.interrupt: return False # export hot-pixel map if self.cfg.params[self.cfg.opt_dbug]: hotp_num = len(cum_img[cum_img != 0]) misc.save_img_file(cum_img, file_path=os.path.join( self.cfg.exp_path, 'hot-pixel_map_' + str(hotp_num) + '.png')) # progress update self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) self._bay_img = bay_img return True
def write_centroids_img(self, fn='default_filename.png'): # draw MICs in binary image and save image file for debug purposes if self.cfg.params[self.cfg.opt_dbug]: plot_img = self.draw_centroids_img() save_img_file( plot_img, os.path.join( os.path.splitext(self.cfg.params[self.cfg.lfp_path])[0], fn)) # plot_centroids(img, centroids) return True
def export_vp_stack(self, type='tiff'): # print status self.sta.status_msg('Write viewpoint image stack', self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) # export all viewpoints in single image views_stacked_path = os.path.join(self.cfg.exp_path, 'views_stacked_img_'+str(self._M)+'px') misc.save_img_file(misc.img_resize(self.views_stacked_img, 1/self._M), file_path=views_stacked_path, file_type=type) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) return True
def _write_lfp_align(self): # convert to 16bit unsigned integer self._lfp_out = misc.Normalizer(self._lfp_out).uint16_norm() # create output data folder misc.mkdir_p(self.cfg.exp_path, self.cfg.params[self.cfg.opt_prnt]) # write aligned light field as pickle file to avoid recalculation with open(os.path.join(self.cfg.exp_path, 'lfp_img_align.pkl'), 'wb') as f: pickle.dump(self._lfp_out, f) if self.cfg.params[self.cfg.opt_dbug]: misc.save_img_file(self._lfp_out, os.path.join(self.cfg.exp_path, 'lfp_img_align.tiff'))
def save_refo_slice(self, a, refo_img, folder_path=None, file_type=None, string=None): string = 'subpixel_' if self.cfg.params[self.cfg.opt_refi] and string is None else string if folder_path is None: folder_path = os.path.join(self.cfg.exp_path, 'refo_' + string + str(self._M) + 'px') misc.mkdir_p(folder_path) # account for sub-pixel precise depth value a = round(float(a) / self._M, 2) if self.cfg.params[self.cfg.opt_refi] else a # write image file misc.save_img_file(refo_img, os.path.join(folder_path, str(a)), file_type=file_type) return True
def write_centroids_img(self, fn='centroids_img.png'): # status message handling self.sta.status_msg(msg='Save centroids image', opt=self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) # draw MICs in binary image and save image file for debug purposes plot_img = self.draw_centroids_img() save_img_file(plot_img, os.path.join(os.path.splitext(self.cfg.params[self.cfg.lfp_path])[0], fn)) # self.plot_centroids() # status message handling self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) return True
def export_viewpoints(vp_img_arr, cfg, type='tiff'): ptc_leng = cfg.params[cfg.ptc_leng] # create folder folderpath = os.path.join(cfg.params[cfg.lfp_path].split('.')[0], 'viewpoints_' + str(ptc_leng) + 'px') misc.mkdir_p(folderpath) # normalize image array to 16-bit unsigned integer vp_img_arr = misc.uint16_norm(vp_img_arr) # export viewpoint images as image files for j in range(ptc_leng): for i in range(ptc_leng): misc.save_img_file(vp_img_arr[j, i], os.path.join(folderpath, str(j) + '_' + str(i)), type=type) return True
def save_refo_slice(self, a, refo_img, folder_path=None, file_type=None, string=None): string = 'subpixel_' if self.cfg.params[ self.cfg.opt_refi] and string is None else string if folder_path is None: folder_path = os.path.join(self.cfg.exp_path, 'refo_' + string + str(self._M) + 'px') misc.mkdir_p(folder_path) # write image file misc.save_img_file(refo_img, os.path.join(folder_path, str(a)), file_type=file_type) return True
def decode_lytro_file(self): # Lytro type decoding with open(self._lfp_path, mode='rb') as file: # LFC and raw type decoding obj = LfpDecoder(file, self.cfg, self.sta, lfp_path=self._lfp_path) obj.main() self._lfp_img = obj.bay_img self._json_dict = obj.json_dict del obj # save bayer image as file (if not already present) if not os.path.exists(self.fp) and not self.sta.interrupt: self.sta.status_msg(msg='Save raw image', opt=self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) misc.save_img_file(misc.Normalizer( self._lfp_img).uint16_norm(), self.fp, file_type='tiff') self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) return True
def ver_hex_bulge(self, img): # variable init img = np.divide(img.astype('float'), img.max(), out=np.zeros_like(img), where=img != 0) m, n, ch = img.shape if len(img.shape) == 3 else img.shape + (1,) # j for shifted and i represents truth (unshifted) i, j = [1, 0] if self.hex_odd else [0, 1] # vertically interpolate pixels to get reference #phi = np.zeros((img[i::2, ...].shape[0], img.shape[1], img.shape[2])) #for p in range(ch): # fun = interp2d(range(img[i::2, ...].shape[1]), range(img[i::2, ...].shape[0]), img[i::2, :, p], kind=self.method) # phi[..., p] = fun(np.arange(img.shape[1]), np.linspace(0, img[i::2, ...].shape[0]+.5, img[i::2, ...].shape[0])) # gradient between shifted and unshifted (responsive to hex artifacts) dif = img[j::2, ...]-img[i::2, ...] if img[i::2, ...].shape[0] == img[j::2, ...].shape[0] else img[j::2, ...]-img[i::2, ...][:-1] # gradient between unshifted (responsive to real object edges) edg = img[i::2, ...][:-1]-img[i+2::2, ...] edg *= 0.75 # absolute values dif = abs(dif) edg = abs(edg) # (don't throw away channel information) dif = dif.sum(2) edg = edg.sum(2) # deduct actual edges karr = dif - edg if dif.shape[0] == edg.shape[0] else dif[:-1, ...] - edg karr = np.divide(karr, karr.max(), out=np.zeros_like(karr), where=karr != 0) karr[karr < 0] = 0 if self.cfg.params[self.cfg.opt_dbug]: misc.save_img_file(karr, os.path.join(self.cfg.exp_path, 'karr.png')) # replicate mask to 3 color channels arr = np.zeros(karr.shape+(3,)) #if karr.shape[0] == dif.shape[0] else np.zeros_like(dif[:-1, ...]) for p in range(ch): arr[..., p] = karr # form long col vector as we are only interested in vertical direction arr_vec = arr.copy().T.ravel() # remove spikes (fast peaks in vertical direction) #arr_med = medfilt(arr_vec, 3) # 1-D low pass to eliminate hi freq noise #gauss = misc.create_gauss_kernel(10, sig=1)[:, 3] #arr_gau = np.convolve(arr_med, gauss, 'same') arr_res = arr_vec.reshape(arr.T.shape).T #rat_res = rat_gau.reshape(rat.T.shape).T # threshold values with insufficient difference mask = np.divide(arr_res, arr_res.max(), out=np.zeros_like(arr_res), where=arr_res != 0) th = 0.1 mask[mask < th] = 0 mask[mask >= th] = 1 # ignore small regions mask = self.retain_connected(mask, n=4) # generate mask if self.cfg.params[self.cfg.opt_dbug]: full_mask = np.zeros(img.shape) if full_mask[j::2, ...].shape[0] == mask.shape[0]: full_mask[j::2, ...] = mask else: full_mask[j::2, ...][:-1] = mask misc.save_img_file(full_mask, os.path.join(self.cfg.exp_path, 'hex_filter_mask.png'), tag=True) # generate image indicating which pixels were treated if self.cfg.params[self.cfg.opt_dbug]: tes = img.copy() for p in range(ch): if tes[j::2, ...].shape[0] == mask.shape[0]: tes[j::2, :, p][mask[..., p] != 0] = tes.max() else: tes[j::2, :, p][:-1][mask[..., p] != 0] = tes.max() tes_out = np.divide(tes, tes.max(), out=np.zeros_like(tes), where=tes != 0) misc.save_img_file(tes_out, os.path.join(self.cfg.exp_path, 'ident.png'), tag=True) idxs = np.array(mask.nonzero()) r = 1 valid_idx = np.where((idxs[0] > r) & (idxs[1] > r) & (img[j::2].shape[0]-idxs[0] > r) & (img.shape[1]-idxs[1] > r))[0] idxs_vals = list(zip(idxs[0][valid_idx], idxs[1][valid_idx], idxs[2][valid_idx])) res = img.copy() arr_res = np.divide(arr_res, arr_res.max(), out=np.zeros_like(arr_res), where=arr_res != 0) for idx in idxs_vals: #f = arr_res[idx[0], idx[1], idx[2]] #new_val = res[j::2, ...][idx[0], idx[1], idx[2]] * (1-f) + phi[idx[0], idx[1], idx[2]] * f #shi[j::2, ...][idx[0], idx[1]]#np.mean(img[i::2, ...][idx[0]:idx[0]+2, idx[1]], axis=0) new_val = np.mean(img[i::2, ...][idx[0]:idx[0]+2, idx[1], idx[2]], axis=0) #new_val = np.mean(img[i::2, ...][idx[0]:idx[0]+2, idx[1]-1:idx[1]+2, idx[2]], axis=(0, 1)) res[j::2, ...][idx[0], idx[1], idx[2]] = new_val if self.cfg.params[self.cfg.opt_dbug]: misc.save_img_file(res, os.path.join(self.cfg.exp_path, 'hex-corr.png')) return res
def scheimpflug_from_scratch(self): patch_len = self.cfg.params[self.cfg.ptc_leng] a_start, a_stop = self.cfg.params[self.cfg.ran_refo] img = self.lfp_img.astype('float') / patch_len m, n, P = self.lfp_img.shape overlap = int(abs(a_stop) * (patch_len - 1)) #tilt_vec_y = np.linspace(a_start, planes, m).astype('uint') a_x = np.linspace(a_start, a_stop, n + overlap).astype('int') # flooring values instead of rounding => 1st round, then int() a_y = np.zeros(m).astype('int')#np.linspace(a_start, planes, m).astype('uint') a_xy = np.ones([m, n + overlap]).astype('int') * a_x # initialize matrices for intermediate and plane results hor_refo = np.zeros([m, n + overlap, P], dtype='float') ver_refo = np.zeros([m + overlap, n + overlap, P], dtype='float') fraction_vec = np.zeros([patch_len, P], dtype='float') # horizontal scheimpflug shift and integration for y in range(m): for x in range(n): # prevent from taking adjacent pixel being beyond image border if x + patch_len < n: adj_idx = x + patch_len else: adj_idx = x for p in range(P): fraction_vec[:, p] = np.linspace(img[y, x, p], img[y, adj_idx, p], patch_len) # load refocus value at x,y a = a_xy[y, x] # consider negative shift negative_a = int((patch_len - 1) * abs(a)) if a < 0 else 0 # centralize row row_shift = int((a_y.max() - a)*(patch_len - 1)/2) newX = int(x + np.mod(x, patch_len) * (a - 1) + negative_a) + row_shift hor_refo[y, newX:newX + patch_len, :] = hor_refo[y, newX:newX + patch_len, :] + fraction_vec # check interrupt status if self.sta.interrupt: return False # print progress status self.sta.progress((y+1)/m*50, self.cfg.params[self.cfg.opt_prnt]) # vertical scheimpflug shift and integration new_n = n + int(abs(a_x.max()) * (patch_len - 1)) for x in range(new_n): for y in range(m): if y + patch_len < m: adj_idx = y + patch_len else: adj_idx = y frac_vec = np.zeros([patch_len, int(n + abs(a_x.max()) * (patch_len - 1)), P], dtype='float') for p in range(P): frac_vec[:, x, p] = np.linspace(hor_refo[y, x, p], hor_refo[adj_idx, x, p], patch_len) # load refocus value at x,y a = a_xy[y, x] # consider negative shift negative_a = int((patch_len - 1) * abs(a)) if a < 0 else 0 # centralize column column_shift = int((a_x.max()-a)*(patch_len-1)/2) # put interpolated vector to refocusing plane newY = int(y + np.mod(y, patch_len) * (a - 1) + negative_a) + column_shift ver_refo[newY:newY + patch_len, :, :] = ver_refo[newY:newY + patch_len, :, :] + frac_vec # print progress status self.sta.progress(((x+1)/new_n+.5)*100, self.cfg.params[self.cfg.opt_prnt]) # write image file to hard drive fp = self.cfg.params[self.cfg.cfn_path].split('.')[0] img = misc.uint16_norm(ver_refo) misc.save_img_file(img, os.path.join(fp, 'scheimpflug_' + str(patch_len) + 'px.tiff')) return True
def main(self): if self._lfp_path.endswith(('.lfp', '.lfr', '.raw') + tuple('.c.'+str(num) for num in (0, 1, 2, 3))): # filename and file path from previously decoded data dp = os.path.splitext(self._lfp_path)[0] fn = os.path.basename(dp)+'.tiff' fp = os.path.join(dp, fn) # load previously generated tiff if present if os.path.exists(fp): try: self._lfp_img = misc.load_img_file(fp) except TypeError as e: self.sta.status_msg(e, self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) raise LfpTypeError(e) except FileNotFoundError as e: # print status self.sta.status_msg('File {0} not found'.format(self._lfp_path), self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) raise PlenopticamError(e) else: try: # Lytro type decoding with open(self._lfp_path, mode='rb') as file: # print status self.sta.status_msg('Decode Lytro image file', self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) # LFC and raw type decoding obj = LfpDecoder(file, self.cfg, self.sta) if self._lfp_path.endswith(('.lfp', '.lfr') + tuple('.c.'+str(num) for num in (0, 1, 2, 3))): # LFC type decoding obj.decode_lfc() self.cfg.save_json(os.path.join(dp, os.path.basename(dp)+'.json'), json_dict=obj.json_dict) elif self._lfp_path.endswith('.raw'): # raw type decoding obj.decode_raw() self._lfp_img = obj.rgb_img del obj # save bayer image as file misc.save_img_file(misc.uint16_norm(self._lfp_img), fp, type='tiff') # print status self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) except FileNotFoundError as e: # print status self.sta.status_msg('File {0} not found'.format(self._lfp_path), self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) raise PlenopticamError(e) else: try: # read and decode generic image file type self._lfp_img = misc.load_img_file(self._lfp_path) except TypeError as e: raise LfpTypeError(e) try: # try to load json file (if present) json_dict = self.cfg.load_json(self._lfp_path) self.cfg.lfpimg = LfpDecoder.filter_json(json_dict) except: pass # write json file self.cfg.save_params() return True
def main(self): if self._lfp_path.lower().endswith(SUPP_FILE_EXT): # filename and file path from previously decoded data dp = os.path.splitext(self._lfp_path)[0] fn = os.path.basename(dp) + '.tiff' fp = os.path.join(dp, fn) # load previously generated tiff if present if os.path.exists(fp): try: self._lfp_img = misc.load_img_file(fp) except FileNotFoundError: # print status self.sta.status_msg( '{0} not found'.format(os.path.basename( self._lfp_path)), self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) self.sta.error = True except TypeError as e: self.sta.status_msg(e, self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) raise LfpTypeError(e) else: try: # Lytro type decoding with open(self._lfp_path, mode='rb') as file: # LFC and raw type decoding obj = LfpDecoder(file, self.cfg, self.sta) if self._lfp_path.lower().endswith(SUPP_FILE_EXT[1:]): # LFC type decoding obj.decode_lfc() self.cfg.save_json(os.path.join( dp, os.path.basename(dp) + '.json'), json_dict=obj.json_dict) elif self._lfp_path.lower().endswith(SUPP_FILE_EXT[0]): # raw type decoding obj.decode_raw() self._lfp_img = obj.rgb_img del obj # save bayer image as file self.sta.status_msg( msg='Save raw image', opt=self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(None, self.cfg.params[self.cfg.opt_prnt]) misc.save_img_file(misc.Normalizer( self._lfp_img).uint16_norm(), fp, file_type='tiff') self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) except FileNotFoundError: # print status self.sta.status_msg( '{0} not found'.format(os.path.basename( self._lfp_path)), self.cfg.params[self.cfg.opt_prnt]) self.sta.progress(100, self.cfg.params[self.cfg.opt_prnt]) self.sta.error = True except Exception as e: # unrecognized LFP file type if not obj.json_dict: raise LfpTypeError(e) else: raise PlenopticamError(e) else: try: # read and decode generic image file type self._lfp_img = misc.load_img_file(self._lfp_path) except TypeError as e: raise LfpTypeError(e) try: # try to load json file (if present) json_dict = self.cfg.load_json(self._lfp_path) self.cfg.lfpimg = LfpDecoder.filter_json(json_dict) except: pass # write json file self.cfg.save_params() return True
def ver_hex_bulge(self, img): # variable init img = np.divide(img.astype('float'), img.max(), out=np.zeros_like(img), where=img != 0) m, n, ch = img.shape if len(img.shape) == 3 else img.shape + (1,) # j for shifted and i represents truth (unshifted) i, j = [1, 0] if self.hex_odd else [0, 1] # gradient between shifted and unshifted (responsive to hex artifacts) if img[i::2, ...].shape[0] == img[j::2, ...].shape[0]: dif = img[j::2, ...]-img[i::2, ...] elif img[j::2, ...].shape[0] == img[i::2, ...].shape[0]+1: dif = img[j::2, ...][:-1]-img[i::2, ...] elif img[j::2, ...].shape[0]+1 == img[i::2, ...].shape[0]: dif = img[j::2, ...] - img[i::2, ...][:-1] else: self.sta.error('Image dimension mismatch') return False # gradient between unshifted (responsive to real object edges) edg = img[i::2, ...][:-1]-img[i+2::2, ...] edg *= 0.75 # absolute values dif = abs(dif) edg = abs(edg) # (don't throw away channel information) dif = dif.sum(2) edg = edg.sum(2) # deduct actual edges karr = dif - edg if dif.shape[0] == edg.shape[0] else dif[:-1, ...] - edg karr = np.divide(karr, karr.max(), out=np.zeros_like(karr), where=karr != 0) karr[karr < 0] = 0 if self.cfg.params[self.cfg.opt_dbug]: misc.save_img_file(karr, os.path.join(self.cfg.exp_path, 'karr.png')) # replicate mask to 3 color channels arr = np.zeros(karr.shape+(3,)) for p in range(ch): arr[..., p] = karr # threshold values with insufficient difference mask = np.divide(arr, arr.max(), out=np.zeros_like(arr), where=arr != 0) th = 0.1 mask[mask < th] = 0 mask[mask >= th] = 1 # ignore small regions mask = self.retain_connected(mask, n=4) # generate mask if self.cfg.params[self.cfg.opt_dbug]: full_mask = np.zeros(img.shape) if full_mask[j::2, ...].shape[0] == mask.shape[0]: full_mask[j::2, ...] = mask else: full_mask[j::2, ...][:-1] = mask misc.save_img_file(full_mask, os.path.join(self.cfg.exp_path, 'hex_filter_mask.png'), tag=True) # generate image indicating which pixels were treated if self.cfg.params[self.cfg.opt_dbug]: tes = img.copy() for p in range(ch): if tes[j::2, ...].shape[0] == mask.shape[0]: tes[j::2, :, p][mask[..., p] != 0] = tes.max() else: tes[j::2, :, p][:-1][mask[..., p] != 0] = tes.max() tes_out = np.divide(tes, tes.max(), out=np.zeros_like(tes), where=tes != 0) misc.save_img_file(tes_out, os.path.join(self.cfg.exp_path, 'ident.png'), tag=True) idxs = np.array(mask.nonzero()) r = 1 valid_idx = np.where((idxs[0] > r) & (idxs[1] > r) & (img[j::2].shape[0]-idxs[0] > r) & (img.shape[1]-idxs[1] > r))[0] idxs_vals = list(zip(idxs[0][valid_idx], idxs[1][valid_idx], idxs[2][valid_idx])) res = img.copy() for idx in idxs_vals: new_val = np.mean(img[i::2, ...][idx[0]:idx[0]+2, idx[1], idx[2]], axis=0) res[j::2, ...][idx[0], idx[1], idx[2]] = new_val if self.cfg.params[self.cfg.opt_dbug]: misc.save_img_file(res, os.path.join(self.cfg.exp_path, 'hex-corr.png')) return res