
    g                        d Z ddlmZ ddlmZ ddlZddlmZ  G d dej                        Z G d d	ej                        Z	 G d
 dej                        Z
y)zCopyright (C) 2024 Apple Inc. All Rights Reserved.

Dense Prediction Transformer Decoder architecture.

Implements a variant of Vision Transformers for Dense Prediction, https://arxiv.org/abs/2103.13413
    )annotations)IterableN)nnc                  4     e Zd ZdZ	 	 	 	 d fdZddZ xZS )MultiresConvDecoderz'Decoder for multi-resolution encodings.c                   t         |           t        |      | _        || _        || _        t        | j                        }| j                  d   |k7  r&t        j                  | j                  d   |dd      nt        j                         }|g}t        d|      D ]9  }|j                  t        j                  | j                  |   |dddd             ; t        j                  |      | _        g }t        |      D ]"  }|j                  t        ||dk7  d             $ t        j                  |      | _        y)	zInitialize multiresolution convolutional decoder.

        Args:
        ----
            dims_encoder: Expected dims at each level from the encoder.
            dim_decoder: Dim of decoder features.

        r      F)kernel_sizebias   r
   stridepaddingr   )num_featuresdeconv
batch_normN)super__init__listdims_encoderdim_decoderdim_outlenr   Conv2dIdentityrangeappend
ModuleListconvsFeatureFusionBlock2dfusions)	selfr   r   num_encodersconv0r   ir!   	__class__s	           F/home/cameronsmith/repos/ml-depth-pro/src/depth_pro/network/decoder.pyr   zMultiresConvDecoder.__init__   s0    	 .&"4,,-   #{2 IId''*KQUS 	 q,' 
	ALL		%%a( !	
	 ]]5)
|$ 	ANN$!,F$	 }}W-    c                b   t        |      }t        | j                        }||k7  rt        d| d|dz    d       | j                  d   |d         }|} | j                  d   |      }t        |dz
  dd      D ]0  } | j                  |   ||         } | j                  |   ||      }2 ||fS )z&Decode the multi-resolution encodings.zGot encoder output levels=z, expected levels=r	   .   )r   r   
ValueErrorr   r!   r   )r"   	encodings
num_levelsr#   featureslowres_featuresr%   
features_is           r'   forwardzMultiresConvDecoder.forwardJ   s    ^
4,,-%,ZL8J<XY>JZZ[\  "4::b>)B-0"#4<<#H-zA~r2. 	=A&Ay|4J&t||Ax<H	= ((r(   )r   zIterable[int]r   int)r.   torch.Tensorreturnr5   __name__
__module____qualname____doc__r   r3   __classcell__r&   s   @r'   r   r      s#    15.#5. 5.n)r(   r   c                  .     e Zd ZdZdd fdZddZ xZS )ResidualBlocka  Generic implementation of residual blocks.

    This implements a generic residual block from
        He et al. - Identity Mappings in Deep Residual Networks (2016),
        https://arxiv.org/abs/1603.05027
    which can be further customized via factory functions.
    c                >    t         |           || _        || _        y)zInitialize ResidualBlock.N)r   r   residualshortcut)r"   rA   rB   r&   s      r'   r   zResidualBlock.__init__i   s      r(   c                h    | j                  |      }| j                  | j                  |      }||z   S )zApply residual block.)rA   rB   )r"   xdelta_xs      r'   r3   zResidualBlock.forwardo   s2    --"==$a A7{r(   N)rA   z	nn.ModulerB   znn.Module | Noner6   None)rD   r5   r6   r5   r7   r=   s   @r'   r?   r?   `   s    !r(   r?   c                  P     e Zd ZdZ	 	 d	 	 	 	 	 d fdZdddZed	d       Z xZS )
r    zFeature fusion for DPT.c                V   t         |           | j                  ||      | _        | j                  ||      | _        || _        |r t        j                  ||dddd      | _        t        j                  ||dddd      | _
        t        j                  j                         | _        y)	a  Initialize feature fusion block.

        Args:
        ----
            num_features: Input and output dimensions.
            deconv: Whether to use deconv before the final output conv.
            batch_norm: Whether to use batch normalization in resnet blocks.

        r,   r   F)in_channelsout_channelsr
   r   r   r   r	   Tr   N)r   r   _residual_blockresnet1resnet2
use_deconvr   ConvTranspose2dr   r   out_conv	quantizedFloatFunctionalskip_add)r"   r   r   r   r&   s       r'   r   zFeatureFusionBlock2d.__init__|   s     	++L*E++L*E ,,()DK 		
 446r(   c                    |}|-| j                  |      }| j                  j                  ||      }| j                  |      }| j                  r| j                  |      }| j                  |      }|S )z Process and fuse input features.)rM   rT   addrN   rO   r   rQ   )r"   x0x1rD   ress        r'   r3   zFeatureFusionBlock2d.forward   sd    >,,r"C!!!S)ALLO??AAMM!r(   c                t     d fd}t        j                  g  | |       | |       }t        |      S )zCreate a residual block.c           	         t        j                  d      t        j                  ddd|       g}|r$|j                  t        j                  |              |S )NFr   r	   r   )r   ReLUr   r   BatchNorm2d)dimr   layersr   s      r'   _create_blockz;FeatureFusionBlock2d._residual_block.<locals>._create_block   sT    		   !'
F bnnS12Mr(   )r^   r   )r^   r4   r   boolr6   zlist[nn.Module])r   
Sequentialr?   )r   r   r`   rA   s   `   r'   rL   z$FeatureFusionBlock2d._residual_block   sC    	  == 
|
C
|
C
 X&&r(   )FF)r   r4   r   ra   r   ra   rF   )rW   r5   rX   ztorch.Tensor | Noner6   r5   )r   r4   r   ra   )	r8   r9   r:   r;   r   r3   staticmethodrL   r<   r=   s   @r'   r    r    y   sI    !
  	(7(7 (7 	(7T  ' 'r(   r    )r;   
__future__r   typingr   torchr   Moduler   r?   r     r(   r'   <module>ri      sM    #   M)")) M)`BII 2U'299 U'r(   