Spaces:
Build error
Build error
| ''' | |
| render using frames in GS | |
| inpaint with fooocus | |
| ''' | |
| import os | |
| import torch | |
| import numpy as np | |
| from PIL import Image | |
| from copy import deepcopy | |
| from ops.utils import * | |
| from ops.sky import Sky_Seg_Tool | |
| from ops.visual_check import Check | |
| from ops.gs.train import GS_Train_Tool | |
| from pipe.lvm_inpaint import Inpaint_Tool | |
| from pipe.reconstruct import Reconstruct_Tool | |
| from ops.trajs import _generate_trajectory | |
| from ops.connect import Occlusion_Removal | |
| from ops.gs.basic import Frame,Gaussian_Scene | |
| from ops.mcs import HackSD_MCS | |
| from pipe.refine_mvdps import Refinement_Tool_MCS | |
| class Pipeline(): | |
| def __init__(self,cfg) -> None: | |
| self.device = 'cuda' | |
| self.cfg = cfg | |
| self.sky_value = cfg.model.sky.value | |
| self.sky_segor = Sky_Seg_Tool(cfg) | |
| self.rgb_inpaintor = Inpaint_Tool(cfg) | |
| self.reconstructor = Reconstruct_Tool(cfg) | |
| # temp | |
| self.removalor = Occlusion_Removal() | |
| self.checkor = Check() | |
| def _mkdir(self,dir): | |
| if not os.path.exists(dir): | |
| os.makedirs(dir) | |
| def _resize_input(self,fn): | |
| resize_long_edge = int(self.cfg.scene.input.resize_long_edge) | |
| print(f'[Preprocess...] Resize the long edge of input image to {resize_long_edge}.') | |
| spl = str.rfind(fn,'.') | |
| backup_fn = fn[:spl] + '.original' + fn[spl:] | |
| rgb = Image.open(fn) | |
| rgb.save(backup_fn) # back up original image | |
| rgb = np.array(rgb)[:,:,:3]/255. | |
| H,W = rgb.shape[0:2] | |
| if H>W: | |
| W = int(W*resize_long_edge/H) | |
| H = resize_long_edge | |
| else: | |
| H = int(H*resize_long_edge/W) | |
| W = resize_long_edge | |
| rgb = cv2.resize(rgb,(W,H)) | |
| pic = (rgb * 255.0).clip(0, 255) | |
| pic_save = Image.fromarray(pic.astype(np.uint8)) | |
| pic_save.save(fn) | |
| def _initialization(self,rgb): | |
| rgb = np.array(rgb)[:,:,:3] | |
| # conduct outpainting on rgb and change cu,cv | |
| outpaint_frame :Frame = self.rgb_inpaintor(Frame(rgb=rgb), | |
| outpaint_selections=self.outpaint_selections, | |
| outpaint_extend_times=self.outpaint_extend_times) | |
| # conduct reconstruction on outpaint results | |
| _,intrinsic,_ = self.reconstructor._ProDpt_(rgb) # estimate focal on input view | |
| metric_dpt,intrinsic,edge_msk = self.reconstructor._ProDpt_(outpaint_frame.rgb) | |
| outpaint_frame.intrinsic = deepcopy(intrinsic) | |
| # split to input and outpaint areas | |
| input_frame = Frame(H=rgb.shape[0], | |
| W=rgb.shape[1], | |
| rgb=rgb, | |
| intrinsic=deepcopy(intrinsic), | |
| extrinsic=np.eye(4)) | |
| input_frame.intrinsic[0,-1] = input_frame.W/2. | |
| input_frame.intrinsic[1,-1] = input_frame.H/2. | |
| # others | |
| input_area = ~outpaint_frame.inpaint | |
| input_edg = edge_msk[input_area].reshape(input_frame.H,input_frame.W) | |
| input_dpt = metric_dpt[input_area].reshape(input_frame.H,input_frame.W) | |
| sky = self.sky_segor(input_frame.rgb) | |
| input_frame.sky = sky | |
| input_dpt[sky] = self.sky_value | |
| input_frame.dpt = input_dpt | |
| input_frame.inpaint = np.ones_like(input_edg,bool) & (~sky) | |
| input_frame.inpaint_wo_edge = (~input_edg) & (~sky) | |
| input_frame.ideal_dpt = deepcopy(input_dpt) | |
| input_frame.prompt = outpaint_frame.prompt | |
| # outpaint frame | |
| sky = self.sky_segor(outpaint_frame.rgb) | |
| outpaint_frame.sky = sky | |
| metric_dpt[sky] = self.sky_value | |
| outpaint_frame.dpt = metric_dpt | |
| outpaint_frame.ideal_dpt = deepcopy(metric_dpt) | |
| outpaint_frame.inpaint = (outpaint_frame.inpaint)&(~sky) | |
| outpaint_frame.inpaint_wo_edge = (outpaint_frame.inpaint)&(~edge_msk) | |
| # add init frame | |
| self.scene._add_trainable_frame(input_frame,require_grad=True) | |
| self.scene._add_trainable_frame(outpaint_frame,require_grad=True) | |
| self.scene = GS_Train_Tool(self.scene,iters=100)(self.scene.frames) | |
| def _generate_traj(self): | |
| self.dense_trajs = _generate_trajectory(self.cfg,self.scene) | |
| def _pose_to_frame(self,extrinsic,margin=32): | |
| H = self.scene.frames[0].H + margin | |
| W = self.scene.frames[0].W + margin | |
| prompt = self.scene.frames[-1].prompt | |
| intrinsic = deepcopy(self.scene.frames[0].intrinsic) | |
| intrinsic[0,-1], intrinsic[1,-1] = W/2, H/2 | |
| frame = Frame(H=H,W=W,intrinsic=intrinsic,extrinsic=extrinsic,prompt=prompt) | |
| frame = self.scene._render_for_inpaint(frame) | |
| return frame | |
| def _next_frame(self,margin=32): | |
| # select the frame with largest holes but less than 60% | |
| inpaint_area_ratio = [] | |
| for pose in self.dense_trajs: | |
| temp_frame = self._pose_to_frame(pose,margin) | |
| inpaint_mask = temp_frame.inpaint | |
| inpaint_area_ratio.append(np.mean(inpaint_mask)) | |
| inpaint_area_ratio = np.array(inpaint_area_ratio) | |
| inpaint_area_ratio[inpaint_area_ratio > 0.6] = 0. | |
| # remove adjustancy frames | |
| for s in self.select_frames: | |
| inpaint_area_ratio[s] = 0. | |
| if s-1>-1: | |
| inpaint_area_ratio[s-1] = 0. | |
| if s+1<len(self.dense_trajs): | |
| inpaint_area_ratio[s+1] = 0. | |
| # select the largest ones | |
| select = np.argmax(inpaint_area_ratio) | |
| if inpaint_area_ratio[select] < 0.0001: return None | |
| self.select_frames.append(select) | |
| pose = self.dense_trajs[select] | |
| frame = self._pose_to_frame(pose,margin) | |
| return frame | |
| def _inpaint_next_frame(self,margin=32): | |
| frame = self._next_frame(margin) | |
| if frame is None: return None | |
| # inpaint rgb | |
| frame = self.rgb_inpaintor(frame) | |
| # inpaint dpt | |
| connect_dpt,metric_dpt,_,edge_msk = self.reconstructor._Guide_ProDpt_(frame.rgb,frame.intrinsic,frame.dpt,~frame.inpaint) | |
| frame.dpt = connect_dpt | |
| frame = self.removalor(self.scene,frame) | |
| sky = self.sky_segor(frame.rgb) | |
| frame.sky = sky | |
| frame.dpt[sky] = self.sky_value | |
| frame.inpaint = (frame.inpaint) & (~sky) | |
| frame.inpaint_wo_edge = (frame.inpaint) & (~edge_msk) | |
| # determine target depth and normal | |
| frame.ideal_dpt = metric_dpt | |
| self.scene._add_trainable_frame(frame) | |
| return 0 | |
| def _coarse_scene(self,rgb): | |
| self._initialization(rgb) | |
| self._generate_traj() | |
| self.select_frames = [] | |
| for i in range(self.n_sample-2): | |
| print(f'Procecssing {i+2}/{self.n_sample} frame...') | |
| sign = self._inpaint_next_frame() | |
| if sign is None: break | |
| self.scene = GS_Train_Tool(self.scene,iters=self.opt_iters_per_frame)(self.scene.frames) | |
| def _MCS_Refinement(self): | |
| refiner = HackSD_MCS(device='cuda',use_lcm=True,denoise_steps=self.mcs_iterations, | |
| sd_ckpt=self.cfg.model.optimize.sd, | |
| lcm_ckpt=self.cfg.model.optimize.lcm) | |
| self.MVDPS = Refinement_Tool_MCS(self.scene,device='cuda', | |
| refiner=refiner, | |
| traj_type=self.traj_type, | |
| n_view=self.mcs_n_view, | |
| rect_w=self.mcs_rect_w, | |
| n_gsopt_iters=self.mcs_gsopt_per_frame) | |
| self.scene = self.MVDPS() | |
| refiner.to('cpu') | |
| def __call__(self): | |
| rgb_fn = self.cfg.scene.input.rgb | |
| # coarse | |
| self.scene = Gaussian_Scene(self.cfg) | |
| # for trajectory genearation | |
| self.n_sample = self.cfg.scene.traj.n_sample | |
| self.traj_type = self.cfg.scene.traj.traj_type | |
| self.scene.traj_type = self.cfg.scene.traj.traj_type | |
| # for scene generation | |
| self.opt_iters_per_frame = self.cfg.scene.gaussian.opt_iters_per_frame | |
| self.outpaint_selections = self.cfg.scene.outpaint.outpaint_selections | |
| self.outpaint_extend_times = self.cfg.scene.outpaint.outpaint_extend_times | |
| # for scene refinement | |
| self.mcs_n_view = self.cfg.scene.mcs.n_view | |
| self.mcs_rect_w = self.cfg.scene.mcs.rect_w | |
| self.mcs_iterations = self.cfg.scene.mcs.steps | |
| self.mcs_gsopt_per_frame = self.cfg.scene.mcs.gsopt_iters | |
| # coarse scene | |
| self._resize_input(rgb_fn) | |
| dir = rgb_fn[:str.rfind(rgb_fn,'/')] | |
| rgb = Image.open(rgb_fn) | |
| self._coarse_scene(rgb) | |
| torch.cuda.empty_cache() | |
| # refinement | |
| self._MCS_Refinement() | |
| torch.save(self.scene,f'{dir}/scene.pth') | |
| self.checkor._render_video(self.scene,save_dir=f'{dir}/') | |