# modified from https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py import torch import torch.nn as nn import torch.nn.functional as F from einops import rearrange import math from torchvision.utils import save_image import torchvision.transforms as T def get_mask_from_cross(attn_processors): reference_masks = [] for attn_processor in attn_processors.values(): if isinstance(attn_processor, IPAttnProcessor): reference_masks.append(attn_processor.mask_i) mask = torch.cat(reference_masks,dim=1).mean(dim=1) mask = (mask-mask.min())/(mask.max()-mask.min()) mask = (mask>0.2).to(torch.float32)*mask mask = (mask-mask.min())/(mask.max()-mask.min()) return mask.unsqueeze(1) class IPAttnProcessor(nn.Module): r""" Attention processor for IP-Adapater. Args: hidden_size (`int`): The hidden size of the attention layer. cross_attention_dim (`int`): The number of channels in the `encoder_hidden_states`. scale (`float`, defaults to 1.0): the weight scale of image prompt. num_tokens (`int`, defaults to 4 when do ip_adapter_plus it should be 16): The context length of the image features. """ def __init__(self, hidden_size, cross_attention_dim=None, scale=1.0, num_tokens=4): super().__init__() self.hidden_size = hidden_size self.cross_attention_dim = cross_attention_dim self.scale = scale self.num_tokens = num_tokens self.to_k_ip = nn.Linear(cross_attention_dim or hidden_size, hidden_size, bias=False) self.to_v_ip = nn.Linear(cross_attention_dim or hidden_size, hidden_size, bias=False) self.store_attn = None self.enabled = True self.mode = 'inject' self.subject_idxs = None self.mask_i = None self.mask_ig_prev = None def __call__( self, attn, hidden_states, encoder_hidden_states=None, attention_mask=None, temb=None, ): residual = hidden_states 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 ) attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size) 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 else: # get encoder_hidden_states, ip_hidden_states end_pos = encoder_hidden_states.shape[1] - self.num_tokens encoder_hidden_states, ip_hidden_states = encoder_hidden_states[:, :end_pos, :], encoder_hidden_states[:, end_pos:, :] if 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) query = attn.head_to_batch_dim(query) key = attn.head_to_batch_dim(key) value = attn.head_to_batch_dim(value) attention_probs = attn.get_attention_scores(query, key, attention_mask) hidden_states = torch.bmm(attention_probs, value) hidden_states = attn.batch_to_head_dim(hidden_states) # for ip-adapter if self.enabled: if self.mode == 'inject' or self.mode == 'masked_generation': ip_key = self.to_k_ip(ip_hidden_states.to(torch.float16)) ip_value = self.to_v_ip(ip_hidden_states.to(torch.float16)) ip_key = attn.head_to_batch_dim(ip_key) ip_value = attn.head_to_batch_dim(ip_value) ip_attention_probs = attn.get_attention_scores(query, ip_key.to(torch.float32), None) ip_hidden_states = torch.bmm(ip_attention_probs, ip_value.to(torch.float32)) ip_hidden_states = attn.batch_to_head_dim(ip_hidden_states) if (self.mask_ig_prev is not None) and self.mode == 'masked_generation': mask_ig_prev = rearrange(F.interpolate(self.mask_ig_prev,size=int(math.sqrt(query.shape[1]))),"b c h w -> b (h w) c") if not mask_ig_prev.shape[0]==ip_hidden_states.shape[0]: mask_ig_prev = mask_ig_prev.repeat(2,1,1) ip_hidden_states = ip_hidden_states * mask_ig_prev hidden_states = hidden_states + self.scale * ip_hidden_states if self.mode == 'extract' or self.mode == 'masked_generation': subject_idxs = self.subject_idxs*2 if not (hidden_states.shape[0] == len(self.subject_idxs)) else self.subject_idxs assert (hidden_states.shape[0] == len(subject_idxs)) attentions = rearrange(attention_probs, '(b h) n d -> b h n d', h=8).mean(1) attn_extracted = [attentions[i, :, subject_idxs[i]].sum(-1) for i in range(hidden_states.shape[0])] attn_extracted = [(atn-atn.min())/(atn.max()-atn.min()) for atn in attn_extracted] attn_extracted = torch.stack(attn_extracted, dim=0) attn_extracted = rearrange(attn_extracted, 'b (h w) -> b h w', h=int(math.sqrt(attention_probs.shape[1]))) attn_extracted = torch.clamp(F.interpolate(attn_extracted.unsqueeze(1),size=512),min=0,max=1) self.mask_i = attn_extracted # linear proj hidden_states = attn.to_out[0](hidden_states) # dropout 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) return hidden_states ### added for self attention class IPAttnProcessor_Self(nn.Module): r""" Attention processor for IP-Adapater. (But for self attention) Args: hidden_size (`int`): The hidden size of the attention layer. cross_attention_dim (`int`): The number of channels in the `encoder_hidden_states`. scale (`float`, defaults to 1.0): the weight scale of image prompt. num_tokens (`int`, defaults to 4 when do ip_adapter_plus it should be 16): The context length of the image features. """ def __init__(self, hidden_size, cross_attention_dim=None, scale=1.0, num_tokens=4): super().__init__() self.hidden_size = hidden_size self.cross_attention_dim = cross_attention_dim self.scale = scale self.num_tokens = num_tokens self.to_k_ip = nn.Linear(hidden_size, hidden_size, bias=False) self.to_v_ip = nn.Linear(hidden_size, hidden_size, bias=False) self.scale_learnable = torch.nn.Parameter(torch.zeros(1),requires_grad=True) self.enabled = True self.mode = 'extract' self.store_ks, self.store_vs = [], [] self.mask_id, self.mask_ig = None, None def __call__( self, attn, hidden_states, encoder_hidden_states=None, attention_mask=None, temb=None, ): 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 ) attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size) 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 else: end_pos = encoder_hidden_states.shape[1] - self.num_tokens encoder_hidden_states, ip_hidden_states = encoder_hidden_states[:, :end_pos, :], encoder_hidden_states[:, end_pos:, :] if attn.norm_cross: encoder_hidden_states = attn.norm_encoder_hidden_states(encoder_hidden_states) key_0 = attn.to_k(encoder_hidden_states) value_0 = attn.to_v(encoder_hidden_states) query = attn.head_to_batch_dim(query) key = attn.head_to_batch_dim(key_0) value = attn.head_to_batch_dim(value_0) attention_probs = attn.get_attention_scores(query, key, attention_mask) hidden_states = torch.bmm(attention_probs, value) hidden_states = attn.batch_to_head_dim(hidden_states) if self.enabled: if self.mode == 'extract': ks, vs = attn.head_to_batch_dim(self.to_k_ip(key_0)), attn.head_to_batch_dim(self.to_v_ip(value_0)) self.store_ks, self.store_vs = self.store_ks+[ks], self.store_vs+[vs] self.store_ks, self.store_vs = torch.cat(self.store_ks,dim=0), torch.cat(self.store_vs,dim=0) if self.mode == 'masked_generation': if not self.store_ks.shape[0]==query.shape[0]: self.store_ks,self.store_vs = self.store_ks.repeat(2,1,1), self.store_vs.repeat(2,1,1) mask_id = self.mask_id.clone() mask_id.masked_fill_(self.mask_id==False, -torch.finfo(mask_id.dtype).max) mask_id = rearrange(F.interpolate(mask_id,size=int(math.sqrt(query.shape[1]))),"b c h w -> b c (h w)").repeat(1,query.shape[1],1) mask_id = mask_id.repeat(8,1,1) # 8 is head dim if not mask_id.shape[0]==int(query.shape[0]): mask_id = mask_id.repeat(2,1,1) attention_probs_ref = attn.get_attention_scores(query, self.store_ks, mask_id.to(query.dtype)) hidden_states_ref = torch.bmm(attention_probs_ref, self.store_vs) hidden_states_ref = attn.batch_to_head_dim(hidden_states_ref) scale = self.scale.repeat(int(batch_size/self.scale.shape[0])).unsqueeze(-1).unsqueeze(-1) if type(self.scale)==torch.Tensor else self.scale if self.mask_ig == None: hidden_states = hidden_states + scale * hidden_states_ref * self.scale_learnable else: mask_ig = rearrange(F.interpolate(self.mask_ig,size=int(math.sqrt(query.shape[1]))),"b c h w -> b (h w) c") if not mask_ig.shape[0]==hidden_states_ref.shape[0]: mask_ig = mask_ig.repeat(2,1,1) hidden_states = hidden_states + scale * hidden_states_ref * mask_ig * self.scale_learnable # linear proj hidden_states = attn.to_out[0](hidden_states) # dropout 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) return hidden_states