-
Notifications
You must be signed in to change notification settings - Fork 244
/
Copy pathCPAM.py
86 lines (64 loc) · 2.96 KB
/
CPAM.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import torch
import torch.nn as nn
import math
#论文:ASF-YOLO: A Novel YOLO Model with Attentional Scale Sequence Fusion for Cell Instance Segmentation(IMAVIS)
#论文地址:https://arxiv.org/abs/2312.06458
class channel_att(nn.Module):
def __init__(self, channel, b=1, gamma=2):
super(channel_att, self).__init__()
kernel_size = int(abs((math.log(channel, 2) + b) / gamma))
kernel_size = kernel_size if kernel_size % 2 else kernel_size + 1
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size=kernel_size, padding=(kernel_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
y = self.avg_pool(x) # 自适应平均池化
y = y.squeeze(-1)
y = y.transpose(-1, -2)
y = self.conv(y).transpose(-1, -2).unsqueeze(-1) # 1D卷积
y = self.sigmoid(y) # Sigmoid激活
return x * y.expand_as(x) # 通道逐元素相乘
class local_att(nn.Module):
def __init__(self, channel, reduction=16):
super(local_att, self).__init__()
self.conv_1x1 = nn.Conv2d(in_channels=channel, out_channels=channel // reduction, kernel_size=1, stride=1,
bias=False)
self.relu = nn.ReLU()
self.bn = nn.BatchNorm2d(channel // reduction)
self.F_h = nn.Conv2d(in_channels=channel // reduction, out_channels=channel, kernel_size=1, stride=1,
bias=False)
self.F_w = nn.Conv2d(in_channels=channel // reduction, out_channels=channel, kernel_size=1, stride=1,
bias=False)
self.sigmoid_h = nn.Sigmoid()
self.sigmoid_w = nn.Sigmoid()
def forward(self, x):
_, _, h, w = x.size()
x_h = torch.mean(x, dim=3, keepdim=True).permute(0, 1, 3, 2)
x_w = torch.mean(x, dim=2, keepdim=True)
x_cat_conv_relu = self.relu(self.bn(self.conv_1x1(torch.cat((x_h, x_w), 3))))
x_cat_conv_split_h, x_cat_conv_split_w = x_cat_conv_relu.split([h, w], 3)
s_h = self.sigmoid_h(self.F_h(x_cat_conv_split_h.permute(0, 1, 3, 2)))
s_w = self.sigmoid_w(self.F_w(x_cat_conv_split_w))
out = x * s_h.expand_as(x) * s_w.expand_as(x)
return out
#Channel and Position Attention Mechanism (CPAM)
class CPAM(nn.Module):
def __init__(self, ch):
super().__init__()
self.channel_att = channel_att(ch)
self.local_att = local_att(ch)
def forward(self, x):
input1,input2 = x[0],x[1]
input1 = self.channel_att(input1)
x = input1 + input2
x = self.local_att(x)
return x
if __name__ == '__main__':
block = CPAM(128)
input1 = torch.randn(1, 128, 32, 32) # B C H W
input2 = torch.randn(1, 128, 32, 32)
inputs = [input1, input2]
output = block(inputs)
print(input1.size())
print(input2.size())
print(output.size())