最近要更新文本檢測的訓練模型,所以看了PSE的升級版PAN;
論文:https://arxiv.org/abs/1908.05900v1
代碼:https://github.com/WenmuZhou/PAN.pytorch
目錄
1.2.1 FPEM模塊(Feature Pyramid Enhancement Module)
1.2.2 FFM模塊(Feature Fusion Module)
1.該論文的主要方法介紹
1.1該方法的主體框架
該方法主體框架fig.3所示,功能上大概包括以下幾部分(b)Lightweight Backbone;(c)Fr,(d)~(e)FPEM,FFM,(f)Ff,loss計算 ;
作者的論文中的主幹網絡使用的是resnet18,由於主幹網絡使用的是resnet18,模型推理速度得到了提升,但是網絡小的時候,最終的感受野也比較小,從而特徵表徵能力也比較差,所以作者提出了segmentation head,高效利用輕量級網絡(resnet18)的特徵;segmentation head包括FPEM(Feature Pyramid Enhancement Module)和FFM(Feature Fusion Module);
FPEM:特點就是低計算消耗; 通過級聯操作,將輸入的不同尺度特徵更深,更強的表達能力(more expressive);
FFM:就是用於融合FPEMs產生的不同深度的特徵;
PAN預測得到文本區域(text region,fig.3),預測核(kernels, fig.3(h))用於區分不同的文本實例,同時也預測每個文本像素的相似矢量(similarity vector),希望相同文本實例的像素和kernel之間的距離越小越好;
1.2 分塊介紹主體功能
1.2.0 Fr作用
fig.3中從(b)的輕量級主幹網絡得到的卷積特徵conv2,conv3,conv4和conv5,與輸入圖片尺寸相比,尺寸變小了4倍,8倍,16倍,32倍(所以輸入樣本尺寸最好是32的倍數),通過Fr作用就是使用1*1的卷積,將所有的conv2,... ... ,conv5的通道數都變爲128,使用代碼操作:
conv_out = 128
# reduce layers
self.reduce_conv_c2 = nn.Sequential(
nn.Conv2d(in_channels=backbone_out_channels[0], out_channels=conv_out, kernel_size=1),
nn.BatchNorm2d(conv_out),
nn.ReLU()
)
疑問1,這個128可不可以變化了,變小,變大會帶來什麼影響?
文中作者是使用128,是爲了得到一個瘦的特徵金字塔Fr,其實(b)處c2,c3,c4,c5通道數分別是64,128,256,512;
1.2.1 FPEM模塊(Feature Pyramid Enhancement Module)
FPEM主要包括功能模塊:up-scale enchancemet和down-scale enchancement; FPEM中使用了可分離卷積,總言之FPEM就有兩個優點:1)級聯不同尺度的特徵,加強了低維和高維特徵融合;2)計算代價小;
論文中FPEM相同操作,操作了兩次;
代碼實現上,分爲兩部分:
第一部分(up-scale enchancemet):
第二部分(down-scale enchancement):
實現代碼:
fpem_repeat = 2
for i in range(fpem_repeat):
self.fpems.append(FPEM(conv_out))
# FPEM
for i, fpem in enumerate(self.fpems):
# print(fpem)
c2, c3, c4, c5 = fpem(c2, c3, c4, c5)
if i == 0:
c2_ffm = c2
c3_ffm = c3
c4_ffm = c4
c5_ffm = c5
else:
c2_ffm += c2
c3_ffm += c3
c4_ffm += c4
c5_ffm += c5
class FPEM(nn.Module):
def __init__(self, in_channels=128):
super().__init__()
self.up_add1 = SeparableConv2d(in_channels, in_channels, 1)
self.up_add2 = SeparableConv2d(in_channels, in_channels, 1)
self.up_add3 = SeparableConv2d(in_channels, in_channels, 1)
self.down_add1 = SeparableConv2d(in_channels, in_channels, 2)
self.down_add2 = SeparableConv2d(in_channels, in_channels, 2)
self.down_add3 = SeparableConv2d(in_channels, in_channels, 2)
def forward(self, c2, c3, c4, c5):
# up階段
c4 = self.up_add1(self._upsample_add(c5, c4))
c3 = self.up_add2(self._upsample_add(c4, c3))
c2 = self.up_add3(self._upsample_add(c3, c2))
# down 階段
c3 = self.down_add1(self._upsample_add(c3, c2))
c4 = self.down_add2(self._upsample_add(c4, c3))
c5 = self.down_add3(self._upsample_add(c5, c4))
return c2, c3, c4, c5
def _upsample_add(self, x, y):
return F.interpolate(x, size=y.size()[2:], mode='bilinear') + y
1.2.2 FFM模塊(Feature Fusion Module)
FFM的作用主要是進行了upsample+concat,實現代碼:
# FFM
c5 = F.interpolate(c5_ffm, c2_ffm.size()[-2:], mode='bilinear')
c4 = F.interpolate(c4_ffm, c2_ffm.size()[-2:], mode='bilinear')
c3 = F.interpolate(c3_ffm, c2_ffm.size()[-2:], mode='bilinear')
Fy = torch.cat([c2_ffm, c3, c4, c5], dim=1)
1.3 loss計算部分
1.3.1 Pixel Aggregation(PA)
解決問題1:同一個文本實例的像素和kernel之間的距離越小越好;
(1)式中,N:文本實例個數,Ti:第i個文本實例;p:文本像素;Ki:kernel
(2)式中,F(p):pixel similarity vector;g(Ki):kernel similarity vector,agg是個常量,值爲0.5,用於過濾容易樣本;
解決問題2:不同文本實例的kernel之間保持一定的距離;
Ldis保證kernels之間的距離不要小於dis,其值文中爲3;
1.3.2 LossFunction
文中的目標函數:
Ltex是文本區域loss;Lker是kernels的loss;loss之間使用了參數=0.5和=0.25;
Ltex和Lker使用了dice loss,爲了有效平衡文本區域和非文本區域 之間的大小;計算公式:
Ptex(i)和Gtex(i)分別代表了第i個像素的分割結果和真實標籤;真實標籤使用的是0,1的二值mask;0:非文本,1:文本;Ltex使用了難例挖掘(OHEM);
2.PAN與PSE的異同
(後續補充)
3.PAN方法代碼實現細讀
(後續補充)
4.訓練PAN的實戰經驗
(後續補充)