def main(self): # compose bayer image from input image buffer self.comp_bayer() # debayer to rgb image if 'bay' in self.cfg.lfpimg.keys() and len(self._bay_img.shape) == 2: self.bay2rgb() # auto white balance if 'awb' in self.cfg.lfpimg.keys(): self._rgb_img = self.correct_awb(self._rgb_img, self.cfg.lfpimg['bay'], gains=self.cfg.lfpimg['awb']) self._rgb_img = self.desaturate_clipped( self._rgb_img, gains=self.cfg.lfpimg['awb']) # perform gamma correction if 'gam' in self.cfg.lfpimg.keys(): self._rgb_img = self.correct_gamma(self._rgb_img, gamma=self.cfg.lfpimg['gam']) # color matrix correction if 'ccm' in self.cfg.lfpimg.keys(): self._rgb_img = self.correct_color(self._rgb_img, ccm_mat=np.reshape( self.cfg.lfpimg['ccm'], (3, 3)).T) # convert to uint16 self._rgb_img = misc.uint16_norm(self._rgb_img) 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_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 _write_lfp_align(self): # convert to 16bit unsigned integer self._lfp_out = misc.uint16_norm(self._lfp_out) out_path = self.cfg.params[self.cfg.lfp_path].split('.')[0] # create output data folder misc.mkdir_p(self.cfg.params[self.cfg.lfp_path].split('.')[0], self.cfg.params[self.cfg.opt_prnt]) # write aligned light field as pickle file to avoid recalculation with open(os.path.join(out_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(out_path, 'lfp_img_align.tiff'))
def scheimpflug_from_stack(self): a_start, a_stop = self.cfg.params[self.cfg.ran_refo] 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[2]: a_map = a_map_x # diagonal orientation elif self.cfg.params[self.cfg.opt_pflu] == (c.PFLU_VALS[3] or c.PFLU_VALS[4]): a_map = np.mean([a_map_x, a_map_y], dtype='int', axis=self.cfg.params[self.cfg.opt_pflu]-3) 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 fp = os.path.splitext(self.cfg.params[self.cfg.lfp_path])[0] fn = 'scheimpflug_' + str(a_start) + '_' + str(a_stop) + '_' + self.cfg.params[self.cfg.opt_pflu] + '.png' misc.save_img_file(misc.uint16_norm(scheimpflug_img), os.path.join(fp, fn)) return True
def save_img_file(img, file_path, type=None): img = place_dnp(img) ext = os.path.splitext(file_path)[-1][1:] if not type: type = ext if ext == 'png' or ext == 'tiff' else 'tiff' if img.dtype == 'uint16' else 'png' file_path = file_path + '.' + type if ext != type else file_path if type == 'tiff': obj = TIFF.open(file_path, mode='w') obj.write_image(misc.uint16_norm(img), compression=None, write_rgb=True) obj.close() elif type == 'png' or type == 'bmp': Image.fromarray(misc.uint8_norm(img)).save(file_path, type, optimize=True) return True
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