CoolFace
Apppublic

Joeythemonster/Text2Video-Zero

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
model.py498 linesDownload Raw Back to root
1from enum import Enum2import gc3import numpy as np4import tomesd5import torch6 7from diffusers import StableDiffusionInstructPix2PixPipeline, StableDiffusionControlNetPipeline, ControlNetModel, UNet2DConditionModel8from diffusers.schedulers import EulerAncestralDiscreteScheduler, DDIMScheduler9from text_to_video_pipeline import TextToVideoPipeline10 11import utils12import gradio_utils13import os14on_huggingspace = os.environ.get("SPACE_AUTHOR_NAME") == "PAIR"15 16from einops import rearrange17 18 19class ModelType(Enum):20    Pix2Pix_Video = 1,21    Text2Video = 2,22    ControlNetCanny = 3,23    ControlNetCannyDB = 4,24    ControlNetPose = 5,25    ControlNetDepth = 6,26 27 28class Model:29    def __init__(self, device, dtype, **kwargs):30        self.device = device31        self.dtype = dtype32        self.generator = torch.Generator(device=device)33        self.pipe_dict = {34            ModelType.Pix2Pix_Video: StableDiffusionInstructPix2PixPipeline,35            ModelType.Text2Video: TextToVideoPipeline,36            ModelType.ControlNetCanny: StableDiffusionControlNetPipeline,37            ModelType.ControlNetCannyDB: StableDiffusionControlNetPipeline,38            ModelType.ControlNetPose: StableDiffusionControlNetPipeline,39            ModelType.ControlNetDepth: StableDiffusionControlNetPipeline,40        }41        self.controlnet_attn_proc = utils.CrossFrameAttnProcessor(42            unet_chunk_size=2)43        self.pix2pix_attn_proc = utils.CrossFrameAttnProcessor(44            unet_chunk_size=3)45        self.text2video_attn_proc = utils.CrossFrameAttnProcessor(46            unet_chunk_size=2)47 48        self.pipe = None49        self.model_type = None50 51        self.states = {}52        self.model_name = ""53 54    def set_model(self, model_type: ModelType, model_id: str, **kwargs):55        if hasattr(self, "pipe") and self.pipe is not None:56            del self.pipe57        torch.cuda.empty_cache()58        gc.collect()59        safety_checker = kwargs.pop('safety_checker', None)60        self.pipe = self.pipe_dict[model_type].from_pretrained(61            model_id, safety_checker=safety_checker, **kwargs).to(self.device).to(self.dtype)62        self.model_type = model_type63        self.model_name = model_id64 65    def inference_chunk(self, frame_ids, **kwargs):66        if not hasattr(self, "pipe") or self.pipe is None:67            return68 69        prompt = np.array(kwargs.pop('prompt'))70        negative_prompt = np.array(kwargs.pop('negative_prompt', ''))71        latents = None72        if 'latents' in kwargs:73            latents = kwargs.pop('latents')[frame_ids]74        if 'image' in kwargs:75            kwargs['image'] = kwargs['image'][frame_ids]76        if 'video_length' in kwargs:77            kwargs['video_length'] = len(frame_ids)78        if self.model_type == ModelType.Text2Video:79            kwargs["frame_ids"] = frame_ids80        return self.pipe(prompt=prompt[frame_ids].tolist(),81                         negative_prompt=negative_prompt[frame_ids].tolist(),82                         latents=latents,83                         generator=self.generator,84                         **kwargs)85 86    def inference(self, split_to_chunks=False, chunk_size=2, **kwargs):87        if not hasattr(self, "pipe") or self.pipe is None:88            return89 90        if "merging_ratio" in kwargs:91            merging_ratio = kwargs.pop("merging_ratio")92 93            # if merging_ratio > 0:94            tomesd.apply_patch(self.pipe, ratio=merging_ratio)95        seed = kwargs.pop('seed', 0)96        if seed < 0:97            seed = self.generator.seed()98        kwargs.pop('generator', '')99 100        if 'image' in kwargs:101            f = kwargs['image'].shape[0]102        else:103            f = kwargs['video_length']104 105        assert 'prompt' in kwargs106        prompt = [kwargs.pop('prompt')] * f107        negative_prompt = [kwargs.pop('negative_prompt', '')] * f108 109        frames_counter = 0110 111        # Processing chunk-by-chunk112        if split_to_chunks:113            chunk_ids = np.arange(0, f, chunk_size - 1)114            result = []115            for i in range(len(chunk_ids)):116                ch_start = chunk_ids[i]117                ch_end = f if i == len(chunk_ids) - 1 else chunk_ids[i + 1]118                frame_ids = [0] + list(range(ch_start, ch_end))119                self.generator.manual_seed(seed)120                print(f'Processing chunk {i + 1} / {len(chunk_ids)}')121                result.append(self.inference_chunk(frame_ids=frame_ids,122                                                   prompt=prompt,123                                                   negative_prompt=negative_prompt,124                                                   **kwargs).images[1:])125                frames_counter += len(chunk_ids)-1126                if on_huggingspace and frames_counter >= 80:127                    break128            result = np.concatenate(result)129            return result130        else:131            self.generator.manual_seed(seed)132            return self.pipe(prompt=prompt, negative_prompt=negative_prompt, generator=self.generator, **kwargs).images133 134    def process_controlnet_canny(self,135                                 video_path,136                                 prompt,137                                 chunk_size=2,138                                 watermark='Picsart AI Research',139                                 merging_ratio=0.0,140                                 num_inference_steps=20,141                                 controlnet_conditioning_scale=1.0,142                                 guidance_scale=9.0,143                                 seed=42,144                                 eta=0.0,145                                 low_threshold=100,146                                 high_threshold=200,147                                 resolution=512,148                                 use_cf_attn=True,149                                 save_path=None):150        print("Module Canny")151        video_path = gradio_utils.edge_path_to_video_path(video_path)152        if self.model_type != ModelType.ControlNetCanny:153            controlnet = ControlNetModel.from_pretrained(154                "lllyasviel/sd-controlnet-canny")155            self.set_model(ModelType.ControlNetCanny,156                           model_id="runwayml/stable-diffusion-v1-5", controlnet=controlnet)157 158            self.pipe.scheduler = DDIMScheduler.from_config(159                self.pipe.scheduler.config)160            if use_cf_attn:161                self.pipe.unet.set_attn_processor(162                    processor=self.controlnet_attn_proc)163                self.pipe.controlnet.set_attn_processor(164                    processor=self.controlnet_attn_proc)165 166        added_prompt = 'best quality, extremely detailed'167        negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality'168 169        video, fps = utils.prepare_video(170            video_path, resolution, self.device, self.dtype, False)171        control = utils.pre_process_canny(172            video, low_threshold, high_threshold).to(self.device).to(self.dtype)173 174        # canny_to_save = list(rearrange(control, 'f c w h -> f w h c').cpu().detach().numpy())175        # _ = utils.create_video(canny_to_save, 4, path="ddxk.mp4", watermark=None)176 177        f, _, h, w = video.shape178        self.generator.manual_seed(seed)179        latents = torch.randn((1, 4, h//8, w//8), dtype=self.dtype,180                              device=self.device, generator=self.generator)181        latents = latents.repeat(f, 1, 1, 1)182        result = self.inference(image=control,183                                prompt=prompt + ', ' + added_prompt,184                                height=h,185                                width=w,186                                negative_prompt=negative_prompts,187                                num_inference_steps=num_inference_steps,188                                guidance_scale=guidance_scale,189                                controlnet_conditioning_scale=controlnet_conditioning_scale,190                                eta=eta,191                                latents=latents,192                                seed=seed,193                                output_type='numpy',194                                split_to_chunks=True,195                                chunk_size=chunk_size,196                                merging_ratio=merging_ratio,197                                )198        return utils.create_video(result, fps, path=save_path, watermark=gradio_utils.logo_name_to_path(watermark))199 200    def process_controlnet_depth(self,201                                 video_path,202                                 prompt,203                                 chunk_size=2,204                                 watermark='Picsart AI Research',205                                 merging_ratio=0.0,206                                 num_inference_steps=20,207                                 controlnet_conditioning_scale=1.0,208                                 guidance_scale=9.0,209                                 seed=42,210                                 eta=0.0,211                                 resolution=512,212                                 use_cf_attn=True,213                                 save_path=None):214        print("Module Depth")215        video_path = gradio_utils.depth_path_to_video_path(video_path)216        if self.model_type != ModelType.ControlNetDepth:217            controlnet = ControlNetModel.from_pretrained(218                "lllyasviel/sd-controlnet-depth")219            self.set_model(ModelType.ControlNetDepth,220                           model_id="runwayml/stable-diffusion-v1-5", controlnet=controlnet)221            self.pipe.scheduler = DDIMScheduler.from_config(222                self.pipe.scheduler.config)223            if use_cf_attn:224                self.pipe.unet.set_attn_processor(225                    processor=self.controlnet_attn_proc)226                self.pipe.controlnet.set_attn_processor(227                    processor=self.controlnet_attn_proc)228 229        added_prompt = 'best quality, extremely detailed'230        negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality'231 232        video, fps = utils.prepare_video(233            video_path, resolution, self.device, self.dtype, False)234        control = utils.pre_process_depth(235            video).to(self.device).to(self.dtype)236 237        # depth_map_to_save = list(rearrange(control, 'f c w h -> f w h c').cpu().detach().numpy())238        # _ = utils.create_video(depth_map_to_save, 4, path="ddxk.mp4", watermark=None)239 240        f, _, h, w = video.shape241        self.generator.manual_seed(seed)242        latents = torch.randn((1, 4, h//8, w//8), dtype=self.dtype,243                              device=self.device, generator=self.generator)244        latents = latents.repeat(f, 1, 1, 1)245        result = self.inference(image=control,246                                prompt=prompt + ', ' + added_prompt,247                                height=h,248                                width=w,249                                negative_prompt=negative_prompts,250                                num_inference_steps=num_inference_steps,251                                guidance_scale=guidance_scale,252                                controlnet_conditioning_scale=controlnet_conditioning_scale,253                                eta=eta,254                                latents=latents,255                                seed=seed,256                                output_type='numpy',257                                split_to_chunks=True,258                                chunk_size=chunk_size,259                                merging_ratio=merging_ratio,260                                )261        return utils.create_video(result, fps, path=save_path, watermark=gradio_utils.logo_name_to_path(watermark))262 263    def process_controlnet_pose(self,264                                video_path,265                                prompt,266                                chunk_size=2,267                                watermark='Picsart AI Research',268                                merging_ratio=0.0,269                                num_inference_steps=20,270                                controlnet_conditioning_scale=1.0,271                                guidance_scale=9.0,272                                seed=42,273                                eta=0.0,274                                resolution=512,275                                use_cf_attn=True,276                                save_path=None):277        print("Module Pose")278        video_path = gradio_utils.motion_to_video_path(video_path)279        if self.model_type != ModelType.ControlNetPose:280            controlnet = ControlNetModel.from_pretrained(281                "fusing/stable-diffusion-v1-5-controlnet-openpose")282            self.set_model(ModelType.ControlNetPose,283                           model_id="runwayml/stable-diffusion-v1-5", controlnet=controlnet)284            self.pipe.scheduler = DDIMScheduler.from_config(285                self.pipe.scheduler.config)286            if use_cf_attn:287                self.pipe.unet.set_attn_processor(288                    processor=self.controlnet_attn_proc)289                self.pipe.controlnet.set_attn_processor(290                    processor=self.controlnet_attn_proc)291 292        video_path = gradio_utils.motion_to_video_path(293            video_path) if 'Motion' in video_path else video_path294 295        added_prompt = 'best quality, extremely detailed, HD, ultra-realistic, 8K, HQ, masterpiece, trending on artstation, art, smooth'296        negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer difits, cropped, worst quality, low quality, deformed body, bloated, ugly, unrealistic'297 298        video, fps = utils.prepare_video(299            video_path, resolution, self.device, self.dtype, False, output_fps=4)300        control = utils.pre_process_pose(301            video, apply_pose_detect=False).to(self.device).to(self.dtype)302        f, _, h, w = video.shape303        self.generator.manual_seed(seed)304        latents = torch.randn((1, 4, h//8, w//8), dtype=self.dtype,305                              device=self.device, generator=self.generator)306        latents = latents.repeat(f, 1, 1, 1)307        result = self.inference(image=control,308                                prompt=prompt + ', ' + added_prompt,309                                height=h,310                                width=w,311                                negative_prompt=negative_prompts,312                                num_inference_steps=num_inference_steps,313                                guidance_scale=guidance_scale,314                                controlnet_conditioning_scale=controlnet_conditioning_scale,315                                eta=eta,316                                latents=latents,317                                seed=seed,318                                output_type='numpy',319                                split_to_chunks=True,320                                chunk_size=chunk_size,321                                merging_ratio=merging_ratio,322                                )323        return utils.create_gif(result, fps, path=save_path, watermark=gradio_utils.logo_name_to_path(watermark))324 325    def process_controlnet_canny_db(self,326                                    db_path,327                                    video_path,328                                    prompt,329                                    chunk_size=2,330                                    watermark='Picsart AI Research',331                                    merging_ratio=0.0,332                                    num_inference_steps=20,333                                    controlnet_conditioning_scale=1.0,334                                    guidance_scale=9.0,335                                    seed=42,336                                    eta=0.0,337                                    low_threshold=100,338                                    high_threshold=200,339                                    resolution=512,340                                    use_cf_attn=True,341                                    save_path=None):342        print("Module Canny_DB")343        db_path = gradio_utils.get_model_from_db_selection(db_path)344        video_path = gradio_utils.get_video_from_canny_selection(video_path)345        # Load db and controlnet weights346        if 'db_path' not in self.states or db_path != self.states['db_path']:347            controlnet = ControlNetModel.from_pretrained(348                "lllyasviel/sd-controlnet-canny")349            self.set_model(ModelType.ControlNetCannyDB,350                           model_id=db_path, controlnet=controlnet)351            self.pipe.scheduler = DDIMScheduler.from_config(352                self.pipe.scheduler.config)353            self.states['db_path'] = db_path354 355        if use_cf_attn:356            self.pipe.unet.set_attn_processor(357                processor=self.controlnet_attn_proc)358            self.pipe.controlnet.set_attn_processor(359                processor=self.controlnet_attn_proc)360 361        added_prompt = 'best quality, extremely detailed'362        negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality'363 364        video, fps = utils.prepare_video(365            video_path, resolution, self.device, self.dtype, False)366        control = utils.pre_process_canny(367            video, low_threshold, high_threshold).to(self.device).to(self.dtype)368        f, _, h, w = video.shape369        self.generator.manual_seed(seed)370        latents = torch.randn((1, 4, h//8, w//8), dtype=self.dtype,371                              device=self.device, generator=self.generator)372        latents = latents.repeat(f, 1, 1, 1)373        result = self.inference(image=control,374                                prompt=prompt + ', ' + added_prompt,375                                height=h,376                                width=w,377                                negative_prompt=negative_prompts,378                                num_inference_steps=num_inference_steps,379                                guidance_scale=guidance_scale,380                                controlnet_conditioning_scale=controlnet_conditioning_scale,381                                eta=eta,382                                latents=latents,383                                seed=seed,384                                output_type='numpy',385                                split_to_chunks=True,386                                chunk_size=chunk_size,387                                merging_ratio=merging_ratio,388                                )389        return utils.create_gif(result, fps, path=save_path, watermark=gradio_utils.logo_name_to_path(watermark))390 391    def process_pix2pix(self,392                        video,393                        prompt,394                        resolution=512,395                        seed=0,396                        image_guidance_scale=1.0,397                        start_t=0,398                        end_t=-1,399                        out_fps=-1,400                        chunk_size=2,401                        watermark='Picsart AI Research',402                        merging_ratio=0.0,403                        use_cf_attn=True,404                        save_path=None,):405        print("Module Pix2Pix")406        if self.model_type != ModelType.Pix2Pix_Video:407            self.set_model(ModelType.Pix2Pix_Video,408                           model_id="timbrooks/instruct-pix2pix")409            self.pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(410                self.pipe.scheduler.config)411            if use_cf_attn:412                self.pipe.unet.set_attn_processor(413                    processor=self.pix2pix_attn_proc)414        video, fps = utils.prepare_video(415            video, resolution, self.device, self.dtype, True, start_t, end_t, out_fps)416        self.generator.manual_seed(seed)417        result = self.inference(image=video,418                                prompt=prompt,419                                seed=seed,420                                output_type='numpy',421                                num_inference_steps=50,422                                image_guidance_scale=image_guidance_scale,423                                split_to_chunks=True,424                                chunk_size=chunk_size,425                                merging_ratio=merging_ratio426                                )427        return utils.create_video(result, fps, path=save_path, watermark=gradio_utils.logo_name_to_path(watermark))428 429    def process_text2video(self,430                           prompt,431                           model_name="dreamlike-art/dreamlike-photoreal-2.0",432                           motion_field_strength_x=12,433                           motion_field_strength_y=12,434                           t0=44,435                           t1=47,436                           n_prompt="",437                           chunk_size=2,438                           video_length=8,439                           watermark='Picsart AI Research',440                           merging_ratio=0.0,441                           seed=0,442                           resolution=512,443                           fps=2,444                           use_cf_attn=True,445                           use_motion_field=True,446                           smooth_bg=False,447                           smooth_bg_strength=0.4,448                           path=None):449        print("Module Text2Video")450        if self.model_type != ModelType.Text2Video or model_name != self.model_name:451            print("Model update")452            unet = UNet2DConditionModel.from_pretrained(453                model_name, subfolder="unet")454            self.set_model(ModelType.Text2Video,455                           model_id=model_name, unet=unet)456            self.pipe.scheduler = DDIMScheduler.from_config(457                self.pipe.scheduler.config)458            if use_cf_attn:459                self.pipe.unet.set_attn_processor(460                    processor=self.text2video_attn_proc)461        self.generator.manual_seed(seed)462 463        added_prompt = "high quality, HD, 8K, trending on artstation, high focus, dramatic lighting"464        negative_prompts = 'longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer difits, cropped, worst quality, low quality, deformed body, bloated, ugly, unrealistic'465 466        prompt = prompt.rstrip()467        if len(prompt) > 0 and (prompt[-1] == "," or prompt[-1] == "."):468            prompt = prompt.rstrip()[:-1]469        prompt = prompt.rstrip()470        prompt = prompt + ", "+added_prompt471        if len(n_prompt) > 0:472            negative_prompt = n_prompt473        else:474            negative_prompt = None475 476        result = self.inference(prompt=prompt,477                                video_length=video_length,478                                height=resolution,479                                width=resolution,480                                num_inference_steps=50,481                                guidance_scale=7.5,482                                guidance_stop_step=1.0,483                                t0=t0,484                                t1=t1,485                                motion_field_strength_x=motion_field_strength_x,486                                motion_field_strength_y=motion_field_strength_y,487                                use_motion_field=use_motion_field,488                                smooth_bg=smooth_bg,489                                smooth_bg_strength=smooth_bg_strength,490                                seed=seed,491                                output_type='numpy',492                                negative_prompt=negative_prompt,493                                merging_ratio=merging_ratio,494                                split_to_chunks=True,495                                chunk_size=chunk_size,496                                )497        return utils.create_video(result, fps, path=path, watermark=gradio_utils.logo_name_to_path(watermark))498