o
    pi                     @  sL   d dl mZ d dlmZ d dlZd dlmZ d
ddZG dd	 d	ejZdS )    )annotations)OrderedDictN)nn   c                 C  sB   |du r|}t |t| |d  | | }|d|  k r||7 }|S )a  
    This function ensures that all layers have a channel number that is divisible by divisor.
    You can also see at https://github.com/keras-team/keras/blob/8ecef127f70db723c158dbe9ed3268b3d610ab55/keras/applications/mobilenet_v2.py#L505

    Args:
        divisor (int, optional): The divisor for number of channels. Default: 8.
        min_value (int, optional): The minimum value of number of channels, if it is None,
            the default is divisor. Default: None.
    N   g?)maxint)vZdivisorZ	min_valuenew_v r   b/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/paddle/vision/models/_utils.py_make_divisible   s   
r   c                      s4   e Zd ZU dZded< d fdd	Zd
d Z  ZS )IntermediateLayerGetterax  
    Layer wrapper that returns intermediate layers from a model.

    It has a strong assumption that the layers have been registered into the model in the
    same order as they are used. This means that one should **not** reuse the same nn.Layer
    twice in the forward if you want this to work.

    Additionally, it is only able to query sublayer that are directly assigned to the model.
    So if `model` is passed, `model.feature1` can be returned, but not `model.feature1.layer2`.

    Args:

        model (nn.Layer): Model on which we will extract the features.
        return_layers (Dict[name, new_name]): A dict containing the names of the layers for
        which the activations will be returned as the key of the dict, and the value of the
        dict is the name of the returned activation (which the user can specify).

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> m = paddle.vision.models.resnet18(pretrained=False)

            >>> # extract layer1 and layer3, giving as names `feat1` and feat2`
            >>> new_m = paddle.vision.models._utils.IntermediateLayerGetter(m,
            ...     {'layer1': 'feat1', 'layer3': 'feat2'})
            >>> out = new_m(paddle.rand([1, 3, 224, 224]))
            >>> print([(k, v.shape) for k, v in out.items()])
            [('feat1', [1, 64, 56, 56]), ('feat2', [1, 256, 14, 14])]
    dict[str, str]return_layersmodelnn.LayerreturnNonec                   s   t |dd | D std|}dd | D }t }| D ]\}}|||< ||v r3||= |s7 nq$t | || _d S )Nc                 S  s   g | ]\}}|qS r   r   ).0name_r   r   r   
<listcomp>N   s    z4IntermediateLayerGetter.__init__.<locals>.<listcomp>z&return_layers are not present in modelc                 S  s   i | ]\}}t |t |qS r   )str)r   kr	   r   r   r   
<dictcomp>R   s    z4IntermediateLayerGetter.__init__.<locals>.<dictcomp>)	setissubsetZnamed_children
ValueErroritemsr   super__init__r   )selfr   r   Zorig_return_layersZlayersr   module	__class__r   r   r!   L   s    
z IntermediateLayerGetter.__init__c                 C  s   t  }|  D ]>\}}t|tjr|jdks-t| dkr3t| d tjr3|jdkr3t	|d}||}|| j
v rE| j
| }|||< q|S )N   r      )r   r   
isinstancer   ZLinearndimlenZ	sublayerspaddleflattenr   )r"   xoutr   r#   Zout_namer   r   r   forward^   s   


zIntermediateLayerGetter.forward)r   r   r   r   r   r   )__name__
__module____qualname____doc____annotations__r!   r/   __classcell__r   r   r$   r   r   )   s
   
  r   )r   N)	
__future__r   collectionsr   r+   r   r   Z	LayerDictr   r   r   r   r   <module>   s   
