o
    ߥiU                     @   sh   d Z ddlmZmZmZ ddlZddlmZ ddlm  m	Z
 G dd dZdd ZG dd	 d	eZdS )
zx
Part of the implementation is borrowed and modified from LaMa, publicly available at
https://github.com/saic-mdal/lama
    )DictOptionalTupleNc                   @   s   e Zd ZdejdejdejdejfddZdejdejdejdejfddZ		ddejdejd
ejdejde	ej de
ejeeejf f fddZ		ddejdejd
ejdejde	ej de
ejeeejf f fddZdd Zd	S )BaseAdversarialLoss
real_batch
fake_batch	generatordiscriminatorc                 C      dS )a  
        Prepare for generator step
        :param real_batch: Tensor, a batch of real samples
        :param fake_batch: Tensor, a batch of samples produced by generator
        :param generator:
        :param discriminator:
        :return: None
        N selfr   r   r   r	   r   r   m/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/cv/image_inpainting/modules/adversarial.pypre_generator_step       z&BaseAdversarialLoss.pre_generator_stepc                 C   r
   )a  
        Prepare for discriminator step
        :param real_batch: Tensor, a batch of real samples
        :param fake_batch: Tensor, a batch of samples produced by generator
        :param generator:
        :param discriminator:
        :return: None
        Nr   r   r   r   r   pre_discriminator_step   r   z*BaseAdversarialLoss.pre_discriminator_stepNdiscr_real_preddiscr_fake_predmaskreturnc                 C      t )a  
        Calculate generator loss
        :param real_batch: Tensor, a batch of real samples
        :param fake_batch: Tensor, a batch of samples produced by generator
        :param discr_real_pred: Tensor, discriminator output for real_batch
        :param discr_fake_pred: Tensor, discriminator output for fake_batch
        :param mask: Tensor, actual mask, which was at input of generator when making fake_batch
        :return: total generator loss along with some values that might be interesting to log
        NotImplementedErrorr   r   r   r   r   r   r   r   r   generator_loss&      z"BaseAdversarialLoss.generator_lossc                 C   r   )a+  
        Calculate discriminator loss and call .backward() on it
        :param real_batch: Tensor, a batch of real samples
        :param fake_batch: Tensor, a batch of samples produced by generator
        :param discr_real_pred: Tensor, discriminator output for real_batch
        :param discr_fake_pred: Tensor, discriminator output for fake_batch
        :param mask: Tensor, actual mask, which was at input of generator when making fake_batch
        :return: total discriminator loss along with some values that might be interesting to log
        r   r   r   r   r   discriminator_loss5   r   z&BaseAdversarialLoss.discriminator_lossc                 C   sp   |d usJ | j s||jdd  ksJ ||jdd  kr6| j r6| jdkr-t||}|S tj||| jd}|S )Nmaxpool)sizemode)allow_scale_maskshapemask_scale_modeFadaptive_max_pool2dinterpolate)r   r   r"   r   r   r   interpolate_maskD   s   
z$BaseAdversarialLoss.interpolate_maskN)__name__
__module____qualname__torchTensornnModuler   r   r   r   r   strr   r   r'   r   r   r   r   r      sH    



r   c                 C   sV   t  r$t jj|  |ddd }||jd djdddd  }nd}d|_	|S )	NT)outputsinputscreate_graphr         )dimF)
r,   is_grad_enabledautogradgradsumviewr"   normmeanrequires_grad)r   r   	grad_realgrad_penaltyr   r   r   
make_r1_gpP   s(   rB   c                   @   s   e Zd Z								dddZ		dd
ejdejdejdejdeejeeejf f f
ddZ	d
ejdejde
jde
jfddZ		dd
ejdejdejdejdeejeeejf f f
ddZd	S )NonSaturatingWithR1   r6   Fnearestr   Tc	           	      C   sL   || _ || _|s|rJ |s|rJ || _|| _|| _|| _|| _|| _d S r(   )gp_coefweightuse_unmasked_for_genuse_unmasked_for_discrmask_as_fake_targetr!   r#   extra_mask_weight_for_gen)	r   rF   rG   rJ   r!   r#   rK   rH   rI   r   r   r   __init__a   s   	
zNonSaturatingWithR1.__init__Nr   r   r   r   r   c                 C   sr   t | }| jr| jdks| js/| ||jdd  }| js$|| }nd|| j  }|| }| | j t	 fS )Nr   r   r6   )
r$   softplusrJ   rK   rH   r'   r"   r>   rG   dict)r   r   r   r   r   r   	fake_losspixel_weightsr   r   r   r   z   s   
z"NonSaturatingWithR1.generator_lossr   r	   c                 C   s
   d|_ d S )NT)r?   r   r   r   r   r      s   
z*NonSaturatingWithR1.pre_discriminator_stepc                 C   s   t | }t||| j }t |}| jr| jr7| ||jdd  }|| }| jr7|d| t |   }|| | }	t|	 |	 |d}
|		 |
fS )Nr   r6   )discr_real_outdiscr_fake_outdiscr_real_gp)
r$   rM   rB   rF   rI   rJ   r'   r"   rN   r>   )r   r   r   r   r   r   	real_lossrA   rO   sum_discr_lossmetricsr   r   r   r      s&   

z&NonSaturatingWithR1.discriminator_loss)rD   r6   FFrE   r   TTr(   )r)   r*   r+   rL   r,   r-   r   r   r0   r   r.   r/   r   r   r   r   r   r   rC   _   sB    


rC   )__doc__typingr   r   r   r,   torch.nnr.   torch.nn.functional
functionalr$   r   rB   rC   r   r   r   r   <module>   s    D