two-stage-anchor-based-faster-rcnn进阶-mask rcnn:Mask R-CNN
paper:https://arxiv.org/abs/1703.06870
code:https://github.com/matterport/Mask_RCNN
? ? mask rcnn是基于faster rcnn的改進(jìn)的一種實(shí)例分割算法(得到目標(biāo)實(shí)例同時(shí)也生成bbox,檢測(cè)結(jié)果也刷出新高),由目標(biāo)檢測(cè)算法直接引申到實(shí)例分割領(lǐng)域,典型的top-down,也叫做 detect-then-segment,顧名思義,先檢測(cè)后分割。在實(shí)例分割上一度領(lǐng)先獨(dú)領(lǐng)風(fēng)騷,即便是放在現(xiàn)在,mask rcnn的效果也是各個(gè)SOTA算法發(fā)表的必備比對(duì)數(shù)據(jù),本文主要描述我對(duì)mask rcnn的理解。
? ? mask-rcnn是基于faster-rcnn的改進(jìn),faster-rcnn此篇文章就不回顧了,需要了解的話去看我前2篇文章。
模型總體結(jié)構(gòu):
? ? 先上結(jié)構(gòu)圖(來(lái)源:https://www.cnblogs.com/haimingv/p/12490957.html)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? 結(jié)構(gòu)與faster rcnn一脈相承,利用backbone獲取feature_map后,第一階段利用RPN獲取propossals,第二階段基于proposals利用mask rcnn獨(dú)有的Roi Align將proposals映射回原圖,再對(duì)這些proposals進(jìn)行bobx regression、classcification、instance segmentation。
? ? 與faster rcnn的區(qū)別:
? ? 1、將faster rcnn的Roi Pooling模塊修改為Roi Align模塊,修復(fù)了像素級(jí)的映射損失
? ? 2、將faster rcnn的cls+reg任務(wù)增加為cls+reg+instance_seg的3個(gè)任務(wù)
? ? 3、backbone:增加了fpn結(jié)構(gòu)(當(dāng)年的sota結(jié)構(gòu))
? ? 4、引入mask loss:稍后細(xì)節(jié)一下討論
整體模型架構(gòu)圖(相當(dāng)詳細(xì),圖片來(lái)源:https://www.cnblogs.com/haimingv/p/12490957.html-后續(xù)的模塊分析基于本張圖進(jìn)行):
詳細(xì)模塊解讀:
? ? 1、backbone+fpn:
? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? 上圖為基于resnet101的fpn的結(jié)構(gòu),renet中的基礎(chǔ)shortcut?block應(yīng)該是bottleneck,由backbone得到c1-c5后:
? ? ? ? ?將c5進(jìn)行1*1的卷積減少通道數(shù)至256生成p5,p5進(jìn)行3*3的卷積生成256通道數(shù)p5;
? ? ? ? ?p5上采樣*2 + c4進(jìn)行1*1卷積減少通道數(shù)至256生成p4,p4進(jìn)行3*3卷積生成256通道數(shù)p4,
? ? ? ? ?p4上采樣*2 + c3進(jìn)行1*1卷積減少通道數(shù)至256生成p3,p3進(jìn)行3*3卷積生成256通道數(shù)p3,
? ? ? ? ?p3上采樣*2 + c2進(jìn)行1*1卷積減少通道數(shù)至256生成p2,p2進(jìn)行3*3卷積生成256通道數(shù)p2,
? ? ? ? ?p5還要進(jìn)行一次最大池化尺寸/2生成p6(僅rpn使用);
? ? ? ? 即[p2,p3,p4,p5,p6] -> RPN, [p2,p3,p4,p5] -> mask rcnn
? ? 2、anchors機(jī)制和proposals機(jī)制
? ? ? ? RPN利用[p2,p3,p4,p5,p6]這5個(gè)尺度,每個(gè)尺度上的特征圖生成3個(gè)anchors,比例是[0.5, 1, 2],然后將5個(gè)尺度上的anchors疊加成為RPN所使用的anchors;
? ? ? ? RPN在5個(gè)尺度上的每個(gè)特征圖經(jīng)過(guò)RPN網(wǎng)絡(luò)生成兩部分結(jié)果,第一部分是rpn_class_logits(每個(gè)anchors對(duì)應(yīng)的BG/FG類別logits)和rpn_class_prob(每個(gè)anchors的類別置信度),第二部分是rpn_box(每個(gè)anchors的偏移量[dy, dx, log(dh), log(dw)]),得到每個(gè)尺度的類別和偏移,然后將五個(gè)尺度疊加合成RPN網(wǎng)絡(luò)輸出的類別和偏移;
? ? ? ? 接下來(lái)判定需要生成的預(yù)選框(proposals),將RPN網(wǎng)絡(luò)生成的偏移量更新給anchors,并生成經(jīng)過(guò)細(xì)化/nms(非極大抑制)后的歸一化預(yù)選框,為之后的訓(xùn)練(2000個(gè))/預(yù)測(cè)(1000個(gè))使用;
? ? ? ??
? ? 3、RoiAlign模塊
? ? ? ? Rol Align很好的解決了 RoI Pooling操作中兩次量化造成的像素級(jí)的誤差問(wèn)題(mis-alignment),此處先簡(jiǎn)單分析一下RoI Pooling的原理:
? ? ? ? 3.1、RoI Pooling
? ? ? ? ? ? 在faster rcnn中,anchors經(jīng)過(guò)proposals layer成為proposal,經(jīng)過(guò)RoI Pooling進(jìn)行size的歸一化然后進(jìn)入固定input-size的全連接網(wǎng)絡(luò),步驟如下:
? ? ? ? ? ? 1、將proposal映射到feature map對(duì)應(yīng)位置
? ? ? ? ? ? 2、將映射后的區(qū)域劃分為相同到校的sections
? ? ? ? ? ? 3、對(duì)每個(gè)sections進(jìn)行max pooling操作??
? ? ? ? 3.2、RoI Pooling的問(wèn)題所在
? ? ? ? ? ? RoI pooling的作用時(shí)根據(jù)proposal(初步bbox)的位置坐標(biāo)在特征圖中將相應(yīng)區(qū)域池化為固定size(7*7)的feature-map,然后進(jìn)行后續(xù)的分類和bbox回歸工作。? ? ?
? ? ? ? ? ? 從上文的顏色對(duì)誤差來(lái)源進(jìn)行分析:
? ?? ? ? ? ?1、將候選邊界框邊界量化為整數(shù)點(diǎn)的feature-map坐標(biāo)值。假定gt為[665*665],下采樣32倍,則RoI Pooling將其變?yōu)?65/32=20.78后-四舍五入等于20,則gt在32倍feature-map上的值為[20,20](此例見(jiàn)下圖的第一部分)。
? ? ? ? ? ? 2、將量化后的邊界區(qū)域(feature-map坐標(biāo)值-proposal)平均分成k*k(固定size)個(gè)單元(固定feature-map)。假定gt在32被feature-map上的坐標(biāo)為[20,20],池化為7*7時(shí),則量化后的邊界區(qū)域平均分割為7*7個(gè)矩形區(qū)域,每個(gè)矩形區(qū)域邊緣為2.86,但是池化時(shí)只能將其量化為2,2*7=14,還有6個(gè)單位的feature被直接忽略掉了,則候選區(qū)域在最終做分類和回歸任務(wù)時(shí)明顯出現(xiàn)了極大的偏差,如下圖的綠色feature為真正使用到的,綠色框之外的全部被忽視掉了。
? ? ? ? ? ? 簡(jiǎn)單來(lái)說(shuō),整形坐標(biāo)在映射到整形feature-map,會(huì)出現(xiàn)第一次誤差,在做固定尺寸的max-pool時(shí),會(huì)出現(xiàn)第二次誤差。
? ? ? ? ? ? 圖片來(lái)源:https://blog.csdn.net/wangdongwei0/article/details/85268965
? ? ? ? ? ? ? ? ??
? ? ? ? 3.3、Roi Align的主要思想和方法
? ? ? ? 取消量化操作。
? ? ? ? 1、遍歷每一個(gè)候選區(qū)域,保持浮點(diǎn)邊界,不做量化
? ? ? ? 2、將候選區(qū)域分割為k*k個(gè)單元,每個(gè)單元的邊界也不做量化
? ? ? ? 3、將每個(gè)單元中固定規(guī)則固定四個(gè)坐標(biāo)位置,用雙線性插值的方法計(jì)算出這4個(gè)位置的值,然后進(jìn)行最大池化操作(詳細(xì)理解見(jiàn)下文)。
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ?如上圖所示,固定的4個(gè)坐標(biāo)位置指的是每一個(gè)矩形單元(bin)中按照固定規(guī)則確定的位置,比如采樣點(diǎn)是1,則就是單元的中心點(diǎn),如果采樣點(diǎn)是4,就是把這個(gè)單元平均分割成4個(gè)小方塊以后它們分別的中心點(diǎn),如上圖所示,顯然這些采樣點(diǎn)通常為浮點(diǎn)型數(shù),因此利用插值的方法得到他們的像素而不是之前的直接量化后讀取,在相關(guān)實(shí)驗(yàn)中,作者發(fā)現(xiàn)將采樣點(diǎn)設(shè)為4會(huì)獲得最佳性能,甚至直接設(shè)為1在性能上也相差無(wú)幾。
? ? ? ?Roi Pooling是直接全部取整,則第一步獲得到的proposal自然就是整形坐標(biāo),也可以直接讀取到對(duì)應(yīng)位置的特征,劃分成bins以后,然后roi pooling直接利用這些劃分bins的特征進(jìn)行最大池化得到固定尺寸的feature。
? ? ? ?RoI Align是全部使用浮點(diǎn),然后使用浮點(diǎn)劃分位置,得到位置后,劃分好bins,對(duì)每個(gè)bins進(jìn)行4個(gè)點(diǎn)的采樣,每個(gè)點(diǎn)都使用距離最近的四個(gè)像素點(diǎn)(feature點(diǎn))進(jìn)行雙線性插值得到,依次對(duì)4個(gè)點(diǎn)完成操作后,在對(duì)這4個(gè)值進(jìn)行max-pool得到固定尺寸的feature。
? ? ? ?具體形象化流程如下:https://blog.csdn.net/qinghuaci666/article/details/80900882(以下的Roi Align為摘自該鏈接的理解,侵刪,該鏈接進(jìn)一步的給出了曠視針對(duì)只采樣4個(gè)點(diǎn)進(jìn)行插值的精度進(jìn)一步改進(jìn)方法)
? ? ? ?從左至右依次順序執(zhí)行:
? ? 更進(jìn)一步的,給出一個(gè)7*7的執(zhí)行實(shí)例:
? ? 輸出7*7的fix featrue:
? ? 1、劃分7*7的bin(我們可以直接精確的映射到feature map來(lái)劃分bin,不用第一次量化)? ? ? ? ??
? ? 2、每個(gè)bin中采樣4個(gè)點(diǎn),雙線性插值?
? ? 3、對(duì)每個(gè)bin4個(gè)點(diǎn)做max或average pooling
# pytorch
# 這是pytorch做法先采樣到14*14,然后max pooling到7*7
pre_pool_size = cfg.POOLING_SIZE * 2
grid = F.affine_grid(theta, torch.Size((rois.size(0), 1, pre_pool_size, pre_pool_size)))
crops = F.grid_sample(bottom.expand(rois.size(0), bottom.size(1), bottom.size(2), bottom.size(3)), grid, mode=mode)
crops = F.max_pool2d(crops, 2, 2)
# tensorflow
pooled.append(tf.image.crop_and_resize(
? ? ? ? ? ? ? ? feature_maps[i], level_boxes, box_indices, self.pool_shape,
? ? ? ? ? ? ? ? method="bilinear"))
?4、head部分
總體框架圖如上,將生成的rois放入head網(wǎng)絡(luò),網(wǎng)絡(luò)分為兩部分,
? ? 第一部分是fc層的生成2個(gè)結(jié)果,一個(gè)是類別(class+bg)-class-prob,一個(gè)是坐標(biāo)回歸(每個(gè)rois的坐標(biāo)偏移量[dy, dx, log(dh), log(dw)]);
? ? 第二部分是全卷積分割網(wǎng)絡(luò)生成mask結(jié)果,大小為28*28*channels(class_num)的mask圖,通道數(shù)為分類數(shù)。
? ? 訓(xùn)練的時(shí)候然后開(kāi)始進(jìn)行l(wèi)oss函數(shù)的計(jì)算,而推理階段forward過(guò)程結(jié)束。
?
模型損失函數(shù):
mask分支對(duì)于每個(gè)RoI有K*m*m?維度的輸出。K個(gè)(類別數(shù))分辨率為m*m的二值mask。
因此作者利用了a per-pixel sigmoid,并且定義 Lmask 為平均二值交叉熵?fù)p失(the average binary cross-entropy loss).
對(duì)于一個(gè)屬于第k個(gè)類別的RoI, Lmask 僅僅考慮第k個(gè)mask(其他的掩模輸入不會(huì)貢獻(xiàn)到損失函數(shù)中)。這樣的定義會(huì)允許對(duì)每個(gè)類別都會(huì)生成掩模,并且不會(huì)存在類間競(jìng)爭(zhēng)
參考:
https://blog.csdn.net/qinghuaci666/article/details/80900882
總結(jié)
以上是生活随笔為你收集整理的two-stage-anchor-based-faster-rcnn进阶-mask rcnn:Mask R-CNN的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C# 使用SDL2实现Mp4文件播放音视
- 下一篇: 3D点云系列——pcl:点云平滑及法线估