libcom 0.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- libcom/__init__.py +23 -0
- libcom/color_transfer/__init__.py +3 -0
- libcom/color_transfer/reinhard.py +57 -0
- libcom/fopa_heat_map/__init__.py +4 -0
- libcom/fopa_heat_map/fopa_heat_map.py +212 -0
- libcom/fopa_heat_map/source/__init__.py +0 -0
- libcom/fopa_heat_map/source/backbone/ResNet.py +229 -0
- libcom/fopa_heat_map/source/backbone/__init__.py +0 -0
- libcom/fopa_heat_map/source/data/OBdataset.py +292 -0
- libcom/fopa_heat_map/source/data/__init__.py +0 -0
- libcom/fopa_heat_map/source/data/all_transforms.py +25 -0
- libcom/fopa_heat_map/source/network/BaseBlocks.py +26 -0
- libcom/fopa_heat_map/source/network/DynamicModules.py +43 -0
- libcom/fopa_heat_map/source/network/ObPlaNet_simple.py +112 -0
- libcom/fopa_heat_map/source/network/__init__.py +1 -0
- libcom/fopa_heat_map/source/network/tensor_ops.py +37 -0
- libcom/fopa_heat_map/source/prepare_multi_fg_scales.py +85 -0
- libcom/fos_score/__init__.py +4 -0
- libcom/fos_score/fos_score_prediction.py +218 -0
- libcom/fos_score/source/__init__.py +0 -0
- libcom/fos_score/source/config/__init__.py +1 -0
- libcom/fos_score/source/config/config.py +68 -0
- libcom/fos_score/source/config/config.sfosd.yaml +43 -0
- libcom/fos_score/source/config/config_rfosd.yaml +43 -0
- libcom/fos_score/source/loss_function.py +118 -0
- libcom/fos_score/source/networks.py +355 -0
- libcom/harmony_score/__init__.py +3 -0
- libcom/harmony_score/harmony_score_prediction.py +119 -0
- libcom/harmony_score/source/__init__.py +0 -0
- libcom/harmony_score/source/bargainnet.py +226 -0
- libcom/image_harmonization/__init__.py +4 -0
- libcom/image_harmonization/image_harmonization.py +193 -0
- libcom/image_harmonization/source/__init__.py +0 -0
- libcom/image_harmonization/source/functions.py +747 -0
- libcom/image_harmonization/source/pct_net.py +85 -0
- libcom/image_harmonization/source/src/__init__.py +0 -0
- libcom/image_harmonization/source/src/lbm/__init__.py +0 -0
- libcom/image_harmonization/source/src/lbm/config.py +141 -0
- libcom/image_harmonization/source/src/lbm/data/__init__.py +62 -0
- libcom/image_harmonization/source/src/lbm/data/datasets/__init__.py +9 -0
- libcom/image_harmonization/source/src/lbm/data/datasets/collation_fn.py +41 -0
- libcom/image_harmonization/source/src/lbm/data/datasets/dataset.py +243 -0
- libcom/image_harmonization/source/src/lbm/data/datasets/datasets_config.py +42 -0
- libcom/image_harmonization/source/src/lbm/data/filters/__init__.py +12 -0
- libcom/image_harmonization/source/src/lbm/data/filters/base.py +21 -0
- libcom/image_harmonization/source/src/lbm/data/filters/filter_wrapper.py +36 -0
- libcom/image_harmonization/source/src/lbm/data/filters/filters.py +33 -0
- libcom/image_harmonization/source/src/lbm/data/filters/filters_config.py +32 -0
- libcom/image_harmonization/source/src/lbm/data/mappers/__init__.py +19 -0
- libcom/image_harmonization/source/src/lbm/data/mappers/base.py +26 -0
- libcom/image_harmonization/source/src/lbm/data/mappers/mappers.py +135 -0
- libcom/image_harmonization/source/src/lbm/data/mappers/mappers_config.py +109 -0
- libcom/image_harmonization/source/src/lbm/data/mappers/mappers_wrapper.py +31 -0
- libcom/image_harmonization/source/src/lbm/inference/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/inference/inference.py +70 -0
- libcom/image_harmonization/source/src/lbm/inference/utils.py +222 -0
- libcom/image_harmonization/source/src/lbm/models/__init__.py +0 -0
- libcom/image_harmonization/source/src/lbm/models/base/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/base/base_model.py +66 -0
- libcom/image_harmonization/source/src/lbm/models/base/model_config.py +8 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/base/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/base/base_conditioner.py +60 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/base/base_conditioner_config.py +27 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/conditioners_wrapper.py +114 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/latents_concat_embedder_config.py +31 -0
- libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/latents_concat_embedder_model.py +80 -0
- libcom/image_harmonization/source/src/lbm/models/lbm/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/lbm/lbm_config.py +101 -0
- libcom/image_harmonization/source/src/lbm/models/lbm/lbm_model.py +359 -0
- libcom/image_harmonization/source/src/lbm/models/unets/__init__.py +14 -0
- libcom/image_harmonization/source/src/lbm/models/unets/unet.py +148 -0
- libcom/image_harmonization/source/src/lbm/models/utils.py +377 -0
- libcom/image_harmonization/source/src/lbm/models/vae/__init__.py +4 -0
- libcom/image_harmonization/source/src/lbm/models/vae/autoencoderKL.py +136 -0
- libcom/image_harmonization/source/src/lbm/models/vae/autoencoderKL_config.py +27 -0
- libcom/image_harmonization/source/src/lbm/trainer/__init__.py +85 -0
- libcom/image_harmonization/source/src/lbm/trainer/loggers.py +324 -0
- libcom/image_harmonization/source/src/lbm/trainer/trainer.py +199 -0
- libcom/image_harmonization/source/src/lbm/trainer/training_config.py +82 -0
- libcom/image_harmonization/source/src/lbm/trainer/utils.py +193 -0
- libcom/inharmonious_region_localization/__init__.py +4 -0
- libcom/inharmonious_region_localization/inharmonious_region_localization.py +97 -0
- libcom/inharmonious_region_localization/source/__init__.py +0 -0
- libcom/inharmonious_region_localization/source/blocks.py +368 -0
- libcom/inharmonious_region_localization/source/functions.py +679 -0
- libcom/inharmonious_region_localization/source/madis_net.py +79 -0
- libcom/kontext_blending_harmonization/__init__.py +3 -0
- libcom/kontext_blending_harmonization/kontext_blending_harmonization.py +148 -0
- libcom/kontext_blending_harmonization/source/__init__.py +0 -0
- libcom/kontext_blending_harmonization/source/pipeline.py +1135 -0
- libcom/naive_composition/__init__.py +3 -0
- libcom/naive_composition/generate_composite_image.py +116 -0
- libcom/opa_score/__init__.py +3 -0
- libcom/opa_score/opa_score_prediction.py +101 -0
- libcom/opa_score/source/__init__.py +3 -0
- libcom/opa_score/source/object_place_net.py +55 -0
- libcom/opa_score/source/oblect_place_config.py +66 -0
- libcom/opa_score/source/resnet_4ch.py +213 -0
- libcom/os_insert/__init__.py +3 -0
- libcom/os_insert/diffusers_osinsert/__init__.py +78 -0
- libcom/os_insert/diffusers_osinsert/_patched_pipeline_flux_fill.py +878 -0
- libcom/os_insert/os_insert.py +534 -0
- libcom/os_insert/source/__init__.py +1 -0
- libcom/os_insert/source/ia_utils.py +183 -0
- libcom/os_insert/source/insertanything_infer.py +529 -0
- libcom/os_insert/source/ldm/__init__.py +0 -0
- libcom/os_insert/source/ldm/data/__init__.py +0 -0
- libcom/os_insert/source/ldm/data/base.py +23 -0
- libcom/os_insert/source/ldm/data/datamodule.py +128 -0
- libcom/os_insert/source/ldm/data/imagenet.py +394 -0
- libcom/os_insert/source/ldm/data/lsun.py +92 -0
- libcom/os_insert/source/ldm/data/open_images.py +728 -0
- libcom/os_insert/source/ldm/lr_scheduler.py +98 -0
- libcom/os_insert/source/ldm/models/__init__.py +0 -0
- libcom/os_insert/source/ldm/models/autoencoder.py +443 -0
- libcom/os_insert/source/ldm/models/diffusion/__init__.py +0 -0
- libcom/os_insert/source/ldm/models/diffusion/classifier.py +267 -0
- libcom/os_insert/source/ldm/models/diffusion/ddim.py +263 -0
- libcom/os_insert/source/ldm/models/diffusion/ddpm.py +1417 -0
- libcom/os_insert/source/ldm/models/diffusion/plms.py +252 -0
- libcom/os_insert/source/ldm/modules/__init__.py +0 -0
- libcom/os_insert/source/ldm/modules/attention.py +261 -0
- libcom/os_insert/source/ldm/modules/diffusionmodules/__init__.py +0 -0
- libcom/os_insert/source/ldm/modules/diffusionmodules/model.py +835 -0
- libcom/os_insert/source/ldm/modules/diffusionmodules/openaimodel.py +1108 -0
- libcom/os_insert/source/ldm/modules/diffusionmodules/util.py +267 -0
- libcom/os_insert/source/ldm/modules/distributions/__init__.py +0 -0
- libcom/os_insert/source/ldm/modules/distributions/distributions.py +92 -0
- libcom/os_insert/source/ldm/modules/ema.py +76 -0
- libcom/os_insert/source/ldm/modules/encoders/__init__.py +0 -0
- libcom/os_insert/source/ldm/modules/encoders/modules.py +190 -0
- libcom/os_insert/source/ldm/modules/encoders/xf.py +130 -0
- libcom/os_insert/source/ldm/modules/losses/__init__.py +1 -0
- libcom/os_insert/source/ldm/modules/losses/contperceptual.py +111 -0
- libcom/os_insert/source/ldm/modules/losses/vqperceptual.py +167 -0
- libcom/os_insert/source/ldm/modules/x_transformer.py +641 -0
- libcom/os_insert/source/ldm/util.py +203 -0
- libcom/os_insert/source/objectstitch_data.py +66 -0
- libcom/os_insert/source/objectstitch_infer.py +618 -0
- libcom/os_insert/source/sam_on_objectstitch.py +253 -0
- libcom/os_insert/source/utils.py +41 -0
- libcom/os_insert/source/v1.yaml +108 -0
- libcom/painterly_image_harmonization/__init__.py +4 -0
- libcom/painterly_image_harmonization/painterly_image_harmonization.py +215 -0
- libcom/painterly_image_harmonization/source/PHDNet/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDNet/networks.py +202 -0
- libcom/painterly_image_harmonization/source/PHDNet/phdnet.py +47 -0
- libcom/painterly_image_harmonization/source/PHDNet/phdnet_config.py +18 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/inference_base.py +300 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/lr_scheduler.py +98 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/autoencoder.py +211 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/__init__.py +3 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/ddim.py +336 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/ddpm.py +1400 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/dpm_solver.py +1217 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/plms.py +243 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/scheduling_pndm.py +518 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/attention.py +378 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/model.py +857 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/openaimodel.py +823 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/util.py +270 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/distributions/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/distributions/distributions.py +92 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/ema.py +80 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/adapter.py +213 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/modules.py +82 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/__init__.py +1 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/api.py +269 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/api.py +175 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/base_model.py +16 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/blocks.py +342 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/dpt_depth.py +109 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/midas_net.py +76 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/midas_net_custom.py +128 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/transforms.py +234 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/vit.py +491 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/utils.py +189 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/model_edge.py +653 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/api.py +35 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/body.py +209 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/hand.py +75 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/model.py +178 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/util.py +203 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/utils.py +72 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/fusion/__init__.py +0 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/fusion/dual_encoder_fusion.py +93 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/__init__.py +2 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/bsrgan.py +730 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/bsrgan_light.py +651 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/utils_image.py +916 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/ldm/util.py +200 -0
- libcom/painterly_image_harmonization/source/PHDiffusion/stable_diffusion.yaml +75 -0
- libcom/painterly_image_harmonization/source/__init__.py +0 -0
- libcom/reflection_generation/__init__.py +3 -0
- libcom/reflection_generation/reflection_generation.py +174 -0
- libcom/reflection_generation/source/PostProcessModel.py +513 -0
- libcom/reflection_generation/source/__init__.py +0 -0
- libcom/reflection_generation/source/cldm/__init__.py +0 -0
- libcom/reflection_generation/source/cldm/base_network.py +166 -0
- libcom/reflection_generation/source/cldm/cldm.py +509 -0
- libcom/reflection_generation/source/cldm/ddim_hacked.py +317 -0
- libcom/reflection_generation/source/cldm/hack.py +111 -0
- libcom/reflection_generation/source/cldm/logger.py +127 -0
- libcom/reflection_generation/source/cldm/model.py +26 -0
- libcom/reflection_generation/source/cldm_v15.yaml +81 -0
- libcom/reflection_generation/source/cluster_feature.py +109 -0
- libcom/reflection_generation/source/ldm/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/models/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/models/autoencoder.py +219 -0
- libcom/reflection_generation/source/ldm/models/diffusion/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/models/diffusion/attention_processor.py +188 -0
- libcom/reflection_generation/source/ldm/models/diffusion/ddim.py +340 -0
- libcom/reflection_generation/source/ldm/models/diffusion/ddpm.py +1892 -0
- libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
- libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/dpm_solver.py +1154 -0
- libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
- libcom/reflection_generation/source/ldm/models/diffusion/ip_adapter.py +57 -0
- libcom/reflection_generation/source/ldm/models/diffusion/plms.py +244 -0
- libcom/reflection_generation/source/ldm/models/diffusion/sampling_util.py +22 -0
- libcom/reflection_generation/source/ldm/modules/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/modules/attention.py +341 -0
- libcom/reflection_generation/source/ldm/modules/diffusionmodules/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/modules/diffusionmodules/model.py +852 -0
- libcom/reflection_generation/source/ldm/modules/diffusionmodules/openaimodel.py +786 -0
- libcom/reflection_generation/source/ldm/modules/diffusionmodules/upscaling.py +81 -0
- libcom/reflection_generation/source/ldm/modules/diffusionmodules/util.py +280 -0
- libcom/reflection_generation/source/ldm/modules/distributions/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/modules/distributions/distributions.py +92 -0
- libcom/reflection_generation/source/ldm/modules/ema.py +80 -0
- libcom/reflection_generation/source/ldm/modules/encoders/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/modules/encoders/modules.py +214 -0
- libcom/reflection_generation/source/ldm/modules/image_degradation/__init__.py +0 -0
- libcom/reflection_generation/source/ldm/modules/image_degradation/bsrgan.py +730 -0
- libcom/reflection_generation/source/ldm/modules/image_degradation/bsrgan_light.py +651 -0
- libcom/reflection_generation/source/ldm/modules/image_degradation/utils_image.py +916 -0
- libcom/reflection_generation/source/ldm/util.py +198 -0
- libcom/reflection_generation/source/local_clip.py +749 -0
- libcom/reflection_generation/source/tool_add_control.py +49 -0
- libcom/shadow_generation/__init__.py +3 -0
- libcom/shadow_generation/shadow_generation.py +754 -0
- libcom/shadow_generation/source/PostProcessModel.py +511 -0
- libcom/shadow_generation/source/__init__.py +0 -0
- libcom/shadow_generation/source/attention_processor.py +234 -0
- libcom/shadow_generation/source/cldm/__init__.py +0 -0
- libcom/shadow_generation/source/cldm/base_network.py +166 -0
- libcom/shadow_generation/source/cldm/cldm.py +524 -0
- libcom/shadow_generation/source/cldm/model.py +28 -0
- libcom/shadow_generation/source/ldm/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/models/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/models/autoencoder.py +219 -0
- libcom/shadow_generation/source/ldm/models/diffusion/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/models/diffusion/attention_processor.py +188 -0
- libcom/shadow_generation/source/ldm/models/diffusion/ddim.py +340 -0
- libcom/shadow_generation/source/ldm/models/diffusion/ddpm.py +1893 -0
- libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
- libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/dpm_solver.py +1154 -0
- libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
- libcom/shadow_generation/source/ldm/models/diffusion/ip_adapter.py +57 -0
- libcom/shadow_generation/source/ldm/models/diffusion/plms.py +244 -0
- libcom/shadow_generation/source/ldm/models/diffusion/sampling_util.py +22 -0
- libcom/shadow_generation/source/ldm/modules/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/attention.py +341 -0
- libcom/shadow_generation/source/ldm/modules/diffusionmodules/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/diffusionmodules/model.py +852 -0
- libcom/shadow_generation/source/ldm/modules/diffusionmodules/openaimodel.py +786 -0
- libcom/shadow_generation/source/ldm/modules/diffusionmodules/upscaling.py +81 -0
- libcom/shadow_generation/source/ldm/modules/diffusionmodules/util.py +270 -0
- libcom/shadow_generation/source/ldm/modules/distributions/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/distributions/distributions.py +92 -0
- libcom/shadow_generation/source/ldm/modules/ema.py +80 -0
- libcom/shadow_generation/source/ldm/modules/encoders/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/encoders/modules.py +214 -0
- libcom/shadow_generation/source/ldm/modules/image_degradation/__init__.py +2 -0
- libcom/shadow_generation/source/ldm/modules/image_degradation/bsrgan.py +730 -0
- libcom/shadow_generation/source/ldm/modules/image_degradation/bsrgan_light.py +651 -0
- libcom/shadow_generation/source/ldm/modules/image_degradation/utils_image.py +916 -0
- libcom/shadow_generation/source/ldm/modules/midas/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/midas/api.py +170 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/__init__.py +0 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/base_model.py +16 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/blocks.py +342 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/dpt_depth.py +109 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/midas_net.py +76 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/midas_net_custom.py +128 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/transforms.py +234 -0
- libcom/shadow_generation/source/ldm/modules/midas/midas/vit.py +491 -0
- libcom/shadow_generation/source/ldm/modules/midas/utils.py +189 -0
- libcom/shadow_generation/source/ldm/util.py +199 -0
- libcom/utils/__init__.py +0 -0
- libcom/utils/environment.py +12 -0
- libcom/utils/model_download.py +67 -0
- libcom/utils/process_image.py +108 -0
- libcom-0.1.8.dist-info/METADATA +157 -0
- libcom-0.1.8.dist-info/RECORD +310 -0
- libcom-0.1.8.dist-info/WHEEL +5 -0
- libcom-0.1.8.dist-info/licenses/LICENSE +201 -0
- libcom-0.1.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""SAM wrapper for ObjectStitch composites (skeleton).
|
|
2
|
+
|
|
3
|
+
This module provides a libcom-style home for running SAM on top of
|
|
4
|
+
ObjectStitch outputs, using a bbox prompt to focus on the insertion region.
|
|
5
|
+
|
|
6
|
+
The actual SAM model loading (segment-anything) will be implemented in a
|
|
7
|
+
later phase. For now only the public API is defined so that `OSInsertModel`
|
|
8
|
+
can depend on it.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
|
|
17
|
+
import cv2
|
|
18
|
+
import numpy as np
|
|
19
|
+
import torch
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
REPO_ROOT = Path(__file__).resolve().parents[3]
|
|
23
|
+
SAM_PRETRAINED_ROOT = REPO_ROOT / "pretrained_models" / "sam"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class SamOnObjectStitchConfig:
|
|
28
|
+
"""Configuration for SAM-on-ObjectStitch inference."""
|
|
29
|
+
|
|
30
|
+
sam_checkpoint: Path | str = SAM_PRETRAINED_ROOT / "sam_vit_h_4b8939.pth"
|
|
31
|
+
model_type: str = "vit_h"
|
|
32
|
+
device: str = "cuda:0"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _run_sam_on_image(predictor, image_bgr: np.ndarray, box_xyxy: Tuple[int, int, int, int]) -> np.ndarray:
|
|
36
|
+
"""Run SAM with a box prompt and return a binary mask (uint8 0/255).
|
|
37
|
+
|
|
38
|
+
Ported from `run_sam_on_objectstitch.py::run_sam_on_image`.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
image = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
|
|
42
|
+
predictor.set_image(image)
|
|
43
|
+
|
|
44
|
+
box = np.array(box_xyxy, dtype=np.float32)
|
|
45
|
+
masks, scores, _ = predictor.predict(
|
|
46
|
+
point_coords=None,
|
|
47
|
+
point_labels=None,
|
|
48
|
+
box=box[None, :],
|
|
49
|
+
multimask_output=True,
|
|
50
|
+
)
|
|
51
|
+
if masks is None or len(masks) == 0:
|
|
52
|
+
raise RuntimeError("SAM returned no masks")
|
|
53
|
+
|
|
54
|
+
best_idx = int(np.argmax(scores))
|
|
55
|
+
m = masks[best_idx].astype(np.uint8)
|
|
56
|
+
|
|
57
|
+
x1, y1, x2, y2 = box_xyxy
|
|
58
|
+
box_w = max(int(x2 - x1), 1)
|
|
59
|
+
box_h = max(int(y2 - y1), 1)
|
|
60
|
+
box_area = float(box_w * box_h)
|
|
61
|
+
area = float(int(m.sum()))
|
|
62
|
+
if area / box_area < 0.01:
|
|
63
|
+
raise RuntimeError("SAM mask area too small")
|
|
64
|
+
|
|
65
|
+
m = m.astype(np.uint8) * 255
|
|
66
|
+
return m
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def run_sam_on_objectstitch_single(
|
|
70
|
+
os_image_path: Path,
|
|
71
|
+
bg_shape_hw: Tuple[int, int],
|
|
72
|
+
bbox_xyxy_bg: Tuple[int, int, int, int],
|
|
73
|
+
*,
|
|
74
|
+
config: SamOnObjectStitchConfig,
|
|
75
|
+
out_path: Path | None = None,
|
|
76
|
+
) -> Path:
|
|
77
|
+
"""Run SAM on a single ObjectStitch composite and return a binary mask path.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
os_image_path:
|
|
82
|
+
Path to the ObjectStitch composite image (BGR when read by OpenCV).
|
|
83
|
+
bg_shape_hw:
|
|
84
|
+
Original background image shape as (H, W). The bbox is defined in this
|
|
85
|
+
coordinate system.
|
|
86
|
+
bbox_xyxy_bg:
|
|
87
|
+
Bbox (x1, y1, x2, y2) in the original background coordinates.
|
|
88
|
+
config:
|
|
89
|
+
SAM configuration including checkpoint and device.
|
|
90
|
+
out_path:
|
|
91
|
+
Optional output path for the SAM mask PNG. If None, will create a
|
|
92
|
+
sibling file next to the ObjectStitch input with suffix `_sam_mask.png`.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
os_image_path = Path(os_image_path)
|
|
96
|
+
if out_path is None:
|
|
97
|
+
out_path = os_image_path.with_name(os_image_path.stem + "_sam_mask.png")
|
|
98
|
+
out_path = Path(out_path)
|
|
99
|
+
|
|
100
|
+
if not os_image_path.exists():
|
|
101
|
+
raise FileNotFoundError(os_image_path)
|
|
102
|
+
if not config.sam_checkpoint.exists():
|
|
103
|
+
raise FileNotFoundError(
|
|
104
|
+
f"SAM checkpoint not found: {config.sam_checkpoint}. "
|
|
105
|
+
f"Expected at {SAM_PRETRAINED_ROOT}."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
os_image_bgr = cv2.imread(str(os_image_path))
|
|
109
|
+
if os_image_bgr is None:
|
|
110
|
+
raise RuntimeError(f"Failed to read ObjectStitch image: {os_image_path}")
|
|
111
|
+
|
|
112
|
+
os_h, os_w = os_image_bgr.shape[:2]
|
|
113
|
+
bg_h, bg_w = bg_shape_hw
|
|
114
|
+
|
|
115
|
+
bx1, by1, bx2, by2 = bbox_xyxy_bg
|
|
116
|
+
|
|
117
|
+
scale_x = os_w / float(bg_w) if bg_w > 0 else 1.0
|
|
118
|
+
scale_y = os_h / float(bg_h) if bg_h > 0 else 1.0
|
|
119
|
+
|
|
120
|
+
x1 = int(bx1 * scale_x)
|
|
121
|
+
y1 = int(by1 * scale_y)
|
|
122
|
+
x2 = int(bx2 * scale_x)
|
|
123
|
+
y2 = int(by2 * scale_y)
|
|
124
|
+
|
|
125
|
+
x1 = max(0, min(x1, os_w - 1))
|
|
126
|
+
y1 = max(0, min(y1, os_h - 1))
|
|
127
|
+
x2 = max(x1 + 1, min(x2, os_w))
|
|
128
|
+
y2 = max(y1 + 1, min(y2, os_h))
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
from segment_anything import SamPredictor, sam_model_registry
|
|
132
|
+
except ImportError as e:
|
|
133
|
+
raise ImportError(
|
|
134
|
+
"segment_anything package is required for SAM aggressive mode. "
|
|
135
|
+
"Install from https://github.com/facebookresearch/segment-anything"
|
|
136
|
+
) from e
|
|
137
|
+
|
|
138
|
+
sam = sam_model_registry[config.model_type](checkpoint=str(config.sam_checkpoint))
|
|
139
|
+
sam.to(device=config.device)
|
|
140
|
+
predictor = SamPredictor(sam)
|
|
141
|
+
|
|
142
|
+
os_mask = _run_sam_on_image(predictor, os_image_bgr, (x1, y1, x2, y2))
|
|
143
|
+
cv2.imwrite(str(out_path), os_mask)
|
|
144
|
+
|
|
145
|
+
return out_path
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def run_sam_on_objectstitch(
|
|
149
|
+
os_image: np.ndarray,
|
|
150
|
+
bg_shape_hw: Tuple[int, int],
|
|
151
|
+
bbox_xyxy_bg: Tuple[int, int, int, int],
|
|
152
|
+
*,
|
|
153
|
+
config: SamOnObjectStitchConfig,
|
|
154
|
+
) -> np.ndarray:
|
|
155
|
+
os_image_bgr = os_image
|
|
156
|
+
if os_image_bgr.ndim != 3 or os_image_bgr.shape[2] != 3:
|
|
157
|
+
raise ValueError("Expected HxWx3 image")
|
|
158
|
+
|
|
159
|
+
os_h, os_w = os_image_bgr.shape[:2]
|
|
160
|
+
bg_h, bg_w = bg_shape_hw
|
|
161
|
+
|
|
162
|
+
bx1, by1, bx2, by2 = bbox_xyxy_bg
|
|
163
|
+
|
|
164
|
+
scale_x = os_w / float(bg_w) if bg_w > 0 else 1.0
|
|
165
|
+
scale_y = os_h / float(bg_h) if bg_h > 0 else 1.0
|
|
166
|
+
|
|
167
|
+
x1 = int(bx1 * scale_x)
|
|
168
|
+
y1 = int(by1 * scale_y)
|
|
169
|
+
x2 = int(bx2 * scale_x)
|
|
170
|
+
y2 = int(by2 * scale_y)
|
|
171
|
+
|
|
172
|
+
x1 = max(0, min(x1, os_w - 1))
|
|
173
|
+
y1 = max(0, min(y1, os_h - 1))
|
|
174
|
+
x2 = max(x1 + 1, min(x2, os_w))
|
|
175
|
+
y2 = max(y1 + 1, min(y2, os_h))
|
|
176
|
+
|
|
177
|
+
if not config.sam_checkpoint.exists():
|
|
178
|
+
raise FileNotFoundError(
|
|
179
|
+
f"SAM checkpoint not found: {config.sam_checkpoint}. "
|
|
180
|
+
f"Expected at {SAM_PRETRAINED_ROOT}."
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
from segment_anything import SamPredictor, sam_model_registry
|
|
185
|
+
except ImportError as e:
|
|
186
|
+
raise ImportError(
|
|
187
|
+
"segment_anything package is required for SAM aggressive mode. "
|
|
188
|
+
"Install from https://github.com/facebookresearch/segment-anything"
|
|
189
|
+
) from e
|
|
190
|
+
|
|
191
|
+
sam = sam_model_registry[config.model_type](checkpoint=str(config.sam_checkpoint))
|
|
192
|
+
sam.to(device=config.device)
|
|
193
|
+
predictor = SamPredictor(sam)
|
|
194
|
+
|
|
195
|
+
return _run_sam_on_image(predictor, os_image_bgr, (x1, y1, x2, y2))
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def build_sam_predictor(*, config: SamOnObjectStitchConfig):
|
|
199
|
+
# 检查 sam_checkpoint 是本地路径还是 HuggingFace 模型 ID
|
|
200
|
+
if isinstance(config.sam_checkpoint, Path):
|
|
201
|
+
if not config.sam_checkpoint.exists():
|
|
202
|
+
raise FileNotFoundError(
|
|
203
|
+
f"SAM checkpoint not found: {config.sam_checkpoint}. "
|
|
204
|
+
f"Expected at {SAM_PRETRAINED_ROOT}."
|
|
205
|
+
)
|
|
206
|
+
sam_checkpoint = str(config.sam_checkpoint)
|
|
207
|
+
else:
|
|
208
|
+
# 如果是字符串,可能是 HuggingFace 模型 ID,直接使用
|
|
209
|
+
sam_checkpoint = config.sam_checkpoint
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
from segment_anything import SamPredictor, sam_model_registry
|
|
213
|
+
except ImportError as e:
|
|
214
|
+
raise ImportError(
|
|
215
|
+
"segment_anything package is required for SAM aggressive mode. "
|
|
216
|
+
"Install from https://github.com/facebookresearch/segment-anything"
|
|
217
|
+
) from e
|
|
218
|
+
|
|
219
|
+
sam = sam_model_registry[config.model_type](checkpoint=sam_checkpoint)
|
|
220
|
+
sam.to(device=config.device)
|
|
221
|
+
return SamPredictor(sam)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def run_sam_on_objectstitch_with_predictor(
|
|
225
|
+
*,
|
|
226
|
+
predictor,
|
|
227
|
+
os_image: np.ndarray,
|
|
228
|
+
bg_shape_hw: Tuple[int, int],
|
|
229
|
+
bbox_xyxy_bg: Tuple[int, int, int, int],
|
|
230
|
+
) -> np.ndarray:
|
|
231
|
+
os_image_bgr = os_image
|
|
232
|
+
if os_image_bgr.ndim != 3 or os_image_bgr.shape[2] != 3:
|
|
233
|
+
raise ValueError("Expected HxWx3 image")
|
|
234
|
+
|
|
235
|
+
os_h, os_w = os_image_bgr.shape[:2]
|
|
236
|
+
bg_h, bg_w = bg_shape_hw
|
|
237
|
+
|
|
238
|
+
bx1, by1, bx2, by2 = bbox_xyxy_bg
|
|
239
|
+
|
|
240
|
+
scale_x = os_w / float(bg_w) if bg_w > 0 else 1.0
|
|
241
|
+
scale_y = os_h / float(bg_h) if bg_h > 0 else 1.0
|
|
242
|
+
|
|
243
|
+
x1 = int(bx1 * scale_x)
|
|
244
|
+
y1 = int(by1 * scale_y)
|
|
245
|
+
x2 = int(bx2 * scale_x)
|
|
246
|
+
y2 = int(by2 * scale_y)
|
|
247
|
+
|
|
248
|
+
x1 = max(0, min(x1, os_w - 1))
|
|
249
|
+
y1 = max(0, min(y1, os_h - 1))
|
|
250
|
+
x2 = max(x1 + 1, min(x2, os_w))
|
|
251
|
+
y2 = max(y1 + 1, min(y2, os_h))
|
|
252
|
+
|
|
253
|
+
return _run_sam_on_image(predictor, os_image_bgr, (x1, y1, x2, y2))
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Shared utility functions for OSInsert."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Tuple
|
|
7
|
+
|
|
8
|
+
import cv2
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def load_bbox_txt(path: str | Path) -> Tuple[int, int, int, int]:
|
|
13
|
+
"""Load a simple `x1 y1 x2 y2` bbox txt file."""
|
|
14
|
+
path = Path(path)
|
|
15
|
+
with path.open("r") as f:
|
|
16
|
+
line = f.readline().strip()
|
|
17
|
+
x1, y1, x2, y2 = map(int, line.split())
|
|
18
|
+
return x1, y1, x2, y2
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def make_rect_mask_from_bbox(h: int, w: int, bbox: Tuple[int, int, int, int]) -> np.ndarray:
|
|
22
|
+
"""Create a uint8 mask (0/255) from bbox coordinates."""
|
|
23
|
+
x1, y1, x2, y2 = bbox
|
|
24
|
+
x1 = max(0, min(w - 1, x1))
|
|
25
|
+
x2 = max(0, min(w, x2))
|
|
26
|
+
y1 = max(0, min(h - 1, y1))
|
|
27
|
+
y2 = max(0, min(h, y2))
|
|
28
|
+
if x2 <= x1 or y2 <= y1:
|
|
29
|
+
raise ValueError("degenerate bbox")
|
|
30
|
+
|
|
31
|
+
mask = np.zeros((h, w), dtype=np.uint8)
|
|
32
|
+
mask[y1:y2, x1:x2] = 255
|
|
33
|
+
return mask
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def read_image_bgr(path: str | Path) -> np.ndarray:
|
|
37
|
+
path = Path(path)
|
|
38
|
+
img = cv2.imread(str(path))
|
|
39
|
+
if img is None:
|
|
40
|
+
raise FileNotFoundError(path)
|
|
41
|
+
return img
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
model:
|
|
2
|
+
base_learning_rate: 1.0e-05
|
|
3
|
+
target: libcom.os_insert.source.ldm.models.diffusion.ddpm.LatentDiffusion
|
|
4
|
+
params:
|
|
5
|
+
linear_start: 0.00085
|
|
6
|
+
linear_end: 0.0120
|
|
7
|
+
num_timesteps_cond: 1
|
|
8
|
+
log_every_t: 200
|
|
9
|
+
timesteps: 1000
|
|
10
|
+
first_stage_key: "composition"
|
|
11
|
+
cond_stage_key: "image"
|
|
12
|
+
image_size: 64
|
|
13
|
+
channels: 4
|
|
14
|
+
cond_stage_trainable: False # Note: different from the one we trained before
|
|
15
|
+
conditioning_key: crossattn
|
|
16
|
+
monitor: val/loss_simple_ema
|
|
17
|
+
scale_factor: 0.18215
|
|
18
|
+
use_ema: False
|
|
19
|
+
u_cond_percent: 0.2
|
|
20
|
+
|
|
21
|
+
scheduler_config: # 10000 warmup steps
|
|
22
|
+
target: libcom.os_insert.source.ldm.lr_scheduler.LambdaLinearScheduler
|
|
23
|
+
params:
|
|
24
|
+
warm_up_steps: [ 1000 ]
|
|
25
|
+
cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
|
|
26
|
+
f_start: [ 1.e-6 ]
|
|
27
|
+
f_max: [ 1. ]
|
|
28
|
+
f_min: [ 1. ]
|
|
29
|
+
|
|
30
|
+
unet_config:
|
|
31
|
+
target: libcom.os_insert.source.ldm.modules.diffusionmodules.openaimodel.UNetModel
|
|
32
|
+
params:
|
|
33
|
+
image_size: 32 # unused
|
|
34
|
+
in_channels: 9
|
|
35
|
+
out_channels: 4
|
|
36
|
+
model_channels: 320
|
|
37
|
+
attention_resolutions: [ 4, 2, 1 ]
|
|
38
|
+
num_res_blocks: 2
|
|
39
|
+
channel_mult: [ 1, 2, 4, 4 ]
|
|
40
|
+
num_heads: 8
|
|
41
|
+
use_spatial_transformer: True
|
|
42
|
+
transformer_depth: 1
|
|
43
|
+
context_dim: 768
|
|
44
|
+
use_checkpoint: True
|
|
45
|
+
legacy: False
|
|
46
|
+
add_conv_in_front_of_unet: False
|
|
47
|
+
|
|
48
|
+
first_stage_config:
|
|
49
|
+
target: libcom.os_insert.source.ldm.models.autoencoder.AutoencoderKL
|
|
50
|
+
params:
|
|
51
|
+
embed_dim: 4
|
|
52
|
+
monitor: val/rec_loss
|
|
53
|
+
ddconfig:
|
|
54
|
+
double_z: true
|
|
55
|
+
z_channels: 4
|
|
56
|
+
resolution: 512
|
|
57
|
+
in_channels: 3
|
|
58
|
+
out_ch: 3
|
|
59
|
+
ch: 128
|
|
60
|
+
ch_mult:
|
|
61
|
+
- 1
|
|
62
|
+
- 2
|
|
63
|
+
- 4
|
|
64
|
+
- 4
|
|
65
|
+
num_res_blocks: 2
|
|
66
|
+
attn_resolutions: []
|
|
67
|
+
dropout: 0.0
|
|
68
|
+
lossconfig:
|
|
69
|
+
target: torch.nn.Identity
|
|
70
|
+
|
|
71
|
+
cond_stage_config:
|
|
72
|
+
target: libcom.os_insert.source.ldm.modules.encoders.modules.FrozenCLIPImageEmbedder
|
|
73
|
+
params:
|
|
74
|
+
version: openai-clip-vit-large-patch14
|
|
75
|
+
|
|
76
|
+
data:
|
|
77
|
+
target: libcom.os_insert.source.ldm.data.datamodule.DataModuleFromConfig
|
|
78
|
+
dataset_dir: &dataset_dir path-to-openimages
|
|
79
|
+
params:
|
|
80
|
+
batch_size: 16
|
|
81
|
+
num_workers: 16
|
|
82
|
+
wrap: False
|
|
83
|
+
train:
|
|
84
|
+
target: libcom.os_insert.source.ldm.data.open_images.OpenImageDataset
|
|
85
|
+
params:
|
|
86
|
+
split: train
|
|
87
|
+
dataset_dir: *dataset_dir
|
|
88
|
+
image_size: 512
|
|
89
|
+
validation:
|
|
90
|
+
target: libcom.os_insert.source.ldm.data.open_images.COCOEEDataset
|
|
91
|
+
params:
|
|
92
|
+
split: test
|
|
93
|
+
dataset_dir: path-to-cocoee
|
|
94
|
+
image_size: 512
|
|
95
|
+
test:
|
|
96
|
+
target: libcom.os_insert.source.ldm.data.open_images.OpenImageDataset
|
|
97
|
+
params:
|
|
98
|
+
split: validation
|
|
99
|
+
dataset_dir: *dataset_dir
|
|
100
|
+
image_size: 512
|
|
101
|
+
|
|
102
|
+
lightning:
|
|
103
|
+
trainer:
|
|
104
|
+
max_epochs: 40
|
|
105
|
+
accelerator: gpu
|
|
106
|
+
devices: 8
|
|
107
|
+
num_nodes: 1
|
|
108
|
+
val_check_interval: 1.0
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torchvision
|
|
3
|
+
from libcom.utils.model_download import download_pretrained_model, download_entire_folder
|
|
4
|
+
from libcom.utils.process_image import *
|
|
5
|
+
from libcom.utils.environment import *
|
|
6
|
+
import torch
|
|
7
|
+
import torch.nn.functional as F
|
|
8
|
+
import os
|
|
9
|
+
import torchvision.transforms as transforms
|
|
10
|
+
from tqdm.auto import tqdm
|
|
11
|
+
from pytorch_lightning import seed_everything
|
|
12
|
+
from omegaconf import OmegaConf
|
|
13
|
+
from PIL import Image
|
|
14
|
+
import torchvision.transforms.functional as tf
|
|
15
|
+
from .source.PHDNet.phdnet import PHDNet
|
|
16
|
+
from .source.PHDiffusion.ldm.modules.encoders.adapter import Adapter,NoRes_Adapter
|
|
17
|
+
from .source.PHDiffusion.ldm.models.diffusion.scheduling_pndm import PNDMScheduler
|
|
18
|
+
from .source.PHDiffusion.ldm.util import instantiate_from_config
|
|
19
|
+
import logging
|
|
20
|
+
logging.getLogger('transformers').setLevel(logging.ERROR) # disable transformer lib warning
|
|
21
|
+
|
|
22
|
+
cur_dir = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
model_dir = os.environ.get('LIBCOM_MODEL_DIR',cur_dir)
|
|
24
|
+
model_set = ['PHDNet', 'PHDiffusion']
|
|
25
|
+
|
|
26
|
+
class PainterlyHarmonizationModel:
|
|
27
|
+
"""
|
|
28
|
+
Painterly image harmonization prediction model.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
device (str | torch.device): gpu id
|
|
32
|
+
model_type (str): predefined model type
|
|
33
|
+
kwargs (dict): use_residual (bool): whether to use adapter with residual or not for PHDiffusion
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
>>> from libcom.utils.process_image import make_image_grid
|
|
37
|
+
>>> from libcom import PainterlyHarmonizationModel
|
|
38
|
+
>>> import cv2
|
|
39
|
+
>>> import torch
|
|
40
|
+
>>> task_name = 'painterly_image_harmonization'
|
|
41
|
+
>>> MODEL_TYPE = 'PHDNet' # choose from 'PHDNet', 'PHDiffusion'
|
|
42
|
+
>>> comp_img = '../tests/painterly_harmonization_source/composite/3.png'
|
|
43
|
+
>>> comp_mask = '../tests/painterly_harmonization_source/composite_mask/3.png'
|
|
44
|
+
>>> net = PainterlyHarmonizationModel(device=0, model_type=MODEL_TYPE)
|
|
45
|
+
>>> output_img = net(comp_img, comp_mask)
|
|
46
|
+
>>> grid_img = make_image_grid([comp_img, comp_mask, output_img])
|
|
47
|
+
>>> cv2.imshow('painterly_image_harmonization_demo', grid_img)
|
|
48
|
+
|
|
49
|
+
Expected result:
|
|
50
|
+
|
|
51
|
+
.. image:: _static/image/painterly_image_harmonization_result2.jpg
|
|
52
|
+
.. image:: _static/image/painterly_image_harmonization_result3.jpg
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
def __init__(self, device=0, model_type='PHDNet', **kwargs):
|
|
56
|
+
assert model_type in model_set, f'Not implementation for {model_type}'
|
|
57
|
+
self.model_type = model_type
|
|
58
|
+
self.option = kwargs
|
|
59
|
+
|
|
60
|
+
if model_type == 'PHDNet':
|
|
61
|
+
weight_path = os.path.join(model_dir, 'pretrained_models', model_type + '.pth')
|
|
62
|
+
self.device = check_gpu_device(device)
|
|
63
|
+
download_pretrained_model(weight_path)
|
|
64
|
+
self.build_pretrained_model(weight_path)
|
|
65
|
+
elif model_type == 'PHDiffusion':
|
|
66
|
+
self.use_residual = self.option.get('use_residual', True)
|
|
67
|
+
if self.use_residual:
|
|
68
|
+
phdiff_weight_path = os.path.join(model_dir, 'pretrained_models', model_type+'WithRes.pth')
|
|
69
|
+
else:
|
|
70
|
+
phdiff_weight_path = os.path.join(model_dir, 'pretrained_models', model_type+'.pth')
|
|
71
|
+
sd_weight_path = os.path.join(model_dir, '../shared_pretrained_models', 'sd-v1-4.ckpt')
|
|
72
|
+
download_pretrained_model(sd_weight_path)
|
|
73
|
+
download_pretrained_model(phdiff_weight_path)
|
|
74
|
+
self.device = check_gpu_device(device)
|
|
75
|
+
self.build_pretrained_model(sd_weight_path, phdiff_weight_path)
|
|
76
|
+
self.build_data_transformer()
|
|
77
|
+
|
|
78
|
+
def build_pretrained_model(self, *weight_path):
|
|
79
|
+
if len(weight_path) == 1:
|
|
80
|
+
weight_path = weight_path[0]
|
|
81
|
+
# build PHDNet
|
|
82
|
+
assert self.model_type == 'PHDNet', self.model_type
|
|
83
|
+
model = PHDNet(self.device)
|
|
84
|
+
model.load_networks(weight_path)
|
|
85
|
+
self.model = model.to(self.device).eval()
|
|
86
|
+
elif len(weight_path) == 2:
|
|
87
|
+
# build PHDiffusion model
|
|
88
|
+
sd_weight_path, phdiff_weight_path = weight_path
|
|
89
|
+
assert self.model_type == 'PHDiffusion', self.model_type
|
|
90
|
+
self.config= OmegaConf.load(cur_dir+'/source/PHDiffusion/stable_diffusion.yaml')
|
|
91
|
+
self.config.model.params.cond_stage_config.params.model_path = "openai/clip-vit-large-patch14"
|
|
92
|
+
pl_sd = torch.load(sd_weight_path, map_location="cpu", weights_only=False)
|
|
93
|
+
sd = pl_sd["state_dict"]
|
|
94
|
+
model = instantiate_from_config(self.config.model)
|
|
95
|
+
model.load_state_dict(sd, strict=False)
|
|
96
|
+
|
|
97
|
+
if self.use_residual:
|
|
98
|
+
adapter=Adapter(cin=int(64 * 4), channels=[320, 640, 1280, 1280][:4], nums_rb=2, ksize=1, sk=True, use_conv=False)
|
|
99
|
+
else:
|
|
100
|
+
adapter=NoRes_Adapter(cin=int(64 * 4), channels=[320, 640, 1280, 1280][:4], nums_rb=2, ksize=1, sk=True, use_conv=False)
|
|
101
|
+
model_resume_state = torch.load(phdiff_weight_path, map_location='cpu')
|
|
102
|
+
adapter.load_state_dict(model_resume_state['ad'])
|
|
103
|
+
model.model.diffusion_model.interact_blocks.load_state_dict(model_resume_state['interact'])
|
|
104
|
+
|
|
105
|
+
self.model = model.to(self.device).eval()
|
|
106
|
+
self.adapter = adapter.to(self.device).eval()
|
|
107
|
+
|
|
108
|
+
self.scheduler = PNDMScheduler(
|
|
109
|
+
beta_end=0.012,
|
|
110
|
+
beta_schedule='scaled_linear',
|
|
111
|
+
beta_start=0.00085,
|
|
112
|
+
num_train_timesteps=1000,
|
|
113
|
+
set_alpha_to_one=False,
|
|
114
|
+
skip_prk_steps=True,
|
|
115
|
+
steps_offset=1,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def build_data_transformer(self):
|
|
119
|
+
self.image_size = 512
|
|
120
|
+
self.transformer = transforms.Compose([
|
|
121
|
+
transforms.Resize((self.image_size, self.image_size)),
|
|
122
|
+
transforms.ToTensor(),
|
|
123
|
+
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
|
|
124
|
+
])
|
|
125
|
+
self.mask_transform = transforms.Compose([
|
|
126
|
+
transforms.Resize((self.image_size, self.image_size)),
|
|
127
|
+
transforms.ToTensor(),
|
|
128
|
+
])
|
|
129
|
+
|
|
130
|
+
def inputs_preprocess(self, composite_image, composite_mask):
|
|
131
|
+
img = read_image_pil(composite_image)
|
|
132
|
+
img = self.transformer(img)
|
|
133
|
+
mask = read_mask_pil(composite_mask).convert('L')
|
|
134
|
+
mask = self.mask_transform(mask)
|
|
135
|
+
if self.model_type == 'PHDiffusion':
|
|
136
|
+
img = img.unsqueeze(0).to(self.device)
|
|
137
|
+
mask = mask.unsqueeze(0).to(self.device)
|
|
138
|
+
return img, mask
|
|
139
|
+
|
|
140
|
+
def outputs_postprocess(self, outputs):
|
|
141
|
+
if outputs.dim() == 4:
|
|
142
|
+
outputs = outputs.squeeze(0)
|
|
143
|
+
outputs = (torch.clamp((outputs.permute(1, 2, 0) + 1) / 2.0 * 255, 0, 255)).cpu().numpy()
|
|
144
|
+
outputs = outputs.astype(np.uint8)
|
|
145
|
+
outputs = cv2.cvtColor(outputs, cv2.COLOR_RGB2BGR)
|
|
146
|
+
return outputs
|
|
147
|
+
|
|
148
|
+
@torch.no_grad()
|
|
149
|
+
def PHDNet_inference(self, composite_image, composite_mask):
|
|
150
|
+
comp, mask = self.inputs_preprocess(composite_image, composite_mask)
|
|
151
|
+
outputs = self.model(comp, mask)
|
|
152
|
+
preds = self.outputs_postprocess(outputs)
|
|
153
|
+
return preds
|
|
154
|
+
|
|
155
|
+
@torch.no_grad()
|
|
156
|
+
def __call__(self, composite_image, composite_mask, sample_steps=50, strength=0.7, random_seed=None):
|
|
157
|
+
"""
|
|
158
|
+
Generating the harmonized image for the given composite image and the corresponding composite mask.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
composite_image (str | numpy.ndarray): The path to the composite image or the composite image in ndarray form.
|
|
162
|
+
composite_mask (str | numpy.ndarray): The path to the composite mask or the composite mask in ndarray form.
|
|
163
|
+
sample_steps (int): Default total step in the inference process of PHDiffusion.
|
|
164
|
+
strength (float): A hyper-parameter that decides the total step (strength * sample_steps) for PHDiffusion.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
preds (numpy.ndarray): Generated harmonized image for the given composite image and the corresponding composite mask, with BGR channel.
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
if self.model_type == 'PHDNet':
|
|
171
|
+
return self.PHDNet_inference(composite_image, composite_mask)
|
|
172
|
+
if random_seed != None:
|
|
173
|
+
seed_everything(random_seed)
|
|
174
|
+
comp, mask = self.inputs_preprocess(composite_image, composite_mask)
|
|
175
|
+
self.scheduler.set_timesteps(sample_steps, device=self.device)
|
|
176
|
+
init_timestep = min(int(sample_steps * strength), sample_steps)
|
|
177
|
+
t_start = max(sample_steps - init_timestep, 0)
|
|
178
|
+
timesteps = self.scheduler.timesteps[t_start:]
|
|
179
|
+
|
|
180
|
+
c = self.model.get_learned_conditioning([''])
|
|
181
|
+
batch_size = mask.shape[0]
|
|
182
|
+
latent_timestep = timesteps[:1].repeat(batch_size)
|
|
183
|
+
|
|
184
|
+
x_0 = self.model.encode_first_stage(comp)
|
|
185
|
+
x_0 = self.model.get_first_stage_encoding(x_0)
|
|
186
|
+
mask_latents = F.interpolate(mask, size=x_0.shape[-2:])
|
|
187
|
+
noise = torch.randn(x_0.shape, device=x_0.device, dtype=x_0.dtype)
|
|
188
|
+
latents = self.scheduler.add_noise(x_0, noise, latent_timestep)
|
|
189
|
+
|
|
190
|
+
adapter_input = torch.cat((comp, mask), dim=1).to(dtype=comp.dtype)
|
|
191
|
+
features_adapter = self.adapter(adapter_input)
|
|
192
|
+
|
|
193
|
+
for i, t in enumerate(timesteps):
|
|
194
|
+
# expand the latents if we are doing classifier free guidance
|
|
195
|
+
noise = torch.randn(x_0.shape, device=x_0.device, dtype=x_0.dtype)
|
|
196
|
+
t_latents = self.scheduler.add_noise(x_0, noise, t)
|
|
197
|
+
latents = latents * mask_latents + t_latents * (1 - mask_latents)
|
|
198
|
+
|
|
199
|
+
latent_model_input = latents
|
|
200
|
+
latent_model_input = self.scheduler.scale_model_input(latent_model_input, t)
|
|
201
|
+
|
|
202
|
+
# predict the noise residual
|
|
203
|
+
noise_pred = self.model.model.diffusion_model(x=latent_model_input,
|
|
204
|
+
fg_mask=mask_latents,
|
|
205
|
+
timesteps=t.repeat(batch_size),
|
|
206
|
+
context=c,
|
|
207
|
+
features_adapter=features_adapter)
|
|
208
|
+
|
|
209
|
+
# compute the previous noisy sample x_t -> x_t-1
|
|
210
|
+
latents = self.scheduler.step(noise_pred, t, latents).prev_sample
|
|
211
|
+
|
|
212
|
+
x_samples_ddim = self.model.decode_first_stage(latents)
|
|
213
|
+
preds = self.outputs_postprocess(x_samples_ddim)
|
|
214
|
+
return preds
|
|
215
|
+
|
|
File without changes
|