| import cv2 |
| import numpy as np |
| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
| from diffusers.models.attention_processor import Attention |
| from typing import Optional |
|
|
| from .layers import MIFusion, MIFusionPrototype |
| from .utils import get_masks, get_sigmoid |
|
|
|
|
| class AttnProcessor2_0(nn.Module): |
| r""" |
| Processor for implementing scaled dot-product attention (enabled by default if you're using PyTorch 2.0). |
| """ |
|
|
| def __init__(self, hidden_size=None, cross_attention_dim=None): |
| if not hasattr(F, "scaled_dot_product_attention"): |
| raise ImportError("AttnProcessor2_0 requires PyTorch 2.0, to use it, please upgrade PyTorch to 2.0.") |
| super().__init__() |
|
|
| def __call__( |
| self, |
| attn: Attention, |
| hidden_states: torch.Tensor, |
| encoder_hidden_states: Optional[torch.Tensor] = None, |
| attention_mask: Optional[torch.Tensor] = None, |
| temb: Optional[torch.Tensor] = None, |
| |
| bboxes=[], |
| obboxes=[], |
| embeds_pooler=None, |
| height=512, |
| width=512, |
| prototypes=None, |
| ref_features=None, |
| guidance_masks=None, |
| supplement_mask=None, |
| sigmoid_values=None, |
| in_box=None, |
| do_classifier_free_guidance=False, |
| |
| *args, |
| **kwargs, |
| ) -> torch.Tensor: |
|
|
| residual = hidden_states |
| if attn.spatial_norm is not None: |
| hidden_states = attn.spatial_norm(hidden_states, temb) |
|
|
| input_ndim = hidden_states.ndim |
|
|
| if input_ndim == 4: |
| batch_size, channel, height, width = hidden_states.shape |
| hidden_states = hidden_states.view(batch_size, channel, height * width).transpose(1, 2) |
|
|
| batch_size, sequence_length, _ = ( |
| hidden_states.shape if encoder_hidden_states is None else encoder_hidden_states.shape |
| ) |
|
|
| if attention_mask is not None: |
| attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size) |
| |
| |
| attention_mask = attention_mask.view(batch_size, attn.heads, -1, attention_mask.shape[-1]) |
|
|
| if attn.group_norm is not None: |
| hidden_states = attn.group_norm(hidden_states.transpose(1, 2)).transpose(1, 2) |
|
|
| query = attn.to_q(hidden_states) |
|
|
| if encoder_hidden_states is None: |
| encoder_hidden_states = hidden_states |
| elif attn.norm_cross: |
| encoder_hidden_states = attn.norm_encoder_hidden_states(encoder_hidden_states) |
|
|
| key = attn.to_k(encoder_hidden_states) |
| value = attn.to_v(encoder_hidden_states) |
|
|
| inner_dim = key.shape[-1] |
| head_dim = inner_dim // attn.heads |
|
|
| query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
|
|
| key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
| value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
|
|
| if attn.norm_q is not None: |
| query = attn.norm_q(query) |
| if attn.norm_k is not None: |
| key = attn.norm_k(key) |
|
|
| |
| |
| hidden_states = F.scaled_dot_product_attention( |
| query, key, value, attn_mask=attention_mask, dropout_p=0.0, is_causal=False |
| ) |
|
|
| hidden_states = hidden_states.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim) |
| hidden_states = hidden_states.to(query.dtype) |
|
|
| |
| hidden_states = attn.to_out[0](hidden_states) |
| |
| hidden_states = attn.to_out[1](hidden_states) |
|
|
| if input_ndim == 4: |
| hidden_states = hidden_states.transpose(-1, -2).reshape(batch_size, channel, height, width) |
|
|
| if attn.residual_connection: |
| hidden_states = hidden_states + residual |
|
|
| hidden_states = hidden_states / attn.rescale_output_factor |
|
|
| return hidden_states |
|
|
|
|
| class MaskedProcessor2_0(nn.Module): |
| def __init__(self, hidden_size, cross_attention_dim=None, |
| use_ea_attn=False, **kwargs): |
| super().__init__() |
| self.hidden_size = hidden_size |
| self.cross_attention_dim = cross_attention_dim |
| self.use_ea_attn = use_ea_attn |
| self.prototype_mode = use_ea_attn and (kwargs['phase'] == 'novel') and (kwargs.get('attn_prototype_switch') is True) |
| if self.prototype_mode: |
| self.fusion = MIFusionPrototype(hidden_size, context_dim=cross_attention_dim) |
| elif use_ea_attn: |
| self.fusion = MIFusion(hidden_size, context_dim=cross_attention_dim) |
| |
| |
| |
| def __call__( |
| self, |
| attn: Attention, |
| |
| |
| hidden_states, |
| encoder_hidden_states=None, |
| attention_mask=None, |
| bboxes=[], |
| obboxes=[], |
| embeds_pooler=None, |
| height=512, |
| width=512, |
| prototypes=None, |
| ref_features=None, |
| guidance_masks=None, |
| supplement_mask=None, |
| sigmoid_values=None, |
| in_box=None, |
| do_classifier_free_guidance=False, |
| ): |
|
|
| instance_num = len(obboxes[0]) |
|
|
| if not self.use_ea_attn: |
| |
| encoder_hidden_states = encoder_hidden_states[:2, ...] if do_classifier_free_guidance else encoder_hidden_states[:1, ...] |
|
|
| if self.use_ea_attn: |
| if do_classifier_free_guidance: |
| hidden_states = torch.cat([hidden_states[0:1], hidden_states[1:2].repeat(instance_num + 1, 1, 1)]) |
| image_token = hidden_states[1:] |
| else: |
| hidden_states = hidden_states.repeat(instance_num + 1, 1, 1) |
| image_token = hidden_states |
|
|
| batch_size, sequence_length, _ = hidden_states.shape |
|
|
| if attention_mask is not None: |
| attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size) |
| |
| |
| attention_mask = attention_mask.view(batch_size, attn.heads, -1, attention_mask.shape[-1]) |
|
|
| query = attn.to_q(hidden_states) |
| key = attn.to_k(encoder_hidden_states) |
| value = attn.to_v(encoder_hidden_states) |
|
|
| inner_dim = key.shape[-1] |
| head_dim = inner_dim // attn.heads |
|
|
| query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
|
|
| key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
| value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) |
|
|
| if attn.norm_q is not None: |
| query = attn.norm_q(query) |
| if attn.norm_k is not None: |
| key = attn.norm_k(key) |
|
|
| hidden_states = F.scaled_dot_product_attention( |
| query, key, value, attn_mask=attention_mask, dropout_p=0.0, is_causal=False |
| ) |
|
|
| hidden_states = hidden_states.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim) |
| hidden_states = hidden_states.to(query.dtype) |
| hidden_states = attn.to_out[0](hidden_states) |
| hidden_states = attn.to_out[1](hidden_states) |
|
|
| if not self.use_ea_attn: |
| return hidden_states |
|
|
| assert self.use_ea_attn |
|
|
| if do_classifier_free_guidance: |
| hidden_states_uncond, hidden_states = hidden_states[0:1], hidden_states[1:] |
|
|
| other_info = {} |
| other_info['image_token'] = image_token.unsqueeze(0) |
| other_info['context'] = encoder_hidden_states[1:, ...] if do_classifier_free_guidance else encoder_hidden_states |
| other_info['box'] = in_box |
| other_info['context_pooler'] = embeds_pooler |
| other_info['supplement_mask'] = supplement_mask |
| other_info['height'] = height |
| other_info['width'] = width |
| other_info['ref_features'] = ref_features |
| other_info['sigmoid_values'] = sigmoid_values |
| other_info['guidance_masks'] = guidance_masks |
| other_info['instance_num'] = instance_num |
| other_info['prototypes'] = prototypes |
|
|
| hidden_states = self.fusion(hidden_states.unsqueeze(0), |
| other_info=other_info) |
| |
|
|
| if do_classifier_free_guidance: |
| hidden_states = torch.cat([hidden_states_uncond, hidden_states]) |
| return hidden_states |
|
|
| |
| def set_processors(unet, **kwargs): |
| attn_processors = {} |
| for name, _ in unet.attn_processors.items(): |
| use_ea_attn = False |
| kwargs['attn_prototype_switch'] = False |
| cross_attention_dim = None if name.endswith("attn1.processor") else unet.config.cross_attention_dim |
| if name.startswith("mid_block"): |
| hidden_size = unet.config.block_out_channels[-1] |
| use_ea_attn = True |
| elif name.startswith("up_blocks"): |
| block_id = int(name[len("up_blocks.")]) |
| attention_id = int(name[len("up_blocks.2.attentions.")]) |
| hidden_size = list(reversed(unet.config.block_out_channels))[block_id] |
| if block_id == 1: |
| use_ea_attn = True |
| elif (block_id != 1) and (kwargs['phase'] == 'novel'): |
| use_ea_attn = True |
| kwargs['attn_prototype_switch'] = True |
| elif name.startswith("down_blocks"): |
| block_id = int(name[len("down_blocks.")]) |
| hidden_size = unet.config.block_out_channels[block_id] |
| if cross_attention_dim is not None: |
| attn_processors[name] = MaskedProcessor2_0(hidden_size=hidden_size, |
| cross_attention_dim=cross_attention_dim, |
| use_ea_attn=use_ea_attn, |
| **kwargs) |
| else: |
| attn_processors[name] = AttnProcessor2_0() |
| unet.set_attn_processor(attn_processors) |