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.
Files changed (310) hide show
  1. libcom/__init__.py +23 -0
  2. libcom/color_transfer/__init__.py +3 -0
  3. libcom/color_transfer/reinhard.py +57 -0
  4. libcom/fopa_heat_map/__init__.py +4 -0
  5. libcom/fopa_heat_map/fopa_heat_map.py +212 -0
  6. libcom/fopa_heat_map/source/__init__.py +0 -0
  7. libcom/fopa_heat_map/source/backbone/ResNet.py +229 -0
  8. libcom/fopa_heat_map/source/backbone/__init__.py +0 -0
  9. libcom/fopa_heat_map/source/data/OBdataset.py +292 -0
  10. libcom/fopa_heat_map/source/data/__init__.py +0 -0
  11. libcom/fopa_heat_map/source/data/all_transforms.py +25 -0
  12. libcom/fopa_heat_map/source/network/BaseBlocks.py +26 -0
  13. libcom/fopa_heat_map/source/network/DynamicModules.py +43 -0
  14. libcom/fopa_heat_map/source/network/ObPlaNet_simple.py +112 -0
  15. libcom/fopa_heat_map/source/network/__init__.py +1 -0
  16. libcom/fopa_heat_map/source/network/tensor_ops.py +37 -0
  17. libcom/fopa_heat_map/source/prepare_multi_fg_scales.py +85 -0
  18. libcom/fos_score/__init__.py +4 -0
  19. libcom/fos_score/fos_score_prediction.py +218 -0
  20. libcom/fos_score/source/__init__.py +0 -0
  21. libcom/fos_score/source/config/__init__.py +1 -0
  22. libcom/fos_score/source/config/config.py +68 -0
  23. libcom/fos_score/source/config/config.sfosd.yaml +43 -0
  24. libcom/fos_score/source/config/config_rfosd.yaml +43 -0
  25. libcom/fos_score/source/loss_function.py +118 -0
  26. libcom/fos_score/source/networks.py +355 -0
  27. libcom/harmony_score/__init__.py +3 -0
  28. libcom/harmony_score/harmony_score_prediction.py +119 -0
  29. libcom/harmony_score/source/__init__.py +0 -0
  30. libcom/harmony_score/source/bargainnet.py +226 -0
  31. libcom/image_harmonization/__init__.py +4 -0
  32. libcom/image_harmonization/image_harmonization.py +193 -0
  33. libcom/image_harmonization/source/__init__.py +0 -0
  34. libcom/image_harmonization/source/functions.py +747 -0
  35. libcom/image_harmonization/source/pct_net.py +85 -0
  36. libcom/image_harmonization/source/src/__init__.py +0 -0
  37. libcom/image_harmonization/source/src/lbm/__init__.py +0 -0
  38. libcom/image_harmonization/source/src/lbm/config.py +141 -0
  39. libcom/image_harmonization/source/src/lbm/data/__init__.py +62 -0
  40. libcom/image_harmonization/source/src/lbm/data/datasets/__init__.py +9 -0
  41. libcom/image_harmonization/source/src/lbm/data/datasets/collation_fn.py +41 -0
  42. libcom/image_harmonization/source/src/lbm/data/datasets/dataset.py +243 -0
  43. libcom/image_harmonization/source/src/lbm/data/datasets/datasets_config.py +42 -0
  44. libcom/image_harmonization/source/src/lbm/data/filters/__init__.py +12 -0
  45. libcom/image_harmonization/source/src/lbm/data/filters/base.py +21 -0
  46. libcom/image_harmonization/source/src/lbm/data/filters/filter_wrapper.py +36 -0
  47. libcom/image_harmonization/source/src/lbm/data/filters/filters.py +33 -0
  48. libcom/image_harmonization/source/src/lbm/data/filters/filters_config.py +32 -0
  49. libcom/image_harmonization/source/src/lbm/data/mappers/__init__.py +19 -0
  50. libcom/image_harmonization/source/src/lbm/data/mappers/base.py +26 -0
  51. libcom/image_harmonization/source/src/lbm/data/mappers/mappers.py +135 -0
  52. libcom/image_harmonization/source/src/lbm/data/mappers/mappers_config.py +109 -0
  53. libcom/image_harmonization/source/src/lbm/data/mappers/mappers_wrapper.py +31 -0
  54. libcom/image_harmonization/source/src/lbm/inference/__init__.py +4 -0
  55. libcom/image_harmonization/source/src/lbm/inference/inference.py +70 -0
  56. libcom/image_harmonization/source/src/lbm/inference/utils.py +222 -0
  57. libcom/image_harmonization/source/src/lbm/models/__init__.py +0 -0
  58. libcom/image_harmonization/source/src/lbm/models/base/__init__.py +4 -0
  59. libcom/image_harmonization/source/src/lbm/models/base/base_model.py +66 -0
  60. libcom/image_harmonization/source/src/lbm/models/base/model_config.py +8 -0
  61. libcom/image_harmonization/source/src/lbm/models/embedders/__init__.py +4 -0
  62. libcom/image_harmonization/source/src/lbm/models/embedders/base/__init__.py +4 -0
  63. libcom/image_harmonization/source/src/lbm/models/embedders/base/base_conditioner.py +60 -0
  64. libcom/image_harmonization/source/src/lbm/models/embedders/base/base_conditioner_config.py +27 -0
  65. libcom/image_harmonization/source/src/lbm/models/embedders/conditioners_wrapper.py +114 -0
  66. libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/__init__.py +4 -0
  67. libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/latents_concat_embedder_config.py +31 -0
  68. libcom/image_harmonization/source/src/lbm/models/embedders/latents_concat/latents_concat_embedder_model.py +80 -0
  69. libcom/image_harmonization/source/src/lbm/models/lbm/__init__.py +4 -0
  70. libcom/image_harmonization/source/src/lbm/models/lbm/lbm_config.py +101 -0
  71. libcom/image_harmonization/source/src/lbm/models/lbm/lbm_model.py +359 -0
  72. libcom/image_harmonization/source/src/lbm/models/unets/__init__.py +14 -0
  73. libcom/image_harmonization/source/src/lbm/models/unets/unet.py +148 -0
  74. libcom/image_harmonization/source/src/lbm/models/utils.py +377 -0
  75. libcom/image_harmonization/source/src/lbm/models/vae/__init__.py +4 -0
  76. libcom/image_harmonization/source/src/lbm/models/vae/autoencoderKL.py +136 -0
  77. libcom/image_harmonization/source/src/lbm/models/vae/autoencoderKL_config.py +27 -0
  78. libcom/image_harmonization/source/src/lbm/trainer/__init__.py +85 -0
  79. libcom/image_harmonization/source/src/lbm/trainer/loggers.py +324 -0
  80. libcom/image_harmonization/source/src/lbm/trainer/trainer.py +199 -0
  81. libcom/image_harmonization/source/src/lbm/trainer/training_config.py +82 -0
  82. libcom/image_harmonization/source/src/lbm/trainer/utils.py +193 -0
  83. libcom/inharmonious_region_localization/__init__.py +4 -0
  84. libcom/inharmonious_region_localization/inharmonious_region_localization.py +97 -0
  85. libcom/inharmonious_region_localization/source/__init__.py +0 -0
  86. libcom/inharmonious_region_localization/source/blocks.py +368 -0
  87. libcom/inharmonious_region_localization/source/functions.py +679 -0
  88. libcom/inharmonious_region_localization/source/madis_net.py +79 -0
  89. libcom/kontext_blending_harmonization/__init__.py +3 -0
  90. libcom/kontext_blending_harmonization/kontext_blending_harmonization.py +148 -0
  91. libcom/kontext_blending_harmonization/source/__init__.py +0 -0
  92. libcom/kontext_blending_harmonization/source/pipeline.py +1135 -0
  93. libcom/naive_composition/__init__.py +3 -0
  94. libcom/naive_composition/generate_composite_image.py +116 -0
  95. libcom/opa_score/__init__.py +3 -0
  96. libcom/opa_score/opa_score_prediction.py +101 -0
  97. libcom/opa_score/source/__init__.py +3 -0
  98. libcom/opa_score/source/object_place_net.py +55 -0
  99. libcom/opa_score/source/oblect_place_config.py +66 -0
  100. libcom/opa_score/source/resnet_4ch.py +213 -0
  101. libcom/os_insert/__init__.py +3 -0
  102. libcom/os_insert/diffusers_osinsert/__init__.py +78 -0
  103. libcom/os_insert/diffusers_osinsert/_patched_pipeline_flux_fill.py +878 -0
  104. libcom/os_insert/os_insert.py +534 -0
  105. libcom/os_insert/source/__init__.py +1 -0
  106. libcom/os_insert/source/ia_utils.py +183 -0
  107. libcom/os_insert/source/insertanything_infer.py +529 -0
  108. libcom/os_insert/source/ldm/__init__.py +0 -0
  109. libcom/os_insert/source/ldm/data/__init__.py +0 -0
  110. libcom/os_insert/source/ldm/data/base.py +23 -0
  111. libcom/os_insert/source/ldm/data/datamodule.py +128 -0
  112. libcom/os_insert/source/ldm/data/imagenet.py +394 -0
  113. libcom/os_insert/source/ldm/data/lsun.py +92 -0
  114. libcom/os_insert/source/ldm/data/open_images.py +728 -0
  115. libcom/os_insert/source/ldm/lr_scheduler.py +98 -0
  116. libcom/os_insert/source/ldm/models/__init__.py +0 -0
  117. libcom/os_insert/source/ldm/models/autoencoder.py +443 -0
  118. libcom/os_insert/source/ldm/models/diffusion/__init__.py +0 -0
  119. libcom/os_insert/source/ldm/models/diffusion/classifier.py +267 -0
  120. libcom/os_insert/source/ldm/models/diffusion/ddim.py +263 -0
  121. libcom/os_insert/source/ldm/models/diffusion/ddpm.py +1417 -0
  122. libcom/os_insert/source/ldm/models/diffusion/plms.py +252 -0
  123. libcom/os_insert/source/ldm/modules/__init__.py +0 -0
  124. libcom/os_insert/source/ldm/modules/attention.py +261 -0
  125. libcom/os_insert/source/ldm/modules/diffusionmodules/__init__.py +0 -0
  126. libcom/os_insert/source/ldm/modules/diffusionmodules/model.py +835 -0
  127. libcom/os_insert/source/ldm/modules/diffusionmodules/openaimodel.py +1108 -0
  128. libcom/os_insert/source/ldm/modules/diffusionmodules/util.py +267 -0
  129. libcom/os_insert/source/ldm/modules/distributions/__init__.py +0 -0
  130. libcom/os_insert/source/ldm/modules/distributions/distributions.py +92 -0
  131. libcom/os_insert/source/ldm/modules/ema.py +76 -0
  132. libcom/os_insert/source/ldm/modules/encoders/__init__.py +0 -0
  133. libcom/os_insert/source/ldm/modules/encoders/modules.py +190 -0
  134. libcom/os_insert/source/ldm/modules/encoders/xf.py +130 -0
  135. libcom/os_insert/source/ldm/modules/losses/__init__.py +1 -0
  136. libcom/os_insert/source/ldm/modules/losses/contperceptual.py +111 -0
  137. libcom/os_insert/source/ldm/modules/losses/vqperceptual.py +167 -0
  138. libcom/os_insert/source/ldm/modules/x_transformer.py +641 -0
  139. libcom/os_insert/source/ldm/util.py +203 -0
  140. libcom/os_insert/source/objectstitch_data.py +66 -0
  141. libcom/os_insert/source/objectstitch_infer.py +618 -0
  142. libcom/os_insert/source/sam_on_objectstitch.py +253 -0
  143. libcom/os_insert/source/utils.py +41 -0
  144. libcom/os_insert/source/v1.yaml +108 -0
  145. libcom/painterly_image_harmonization/__init__.py +4 -0
  146. libcom/painterly_image_harmonization/painterly_image_harmonization.py +215 -0
  147. libcom/painterly_image_harmonization/source/PHDNet/__init__.py +0 -0
  148. libcom/painterly_image_harmonization/source/PHDNet/networks.py +202 -0
  149. libcom/painterly_image_harmonization/source/PHDNet/phdnet.py +47 -0
  150. libcom/painterly_image_harmonization/source/PHDNet/phdnet_config.py +18 -0
  151. libcom/painterly_image_harmonization/source/PHDiffusion/__init__.py +0 -0
  152. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/__init__.py +0 -0
  153. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/inference_base.py +300 -0
  154. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/lr_scheduler.py +98 -0
  155. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/__init__.py +0 -0
  156. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/autoencoder.py +211 -0
  157. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/__init__.py +3 -0
  158. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/ddim.py +336 -0
  159. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/ddpm.py +1400 -0
  160. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
  161. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/dpm_solver.py +1217 -0
  162. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
  163. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/plms.py +243 -0
  164. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/models/diffusion/scheduling_pndm.py +518 -0
  165. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/__init__.py +0 -0
  166. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/attention.py +378 -0
  167. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/__init__.py +0 -0
  168. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/model.py +857 -0
  169. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/openaimodel.py +823 -0
  170. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/diffusionmodules/util.py +270 -0
  171. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/distributions/__init__.py +0 -0
  172. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/distributions/distributions.py +92 -0
  173. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/ema.py +80 -0
  174. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/__init__.py +0 -0
  175. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/adapter.py +213 -0
  176. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/encoders/modules.py +82 -0
  177. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/__init__.py +1 -0
  178. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/api.py +269 -0
  179. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/__init__.py +0 -0
  180. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/api.py +175 -0
  181. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/__init__.py +0 -0
  182. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/base_model.py +16 -0
  183. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/blocks.py +342 -0
  184. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/dpt_depth.py +109 -0
  185. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/midas_net.py +76 -0
  186. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/midas_net_custom.py +128 -0
  187. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/transforms.py +234 -0
  188. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/midas/vit.py +491 -0
  189. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/midas/utils.py +189 -0
  190. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/model_edge.py +653 -0
  191. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/__init__.py +0 -0
  192. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/api.py +35 -0
  193. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/body.py +209 -0
  194. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/hand.py +75 -0
  195. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/model.py +178 -0
  196. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/openpose/util.py +203 -0
  197. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/extra_condition/utils.py +72 -0
  198. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/fusion/__init__.py +0 -0
  199. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/fusion/dual_encoder_fusion.py +93 -0
  200. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/__init__.py +2 -0
  201. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/bsrgan.py +730 -0
  202. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/bsrgan_light.py +651 -0
  203. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/modules/image_degradation/utils_image.py +916 -0
  204. libcom/painterly_image_harmonization/source/PHDiffusion/ldm/util.py +200 -0
  205. libcom/painterly_image_harmonization/source/PHDiffusion/stable_diffusion.yaml +75 -0
  206. libcom/painterly_image_harmonization/source/__init__.py +0 -0
  207. libcom/reflection_generation/__init__.py +3 -0
  208. libcom/reflection_generation/reflection_generation.py +174 -0
  209. libcom/reflection_generation/source/PostProcessModel.py +513 -0
  210. libcom/reflection_generation/source/__init__.py +0 -0
  211. libcom/reflection_generation/source/cldm/__init__.py +0 -0
  212. libcom/reflection_generation/source/cldm/base_network.py +166 -0
  213. libcom/reflection_generation/source/cldm/cldm.py +509 -0
  214. libcom/reflection_generation/source/cldm/ddim_hacked.py +317 -0
  215. libcom/reflection_generation/source/cldm/hack.py +111 -0
  216. libcom/reflection_generation/source/cldm/logger.py +127 -0
  217. libcom/reflection_generation/source/cldm/model.py +26 -0
  218. libcom/reflection_generation/source/cldm_v15.yaml +81 -0
  219. libcom/reflection_generation/source/cluster_feature.py +109 -0
  220. libcom/reflection_generation/source/ldm/__init__.py +0 -0
  221. libcom/reflection_generation/source/ldm/models/__init__.py +0 -0
  222. libcom/reflection_generation/source/ldm/models/autoencoder.py +219 -0
  223. libcom/reflection_generation/source/ldm/models/diffusion/__init__.py +0 -0
  224. libcom/reflection_generation/source/ldm/models/diffusion/attention_processor.py +188 -0
  225. libcom/reflection_generation/source/ldm/models/diffusion/ddim.py +340 -0
  226. libcom/reflection_generation/source/ldm/models/diffusion/ddpm.py +1892 -0
  227. libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
  228. libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/dpm_solver.py +1154 -0
  229. libcom/reflection_generation/source/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
  230. libcom/reflection_generation/source/ldm/models/diffusion/ip_adapter.py +57 -0
  231. libcom/reflection_generation/source/ldm/models/diffusion/plms.py +244 -0
  232. libcom/reflection_generation/source/ldm/models/diffusion/sampling_util.py +22 -0
  233. libcom/reflection_generation/source/ldm/modules/__init__.py +0 -0
  234. libcom/reflection_generation/source/ldm/modules/attention.py +341 -0
  235. libcom/reflection_generation/source/ldm/modules/diffusionmodules/__init__.py +0 -0
  236. libcom/reflection_generation/source/ldm/modules/diffusionmodules/model.py +852 -0
  237. libcom/reflection_generation/source/ldm/modules/diffusionmodules/openaimodel.py +786 -0
  238. libcom/reflection_generation/source/ldm/modules/diffusionmodules/upscaling.py +81 -0
  239. libcom/reflection_generation/source/ldm/modules/diffusionmodules/util.py +280 -0
  240. libcom/reflection_generation/source/ldm/modules/distributions/__init__.py +0 -0
  241. libcom/reflection_generation/source/ldm/modules/distributions/distributions.py +92 -0
  242. libcom/reflection_generation/source/ldm/modules/ema.py +80 -0
  243. libcom/reflection_generation/source/ldm/modules/encoders/__init__.py +0 -0
  244. libcom/reflection_generation/source/ldm/modules/encoders/modules.py +214 -0
  245. libcom/reflection_generation/source/ldm/modules/image_degradation/__init__.py +0 -0
  246. libcom/reflection_generation/source/ldm/modules/image_degradation/bsrgan.py +730 -0
  247. libcom/reflection_generation/source/ldm/modules/image_degradation/bsrgan_light.py +651 -0
  248. libcom/reflection_generation/source/ldm/modules/image_degradation/utils_image.py +916 -0
  249. libcom/reflection_generation/source/ldm/util.py +198 -0
  250. libcom/reflection_generation/source/local_clip.py +749 -0
  251. libcom/reflection_generation/source/tool_add_control.py +49 -0
  252. libcom/shadow_generation/__init__.py +3 -0
  253. libcom/shadow_generation/shadow_generation.py +754 -0
  254. libcom/shadow_generation/source/PostProcessModel.py +511 -0
  255. libcom/shadow_generation/source/__init__.py +0 -0
  256. libcom/shadow_generation/source/attention_processor.py +234 -0
  257. libcom/shadow_generation/source/cldm/__init__.py +0 -0
  258. libcom/shadow_generation/source/cldm/base_network.py +166 -0
  259. libcom/shadow_generation/source/cldm/cldm.py +524 -0
  260. libcom/shadow_generation/source/cldm/model.py +28 -0
  261. libcom/shadow_generation/source/ldm/__init__.py +0 -0
  262. libcom/shadow_generation/source/ldm/models/__init__.py +0 -0
  263. libcom/shadow_generation/source/ldm/models/autoencoder.py +219 -0
  264. libcom/shadow_generation/source/ldm/models/diffusion/__init__.py +0 -0
  265. libcom/shadow_generation/source/ldm/models/diffusion/attention_processor.py +188 -0
  266. libcom/shadow_generation/source/ldm/models/diffusion/ddim.py +340 -0
  267. libcom/shadow_generation/source/ldm/models/diffusion/ddpm.py +1893 -0
  268. libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/__init__.py +1 -0
  269. libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/dpm_solver.py +1154 -0
  270. libcom/shadow_generation/source/ldm/models/diffusion/dpm_solver/sampler.py +87 -0
  271. libcom/shadow_generation/source/ldm/models/diffusion/ip_adapter.py +57 -0
  272. libcom/shadow_generation/source/ldm/models/diffusion/plms.py +244 -0
  273. libcom/shadow_generation/source/ldm/models/diffusion/sampling_util.py +22 -0
  274. libcom/shadow_generation/source/ldm/modules/__init__.py +0 -0
  275. libcom/shadow_generation/source/ldm/modules/attention.py +341 -0
  276. libcom/shadow_generation/source/ldm/modules/diffusionmodules/__init__.py +0 -0
  277. libcom/shadow_generation/source/ldm/modules/diffusionmodules/model.py +852 -0
  278. libcom/shadow_generation/source/ldm/modules/diffusionmodules/openaimodel.py +786 -0
  279. libcom/shadow_generation/source/ldm/modules/diffusionmodules/upscaling.py +81 -0
  280. libcom/shadow_generation/source/ldm/modules/diffusionmodules/util.py +270 -0
  281. libcom/shadow_generation/source/ldm/modules/distributions/__init__.py +0 -0
  282. libcom/shadow_generation/source/ldm/modules/distributions/distributions.py +92 -0
  283. libcom/shadow_generation/source/ldm/modules/ema.py +80 -0
  284. libcom/shadow_generation/source/ldm/modules/encoders/__init__.py +0 -0
  285. libcom/shadow_generation/source/ldm/modules/encoders/modules.py +214 -0
  286. libcom/shadow_generation/source/ldm/modules/image_degradation/__init__.py +2 -0
  287. libcom/shadow_generation/source/ldm/modules/image_degradation/bsrgan.py +730 -0
  288. libcom/shadow_generation/source/ldm/modules/image_degradation/bsrgan_light.py +651 -0
  289. libcom/shadow_generation/source/ldm/modules/image_degradation/utils_image.py +916 -0
  290. libcom/shadow_generation/source/ldm/modules/midas/__init__.py +0 -0
  291. libcom/shadow_generation/source/ldm/modules/midas/api.py +170 -0
  292. libcom/shadow_generation/source/ldm/modules/midas/midas/__init__.py +0 -0
  293. libcom/shadow_generation/source/ldm/modules/midas/midas/base_model.py +16 -0
  294. libcom/shadow_generation/source/ldm/modules/midas/midas/blocks.py +342 -0
  295. libcom/shadow_generation/source/ldm/modules/midas/midas/dpt_depth.py +109 -0
  296. libcom/shadow_generation/source/ldm/modules/midas/midas/midas_net.py +76 -0
  297. libcom/shadow_generation/source/ldm/modules/midas/midas/midas_net_custom.py +128 -0
  298. libcom/shadow_generation/source/ldm/modules/midas/midas/transforms.py +234 -0
  299. libcom/shadow_generation/source/ldm/modules/midas/midas/vit.py +491 -0
  300. libcom/shadow_generation/source/ldm/modules/midas/utils.py +189 -0
  301. libcom/shadow_generation/source/ldm/util.py +199 -0
  302. libcom/utils/__init__.py +0 -0
  303. libcom/utils/environment.py +12 -0
  304. libcom/utils/model_download.py +67 -0
  305. libcom/utils/process_image.py +108 -0
  306. libcom-0.1.8.dist-info/METADATA +157 -0
  307. libcom-0.1.8.dist-info/RECORD +310 -0
  308. libcom-0.1.8.dist-info/WHEEL +5 -0
  309. libcom-0.1.8.dist-info/licenses/LICENSE +201 -0
  310. libcom-0.1.8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,754 @@
1
+ import argparse
2
+ import logging
3
+ import torch
4
+ import torch.nn.functional as F
5
+ import pickle
6
+ import numpy as np
7
+ import os, cv2, torch, random
8
+ from tqdm.auto import tqdm
9
+ from transformers import AutoTokenizer, PretrainedConfig
10
+ from diffusers import (
11
+ AutoencoderKL,
12
+ ControlNetModel,
13
+ DDPMScheduler,
14
+ UNet2DConditionModel,
15
+ )
16
+ from pytorch_lightning import seed_everything
17
+ from diffusers.utils import check_min_version, is_wandb_available
18
+ from torch.utils.data import Dataset
19
+ from .source.cldm.base_network import MaskCls, RegNetwork
20
+ from .source.PostProcessModel import PostProcess
21
+ from .source.cldm.model import load_state_dict
22
+ from .source.attention_processor import IPAttnProcessor, AttnProcessor
23
+
24
+ seed_everything(42)
25
+
26
+ def is_torch2_available():
27
+ return hasattr(F, "scaled_dot_product_attention")
28
+
29
+ def print_memory(prefix=""):
30
+ if torch.cuda.is_available():
31
+ allocated = torch.cuda.memory_allocated() / 1024**3
32
+ reserved = torch.cuda.memory_reserved() / 1024**3
33
+ print(f"[Memory] {prefix} Allocated: {allocated:.2f} GB | Reserved: {reserved:.2f} GB")
34
+
35
+ class TestDataset(Dataset):
36
+ def __init__(self, shadowfree_img, object_mask, text_encoders, tokenizers, caption_column='text'):
37
+ """
38
+ shadowfree_img: str(path) 或 np.ndarray (H, W, 3)
39
+ object_mask: str(path) 或 np.ndarray (H, W)
40
+ """
41
+ self.shadowfree_img = self._load_image(shadowfree_img)
42
+ self.object_mask = self._load_mask(object_mask)
43
+ self.text_encoders = text_encoders
44
+ self.tokenizers = tokenizers
45
+ self.caption_column = caption_column
46
+
47
+ # 预处理图片,生成 control input, target, bounding box, embedding 占位
48
+ self.preprocess_data()
49
+ self.precompute_embeddings()
50
+
51
+ def _load_image(self, img_input):
52
+ """自动处理路径或 np.ndarray 的彩色图片"""
53
+ if isinstance(img_input, str):
54
+ img = cv2.imread(img_input)
55
+ if img is None:
56
+ raise ValueError(f"Image not found: {img_input}")
57
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
58
+ elif isinstance(img_input, np.ndarray):
59
+ img = cv2.cvtColor(img_input, cv2.COLOR_BGR2RGB)
60
+ else:
61
+ raise TypeError("shadowfree_img must be str or np.ndarray")
62
+ img = cv2.resize(img, (512, 512))
63
+ return img
64
+
65
+ def _load_mask(self, mask_input):
66
+ """自动处理路径或 np.ndarray 的灰度 mask"""
67
+ if isinstance(mask_input, str):
68
+ mask = cv2.imread(mask_input, cv2.IMREAD_GRAYSCALE)
69
+ if mask is None:
70
+ raise ValueError(f"Mask not found: {mask_input}")
71
+ elif isinstance(mask_input, np.ndarray):
72
+ mask = mask_input
73
+ else:
74
+ raise TypeError("object_mask must be str or np.ndarray")
75
+ mask = cv2.resize(mask, (512, 512))
76
+ return mask
77
+
78
+ def preprocess_data(self):
79
+ # Bounding box 前景
80
+ _, fg_instance_thresh = cv2.threshold(self.object_mask, 128, 255, cv2.THRESH_BINARY)
81
+ contours_instance, _ = cv2.findContours(fg_instance_thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
82
+ merged_contour_points_instance = np.concatenate(contours_instance)
83
+ rect_instance = cv2.minAreaRect(merged_contour_points_instance)
84
+ (x, y), (w, h), theta = rect_instance
85
+ if w < h:
86
+ w, h = h, w
87
+ theta += 90
88
+ self.fg_instance = np.array([x, y, w+1, h+1, theta]).astype(int)
89
+ self.bbx_region = torch.zeros((512, 512), dtype=torch.float16)
90
+
91
+ # Control input 和 target
92
+ control_input = np.concatenate([self.shadowfree_img, self.object_mask[..., None]], axis=-1)
93
+ self.control_input = control_input.astype(np.float16) / 255.0
94
+ self.target = (self.shadowfree_img.astype(np.float16) / 127.5) - 1.0
95
+
96
+ # Embedding 占位
97
+ self.embeddings_placeholder = torch.zeros((64, 2048), dtype=torch.float16)
98
+ self.prompt = 'foreground object with shadow'
99
+ self.name = 'single_image'
100
+
101
+ def precompute_embeddings(self):
102
+ dummy_batch = {
103
+ self.caption_column: [self.prompt],
104
+ "__fake_image__": [None]
105
+ }
106
+
107
+ with torch.no_grad():
108
+ embeddings = compute_embeddings(
109
+ batch=dummy_batch,
110
+ proportion_empty_prompts=0,
111
+ text_encoders=self.text_encoders,
112
+ tokenizers=self.tokenizers
113
+ )
114
+
115
+ # 取第0个 batch 的结果
116
+ self.prompt_embeds = embeddings["prompt_embeds"].cpu()[0]
117
+ self.text_embeds = embeddings["text_embeds"].cpu()[0]
118
+ self.time_ids = embeddings["time_ids"].cpu()[0]
119
+
120
+ def __len__(self):
121
+ return 1 # 单张图片
122
+
123
+ def __getitem__(self, idx):
124
+ return {
125
+ "pixel_values": torch.tensor(self.target).permute(2, 0, 1).float(),
126
+ "conditioning_pixel_values": torch.tensor(self.control_input).permute(2, 0, 1).float(),
127
+ "bbx": self.bbx_region,
128
+ "fg": self.fg_instance,
129
+ "embeddings": self.embeddings_placeholder,
130
+ "prompt_ids": self.prompt_embeds,
131
+ "unet_added_conditions": {
132
+ "text_embeds": self.text_embeds,
133
+ "time_ids": self.time_ids
134
+ },
135
+ "name": self.name
136
+ }
137
+
138
+
139
+ class IPAdapter(torch.nn.Module):
140
+ """IP-Adapter"""
141
+ def __init__(self, unet, image_proj_model, adapter_modules, ckpt_path=None):
142
+ super().__init__()
143
+ self.unet = unet
144
+ self.image_proj_model = image_proj_model
145
+ self.adapter_modules = adapter_modules
146
+
147
+ if ckpt_path is not None:
148
+ self.load_from_checkpoint(ckpt_path)
149
+
150
+ def forward(self, noisy_latents, timesteps, encoder_hidden_states, added_cond_kwargs, down_block_additional_residuals, mid_block_additional_residual, mask_embeddings):
151
+ ip_tokens = self.image_proj_model(mask_embeddings)
152
+ encoder_hidden_states = torch.cat([encoder_hidden_states, ip_tokens], dim=1)
153
+ # Predict the noise residual
154
+ noise_pred = self.unet(sample=noisy_latents, timestep=timesteps, encoder_hidden_states=encoder_hidden_states, added_cond_kwargs=added_cond_kwargs, down_block_additional_residuals=down_block_additional_residuals, mid_block_additional_residual=mid_block_additional_residual, return_dict=False)[0]
155
+ return noise_pred
156
+
157
+ def load_from_checkpoint(self, ckpt_path: str):
158
+ # Calculate original checksums
159
+ orig_ip_proj_sum = torch.sum(torch.stack([torch.sum(p) for p in self.image_proj_model.parameters()]))
160
+ orig_adapter_sum = torch.sum(torch.stack([torch.sum(p) for p in self.adapter_modules.parameters()]))
161
+
162
+ state_dict = torch.load(ckpt_path, map_location="cpu")
163
+
164
+ # Load state dict for image_proj_model and adapter_modules
165
+ self.image_proj_model.load_state_dict(state_dict["image_proj"], strict=True)
166
+ self.adapter_modules.load_state_dict(state_dict["ip_adapter"], strict=True)
167
+
168
+ # Calculate new checksums
169
+ new_ip_proj_sum = torch.sum(torch.stack([torch.sum(p) for p in self.image_proj_model.parameters()]))
170
+ new_adapter_sum = torch.sum(torch.stack([torch.sum(p) for p in self.adapter_modules.parameters()]))
171
+
172
+ # Verify if the weights have changed
173
+ assert orig_ip_proj_sum != new_ip_proj_sum, "Weights of image_proj_model did not change!"
174
+ assert orig_adapter_sum != new_adapter_sum, "Weights of adapter_modules did not change!"
175
+
176
+ print(f"Successfully loaded weights from checkpoint {ckpt_path}")
177
+
178
+ class ImageProjModel(torch.nn.Module):
179
+ """Projection Model"""
180
+
181
+ def __init__(self, cross_attention_dim=768, extra_embeddings_dim=2048, clip_extra_context_tokens=64):
182
+ super().__init__()
183
+
184
+ self.generator = None
185
+ self.cross_attention_dim = cross_attention_dim
186
+ self.clip_extra_context_tokens = clip_extra_context_tokens
187
+ self.proj = torch.nn.Linear(extra_embeddings_dim, cross_attention_dim)
188
+ self.norm = torch.nn.LayerNorm(cross_attention_dim)
189
+
190
+ def forward(self, image_embeds):
191
+ extra_embeds = self.proj(image_embeds)
192
+ extra_embeds = self.norm(extra_embeds)
193
+ return extra_embeds
194
+
195
+ def compute_embeddings(batch, proportion_empty_prompts, text_encoders, tokenizers, is_train=False):
196
+ original_size = (512, 512)
197
+ target_size = (512, 512)
198
+ crops_coords_top_left = (0, 0)
199
+ prompt_batch = batch['text']
200
+
201
+ prompt_embeds, pooled_prompt_embeds = encode_prompt(
202
+ prompt_batch, text_encoders, tokenizers, proportion_empty_prompts, is_train
203
+ )
204
+ add_text_embeds = pooled_prompt_embeds
205
+
206
+ # Adapted from pipeline.StableDiffusionXLPipeline._get_add_time_ids
207
+ add_time_ids = list(original_size + crops_coords_top_left + target_size)
208
+ add_time_ids = torch.tensor([add_time_ids])
209
+
210
+ prompt_embeds = prompt_embeds
211
+ add_text_embeds = add_text_embeds
212
+ add_time_ids = add_time_ids.repeat(len(prompt_batch), 1)
213
+ add_time_ids = add_time_ids.to(prompt_embeds.dtype)
214
+ unet_added_cond_kwargs = {"text_embeds": add_text_embeds, "time_ids": add_time_ids}
215
+
216
+ return {"prompt_embeds": prompt_embeds, **unet_added_cond_kwargs}
217
+
218
+ if is_wandb_available():
219
+ import wandb
220
+
221
+ # Will error if the minimal version of diffusers is not installed. Remove at your own risks.
222
+ check_min_version("0.34.0.dev0")
223
+
224
+ def import_model_class_from_model_name_or_path(
225
+ pretrained_model_name_or_path: str, revision: str, subfolder: str = "text_encoder"
226
+ ):
227
+ text_encoder_config = PretrainedConfig.from_pretrained(
228
+ pretrained_model_name_or_path, subfolder=subfolder, revision=revision
229
+ )
230
+ model_class = text_encoder_config.architectures[0]
231
+
232
+ if model_class == "CLIPTextModel":
233
+ from transformers import CLIPTextModel
234
+
235
+ return CLIPTextModel
236
+ elif model_class == "CLIPTextModelWithProjection":
237
+ from transformers import CLIPTextModelWithProjection
238
+
239
+ return CLIPTextModelWithProjection
240
+ else:
241
+ raise ValueError(f"{model_class} is not supported.")
242
+
243
+
244
+ def parse_args(input_args=None):
245
+ parser = argparse.ArgumentParser(description="Simple example of a ControlNet script.")
246
+ parser.add_argument(
247
+ "--pretrained_model_name_or_path",
248
+ type=str,
249
+ default='stabilityai/stable-diffusion-xl-base-1.0',
250
+ help="Path to pretrained model or model identifier from huggingface.co/models.",
251
+ )
252
+ parser.add_argument(
253
+ "--pretrained_vae_model_name_or_path",
254
+ type=str,
255
+ default=None,
256
+ help="Path to an improved VAE to stabilize training. For more details check out: https://github.com/huggingface/diffusers/pull/4038.",
257
+ )
258
+ parser.add_argument(
259
+ "--variant",
260
+ type=str,
261
+ default=None,
262
+ help="Variant of the model files of the pretrained model identifier from huggingface.co/models, 'e.g.' fp16",
263
+ )
264
+ parser.add_argument(
265
+ "--revision",
266
+ type=str,
267
+ default=None,
268
+ required=False,
269
+ help="Revision of pretrained model identifier from huggingface.co/models.",
270
+ )
271
+ parser.add_argument(
272
+ "--tokenizer_name",
273
+ type=str,
274
+ default=None,
275
+ help="Pretrained tokenizer name or path if not the same as model_name",
276
+ )
277
+
278
+ parser.add_argument(
279
+ "--resolution",
280
+ type=int,
281
+ default=512,
282
+ help=(
283
+ "The resolution for input images, all the images in the train/validation dataset will be resized to this"
284
+ " resolution"
285
+ ),
286
+ )
287
+ parser.add_argument(
288
+ "--crops_coords_top_left_h",
289
+ type=int,
290
+ default=0,
291
+ help=("Coordinate for (the height) to be included in the crop coordinate embeddings needed by SDXL UNet."),
292
+ )
293
+ parser.add_argument(
294
+ "--crops_coords_top_left_w",
295
+ type=int,
296
+ default=0,
297
+ help=("Coordinate for (the height) to be included in the crop coordinate embeddings needed by SDXL UNet."),
298
+ )
299
+ parser.add_argument(
300
+ "--dataloader_num_workers",
301
+ type=int,
302
+ default=0,
303
+ help=(
304
+ "Number of subprocesses to use for data loading. 0 means that the data will be loaded in the main process."
305
+ ),
306
+ )
307
+ parser.add_argument(
308
+ "--caption_column",
309
+ type=str,
310
+ default="text",
311
+ help="The column of the dataset containing a caption or a list of captions.",
312
+ )
313
+ parser.add_argument(
314
+ "--proportion_empty_prompts",
315
+ type=float,
316
+ default=0,
317
+ help="Proportion of image prompts to be replaced with empty strings. Defaults to 0 (no prompt replacement).",
318
+ )
319
+ if input_args is not None:
320
+ args = parser.parse_args(input_args)
321
+ else:
322
+ args = parser.parse_args()
323
+
324
+ if args.proportion_empty_prompts < 0 or args.proportion_empty_prompts > 1:
325
+ raise ValueError("`--proportion_empty_prompts` must be in the range [0, 1].")
326
+
327
+
328
+ if args.resolution % 8 != 0:
329
+ raise ValueError(
330
+ "`--resolution` must be divisible by 8 for consistently sized encoded images between the VAE and the controlnet encoder."
331
+ )
332
+
333
+ return args
334
+
335
+
336
+ # Adapted from pipelines.StableDiffusionXLPipeline.encode_prompt
337
+ def encode_prompt(prompt_batch, text_encoders, tokenizers, proportion_empty_prompts, is_train=False):
338
+ prompt_embeds_list = []
339
+
340
+ captions = []
341
+ for caption in prompt_batch:
342
+ if random.random() < proportion_empty_prompts:
343
+ captions.append("")
344
+ elif isinstance(caption, str):
345
+ captions.append(caption)
346
+ elif isinstance(caption, (list, np.ndarray)):
347
+ # take a random caption if there are multiple
348
+ captions.append(random.choice(caption) if is_train else caption[0])
349
+
350
+ with torch.no_grad():
351
+ for tokenizer, text_encoder in zip(tokenizers, text_encoders):
352
+ text_inputs = tokenizer(
353
+ captions,
354
+ padding="max_length",
355
+ max_length=tokenizer.model_max_length,
356
+ truncation=True,
357
+ return_tensors="pt",
358
+ )
359
+ text_input_ids = text_inputs.input_ids
360
+ prompt_embeds = text_encoder(
361
+ text_input_ids.to(text_encoder.device),
362
+ output_hidden_states=True,
363
+ )
364
+
365
+ # We are only ALWAYS interested in the pooled output of the final text encoder
366
+ pooled_prompt_embeds = prompt_embeds[0]
367
+ prompt_embeds = prompt_embeds.hidden_states[-2]
368
+ bs_embed, seq_len, _ = prompt_embeds.shape
369
+ prompt_embeds = prompt_embeds.view(bs_embed, seq_len, -1)
370
+ prompt_embeds_list.append(prompt_embeds)
371
+
372
+ prompt_embeds = torch.concat(prompt_embeds_list, dim=-1)
373
+ pooled_prompt_embeds = pooled_prompt_embeds.view(bs_embed, -1)
374
+ return prompt_embeds, pooled_prompt_embeds
375
+
376
+
377
+ def collate_fn(examples):
378
+ pixel_values = torch.stack([torch.from_numpy(example["pixel_values"].transpose(2, 0, 1)) if isinstance(example["pixel_values"], np.ndarray) else example["pixel_values"].permute(0, 3, 1, 2) for example in examples])
379
+ pixel_values = pixel_values.to(memory_format=torch.contiguous_format).float()
380
+
381
+ conditioning_pixel_values = torch.stack([torch.from_numpy(example["conditioning_pixel_values"].transpose(2, 0, 1)) if isinstance(example["conditioning_pixel_values"], np.ndarray) else example["conditioning_pixel_values"].permute(0, 3, 1, 2) for example in examples])
382
+ conditioning_pixel_values = conditioning_pixel_values.to(memory_format=torch.contiguous_format).float()
383
+
384
+ prompt_ids = torch.stack([torch.tensor(example["prompt_embeds"]) for example in examples])
385
+
386
+ add_text_embeds = torch.stack([torch.tensor(example["text_embeds"]) for example in examples])
387
+ add_time_ids = torch.stack([torch.tensor(example["time_ids"]) for example in examples])
388
+
389
+ return {
390
+ "pixel_values": pixel_values,
391
+ "conditioning_pixel_values": conditioning_pixel_values,
392
+ "prompt_ids": prompt_ids,
393
+ "unet_added_conditions": {"text_embeds": add_text_embeds, "time_ids": add_time_ids},
394
+ }
395
+
396
+ import torch
397
+ import torch.nn as nn
398
+ import torch.nn.functional as F
399
+ import numpy as np
400
+ import cv2
401
+ import gc
402
+ import pickle
403
+ from pathlib import Path
404
+ from tqdm import tqdm
405
+ import os
406
+ import logging
407
+ from libcom.utils.model_download import download_pretrained_model, download_entire_folder
408
+
409
+ cur_dir = os.path.dirname(os.path.abspath(__file__))
410
+ model_dir = os.environ.get('LIBCOM_MODEL_DIR',cur_dir)
411
+
412
+ logger = logging.getLogger(__name__)
413
+
414
+ class ShadowGenerationModel:
415
+ """
416
+ Foreground Shadow generation model based on diffusion model.
417
+
418
+ Args:
419
+ device (str | torch.device): gpu id
420
+
421
+ Examples:
422
+ >>> from libcom import ShadowGenerationModel
423
+ >>> from libcom.utils.process_image import make_image_grid
424
+ >>> import cv2
425
+ >>> net = ShadowGenerationModel()
426
+ >>> comp_image1 = "../tests/shadow_generation/composite/1.png"
427
+ >>> comp_mask1 = "../tests/shadow_generation/composite_mask/1.png"
428
+ >>> preds = net(comp_image1, comp_mask1, number=5)
429
+ >>> grid_img = make_image_grid([comp_image1, comp_mask1] + preds)
430
+ >>> cv2.imwrite('../docs/_static/image/shadow_generation_result1.jpg', grid_img)
431
+ >>> comp_image2 = "../tests/shadow_generation/composite/2.png"
432
+ >>> comp_mask2 = "../tests/shadow_generation/composite_mask/2.png"
433
+ >>> preds = net(comp_image2, comp_mask2, number=5)
434
+ >>> grid_img = make_image_grid([comp_image2, comp_mask2] + preds)
435
+ >>> cv2.imwrite('../docs/_static/image/shadow_generation_result2.jpg', grid_img)
436
+
437
+ Expected result:
438
+
439
+ .. image:: _static/image/shadow_generation_result1.jpg
440
+ :scale: 21 %
441
+ .. image:: _static/image/shadow_generation_result2.jpg
442
+ :scale: 21 %
443
+
444
+ """
445
+ def __init__(self, device=0):
446
+ self.args = parse_args()
447
+ self.device = torch.device(f"cuda:{device}" if torch.cuda.is_available() else "cpu")
448
+ self.weight_dtype = torch.float32
449
+
450
+
451
+ self.controlnet_model_path = os.path.join(model_dir, 'shadow_controlnet')
452
+ self.ip_adapter_path = os.path.join(model_dir, 'pretrained_models', 'ip_adapter.ckpt')
453
+ self.ppp_weight_path = os.path.join(model_dir, 'pretrained_models', 'Shadow_ppp.ckpt')
454
+ self.cls_weight_path = os.path.join(model_dir, 'pretrained_models', 'Shadow_cls.pth')
455
+ self.reg_weight_path = os.path.join(model_dir, 'pretrained_models', 'Shadow_reg.pth')
456
+ self.cls_label_path = os.path.join(model_dir, 'pretrained_models', 'Shadow_cls_label.pkl')
457
+
458
+ download_entire_folder(self.controlnet_model_path)
459
+ download_pretrained_model(self.ip_adapter_path)
460
+ download_pretrained_model(self.ppp_weight_path)
461
+ download_pretrained_model(self.cls_weight_path)
462
+ download_pretrained_model(self.reg_weight_path)
463
+ download_pretrained_model(self.cls_label_path)
464
+
465
+ # Load tokenizers
466
+ self.tokenizer_one = AutoTokenizer.from_pretrained(
467
+ self.args.pretrained_model_name_or_path, subfolder="tokenizer", revision=self.args.revision, use_fast=False
468
+ )
469
+ self.tokenizer_two = AutoTokenizer.from_pretrained(
470
+ self.args.pretrained_model_name_or_path, subfolder="tokenizer_2", revision=self.args.revision, use_fast=False
471
+ )
472
+
473
+ # Load text encoders
474
+ text_encoder_cls_one = import_model_class_from_model_name_or_path(self.args.pretrained_model_name_or_path, self.args.revision)
475
+ text_encoder_cls_two = import_model_class_from_model_name_or_path(self.args.pretrained_model_name_or_path, self.args.revision, subfolder="text_encoder_2")
476
+
477
+ self.text_encoder_one = text_encoder_cls_one.from_pretrained(
478
+ self.args.pretrained_model_name_or_path, subfolder="text_encoder", revision=self.args.revision, variant=self.args.variant
479
+ ).to(self.device, dtype=self.weight_dtype)
480
+ self.text_encoder_two = text_encoder_cls_two.from_pretrained(
481
+ self.args.pretrained_model_name_or_path, subfolder="text_encoder_2", revision=self.args.revision, variant=self.args.variant
482
+ ).to(self.device, dtype=self.weight_dtype)
483
+
484
+ # Load scheduler and models
485
+ self.noise_scheduler = DDPMScheduler.from_pretrained(self.args.pretrained_model_name_or_path, subfolder="scheduler")
486
+ vae_path = self.args.pretrained_model_name_or_path if self.args.pretrained_vae_model_name_or_path is None else self.args.pretrained_vae_model_name_or_path
487
+ self.vae = AutoencoderKL.from_pretrained(
488
+ vae_path,
489
+ subfolder="vae" if self.args.pretrained_vae_model_name_or_path is None else None,
490
+ revision=self.args.revision,
491
+ variant=self.args.variant
492
+ ).to(self.device, dtype=self.weight_dtype)
493
+
494
+ self.unet = UNet2DConditionModel.from_pretrained(
495
+ self.args.pretrained_model_name_or_path, subfolder="unet", revision=self.args.revision, variant=self.args.variant
496
+ ).to(self.device, dtype=self.weight_dtype)
497
+
498
+ # MaskCls & RegNetwork
499
+ self.mask_cls = MaskCls(num_classes=256).to(self.device, dtype=self.weight_dtype)
500
+ if os.path.exists(self.cls_weight_path):
501
+ self.mask_cls.load_state_dict(torch.load(self.cls_weight_path, weights_only=False)['net'])
502
+ print('Loaded mask classification model.')
503
+
504
+ self.bbx_reg = RegNetwork().to(self.device, dtype=self.weight_dtype)
505
+ if os.path.exists(self.reg_weight_path):
506
+ self.bbx_reg.load_state_dict(torch.load(self.reg_weight_path, weights_only=False)['net'])
507
+ print('Loaded rotated bounding box regression model.')
508
+
509
+ # ControlNet
510
+ if self.controlnet_model_path:
511
+ self.controlnet = ControlNetModel.from_pretrained(self.controlnet_model_path).to(self.device, dtype=self.weight_dtype)
512
+ else:
513
+ self.controlnet = ControlNetModel.from_unet(self.unet, conditioning_channels=5).to(self.device, dtype=self.weight_dtype)
514
+
515
+ # IP-Adapter
516
+ num_tokens = 64
517
+ self.image_proj_model = ImageProjModel(
518
+ cross_attention_dim=self.unet.config.cross_attention_dim,
519
+ extra_embeddings_dim=2048,
520
+ clip_extra_context_tokens=num_tokens,
521
+ ).to(self.device, dtype=self.weight_dtype)
522
+
523
+ # init adapter modules
524
+ attn_procs = {}
525
+ unet_sd = self.unet.state_dict()
526
+ for name in self.unet.attn_processors.keys():
527
+ cross_attention_dim = None if name.endswith("attn1.processor") else self.unet.config.cross_attention_dim
528
+ if name.startswith("mid_block"):
529
+ hidden_size = self.unet.config.block_out_channels[-1]
530
+ elif name.startswith("up_blocks"):
531
+ block_id = int(name[len("up_blocks.")])
532
+ hidden_size = list(reversed(self.unet.config.block_out_channels))[block_id]
533
+ elif name.startswith("down_blocks"):
534
+ block_id = int(name[len("down_blocks.")])
535
+ hidden_size = self.unet.config.block_out_channels[block_id]
536
+ if cross_attention_dim is None:
537
+ attn_procs[name] = AttnProcessor()
538
+ else:
539
+ layer_name = name.split(".processor")[0]
540
+ weights = {
541
+ "to_k_ip.weight": unet_sd[layer_name + ".to_k.weight"],
542
+ "to_v_ip.weight": unet_sd[layer_name + ".to_v.weight"],
543
+ }
544
+ attn_procs[name] = IPAttnProcessor(hidden_size=hidden_size, cross_attention_dim=cross_attention_dim, num_tokens=num_tokens)
545
+ attn_procs[name].load_state_dict(weights)
546
+ self.unet.set_attn_processor(attn_procs)
547
+
548
+ adapter_modules = nn.ModuleList(self.unet.attn_processors.values())
549
+ self.ip_adapter = IPAdapter(self.unet, self.image_proj_model, adapter_modules, self.ip_adapter_path)
550
+ self.ip_adapter.to(self.device, dtype=self.weight_dtype)
551
+ self.ip_adapter.requires_grad_(False)
552
+
553
+ # Freeze all
554
+ for model in [self.vae, self.unet, self.text_encoder_one, self.text_encoder_two, self.mask_cls, self.bbx_reg, self.controlnet]:
555
+ model.requires_grad_(False)
556
+
557
+ # Ensure all attention processors are on same device
558
+ for proc in self.unet.attn_processors.values():
559
+ for k, v in proc.state_dict().items():
560
+ proc._parameters[k] = v.to(self.device, dtype=self.weight_dtype)
561
+
562
+ self.post_model = PostProcess(infe_steps=50).cpu()
563
+ self.post_model.load_state_dict(load_state_dict(self.ppp_weight_path, location='cuda'), strict=False)
564
+ self.post_model = self.post_model.to(self.device)
565
+ self.post_model.eval()
566
+
567
+ def post_process(self, decoded, shadowfree_img, object_mask):
568
+ """
569
+ decoded: np.uint8 HWC [0-255] RGB
570
+ shadowfree_img: np.uint8 HWC [0-255] RGB
571
+ object_mask: np.uint8 HW [0-255]
572
+ """
573
+ width, height = 512, 512
574
+ decoded_512 = cv2.resize(decoded, (width, height))
575
+ shadowfree_img_512 = cv2.resize(shadowfree_img, (width, height))
576
+ object_mask_512 = cv2.resize(object_mask, (width, height))
577
+
578
+ comp_img_scaled = shadowfree_img_512.astype(np.float32)/127.5 - 1.0
579
+ obj_mask = object_mask_512[:,:,np.newaxis].astype(np.float32)/255.0
580
+ image_scaled = decoded_512.astype(np.float32)/127.5 - 1.0
581
+
582
+ comp_img_scaled = torch.from_numpy(comp_img_scaled).float().unsqueeze(0).to(self.device)
583
+ obj_mask = torch.from_numpy(obj_mask).float().unsqueeze(0).to(self.device)
584
+ image_scaled = torch.from_numpy(image_scaled).float().unsqueeze(0).to(self.device)
585
+
586
+ input_tensor = torch.concat([image_scaled, comp_img_scaled, obj_mask], dim=-1).permute(0,3,1,2)
587
+ null_timesteps = torch.zeros(1, device=self.device)
588
+
589
+ with torch.no_grad():
590
+ output = self.post_model.post_process_net(input_tensor, timesteps=null_timesteps)
591
+ output = output.permute(0,2,3,1) # [B,H,W,C]
592
+
593
+ pred_mask = torch.greater_equal(output[:,:,:,3],0).float()
594
+ pred_mask = pred_mask.unsqueeze(-1) # [B,H,W,1]
595
+
596
+ adjusted_img = torch.clamp(image_scaled, -1.,1)
597
+ adjusted_img = (adjusted_img + 1)/2.0 * 255
598
+
599
+ comp_img_tensor = (comp_img_scaled +1)/2.0 * 255
600
+ new_composite = adjusted_img * pred_mask + (1 - pred_mask) * comp_img_tensor
601
+ new_composite = new_composite.squeeze(0).cpu().numpy().astype(np.uint8)
602
+
603
+ new_composite_512 = cv2.resize(new_composite, (512,512))
604
+ return new_composite_512
605
+
606
+ def __call__(self, shadowfree_img, object_mask, number=5):
607
+ """
608
+ Generate shadow for foreground object.
609
+
610
+ Args:
611
+ shadowfree_img (str | numpy.ndarray): The path to composite image or composite image in ndarray form.
612
+ object_mask (str | numpy.ndarray): The path to foreground object mask or foreground object mask in ndarray form.
613
+ number (int): Number of images to be inferenced. default: 5.
614
+
615
+ Returns:
616
+ generated_images (list): A list of images with generated foreground shadows. Each image is in ndarray form with a shape of 512x512x3
617
+
618
+ """
619
+
620
+ test_dataset = TestDataset(
621
+ shadowfree_img=shadowfree_img,
622
+ object_mask=object_mask,
623
+ text_encoders=[self.text_encoder_one, self.text_encoder_two],
624
+ tokenizers=[self.tokenizer_one, self.tokenizer_two],
625
+ caption_column='text'
626
+ )
627
+
628
+ test_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=False, batch_size=1, num_workers=self.args.dataloader_num_workers)
629
+
630
+ preds = []
631
+ with torch.no_grad():
632
+ for batch in tqdm(test_dataloader, desc="Testing", unit="batch"):
633
+ batch_name = batch["name"]
634
+ for repeat in range(number):
635
+ # Move all tensors to device & float32
636
+ pixel_values = batch["pixel_values"].to(self.device, dtype=self.weight_dtype)
637
+ geometry_input = batch["conditioning_pixel_values"].to(self.device, dtype=self.weight_dtype)
638
+ bbx_mask = batch['bbx'].to(self.device, dtype=self.weight_dtype)
639
+ fg_instance_bbx = batch['fg'].to(self.device, dtype=self.weight_dtype)
640
+ added_conditions = {k: v.to(self.device, dtype=self.weight_dtype) for k,v in batch["unet_added_conditions"].items()}
641
+ prompt_ids = batch["prompt_ids"].to(self.device, dtype=self.weight_dtype)
642
+ mask_embeddings = batch['embeddings'].to(self.device, dtype=self.weight_dtype)
643
+
644
+ # Encode image
645
+ latents = self.vae.encode(pixel_values).latent_dist.sample() * self.vae.config.scaling_factor
646
+ latents = latents.to(self.device, dtype=self.weight_dtype)
647
+
648
+ # Add noise
649
+ noise = torch.randn_like(latents)
650
+ timesteps = torch.randint(0, self.noise_scheduler.config.num_train_timesteps, (latents.shape[0],), device=self.device).long()
651
+ noisy_latents = self.noise_scheduler.add_noise(latents, noise, timesteps)
652
+ latents = noisy_latents
653
+
654
+ # Generate bounding boxes
655
+ pred_t = self.bbx_reg(geometry_input)
656
+ img_height, img_width = 512, 512
657
+ pred_bbx = pred_t.new(pred_t.shape)
658
+ pred_bbx[:,0] = pred_t[:,0] * fg_instance_bbx[:,2] + fg_instance_bbx[:,0]
659
+ pred_bbx[:,1] = pred_t[:,1] * fg_instance_bbx[:,3] + fg_instance_bbx[:,1]
660
+ pred_bbx[:,2] = fg_instance_bbx[:,2] * torch.exp(pred_t[:,2])
661
+ pred_bbx[:,3] = fg_instance_bbx[:,3] * torch.exp(pred_t[:,3])
662
+ pred_bbx[:,4] = pred_t[:,4] * 180 / np.pi + fg_instance_bbx[:,4]
663
+ for i in range(pred_bbx.shape[0]):
664
+ if pred_bbx[i,4] > 0:
665
+ temp = pred_bbx[i,2]
666
+ pred_bbx[i,2] = pred_bbx[i,3]
667
+ pred_bbx[i,3] = temp
668
+ pred_bbx[i,4] -= 90
669
+ x,y,w,h,theta = pred_bbx[i]
670
+ box = ((x.item(),y.item()),(w.item(),h.item()),theta.item())
671
+ box_points = cv2.boxPoints(box)
672
+ box_points = np.clip(box_points, 0, [img_width-1,img_height-1])
673
+ cv2.fillPoly(bbx_mask[i].cpu().numpy().astype(np.uint8), [np.int32(box_points)], 1)
674
+ bbx_region = bbx_mask.unsqueeze(1).to(self.device, dtype=self.weight_dtype)
675
+
676
+ controlnet_image = torch.cat((geometry_input, bbx_region), 1)
677
+
678
+ # Set scheduler timesteps
679
+ num_inference_steps = 50
680
+ self.noise_scheduler.set_timesteps(num_inference_steps)
681
+ self.noise_scheduler.timesteps = self.noise_scheduler.timesteps.to(self.device)
682
+
683
+ # Denoising loop
684
+ for t in tqdm(self.noise_scheduler.timesteps, desc=f"Denoising {batch_name[0]}_{repeat}", leave=False):
685
+ # ControlNet
686
+ down_block_res_samples, mid_block_res_sample = self.controlnet(
687
+ latents, t, encoder_hidden_states=prompt_ids, added_cond_kwargs=added_conditions,
688
+ controlnet_cond=controlnet_image, return_dict=False
689
+ )
690
+
691
+ # Mask embeddings adjustment
692
+ mask_label = self.mask_cls(geometry_input)
693
+ with open(self.cls_label_path, 'rb') as f:
694
+ centroid_dict = pickle.load(f)
695
+ _, top64_label = torch.topk(mask_label, 64, largest=True, sorted=False)
696
+ for i in range(mask_embeddings.shape[0]):
697
+ for j in range(top64_label.shape[1]):
698
+ label = top64_label[i,j].item()
699
+ if label in centroid_dict:
700
+ mask_embeddings[i,j,:] += torch.tensor(centroid_dict[label], dtype=torch.float32, device=self.device)
701
+
702
+ # IP Adapter
703
+ model_pred = self.ip_adapter(
704
+ latents,
705
+ t,
706
+ encoder_hidden_states=prompt_ids,
707
+ added_cond_kwargs=added_conditions,
708
+ down_block_additional_residuals=[sample.to(self.device, dtype=self.weight_dtype) for sample in down_block_res_samples],
709
+ mid_block_additional_residual=mid_block_res_sample.to(self.device, dtype=self.weight_dtype),
710
+ mask_embeddings=mask_embeddings
711
+ )
712
+
713
+ # Update latents
714
+ latents = self.noise_scheduler.step(model_output=model_pred, timestep=t, sample=latents).prev_sample
715
+
716
+ # Decode
717
+ latents = latents / self.vae.config.scaling_factor
718
+ decoded = self.vae.decode(latents).sample
719
+ decoded = (decoded.clamp(-1,1)+1)/2
720
+ decoded = decoded.cpu().permute(0,2,3,1).numpy()
721
+ decoded = (decoded*255).astype(np.uint8)[0]
722
+
723
+ # shadowfree_img_cv = cv2.imread(shadowfree_img)
724
+ # shadowfree_img_cv = cv2.cvtColor(shadowfree_img_cv, cv2.COLOR_BGR2RGB)
725
+ # object_mask_cv = cv2.imread(object_mask, cv2.IMREAD_GRAYSCALE)
726
+
727
+ if isinstance(shadowfree_img, str):
728
+ shadowfree_img_cv = cv2.imread(shadowfree_img)
729
+ if shadowfree_img_cv is None:
730
+ raise ValueError(f"Image not found: {shadowfree_img}")
731
+ shadowfree_img_cv = cv2.cvtColor(shadowfree_img_cv, cv2.COLOR_BGR2RGB)
732
+ elif isinstance(shadowfree_img, np.ndarray):
733
+ shadowfree_img_cv = cv2.cvtColor(shadowfree_img, cv2.COLOR_BGR2RGB)
734
+ else:
735
+ raise TypeError(f"shadowfree_img must be str or np.ndarray, got {type(shadowfree_img)}")
736
+
737
+ # 处理 object_mask
738
+ if isinstance(object_mask, str):
739
+ object_mask_cv = cv2.imread(object_mask, cv2.IMREAD_GRAYSCALE)
740
+ if object_mask_cv is None:
741
+ raise ValueError(f"Mask not found: {object_mask}")
742
+ elif isinstance(object_mask, np.ndarray):
743
+ object_mask_cv = object_mask
744
+ else:
745
+ raise TypeError(f"object_mask must be str or np.ndarray, got {type(object_mask)}")
746
+
747
+
748
+
749
+ decoded_post = self.post_process(decoded, shadowfree_img_cv, object_mask_cv)
750
+ decoded_post = cv2.cvtColor(decoded_post, cv2.COLOR_RGB2BGR)
751
+
752
+ preds.append(decoded_post)
753
+
754
+ return preds