? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?姓名:韓宜真
學(xué)號(hào):17020120095
轉(zhuǎn)載自:https://mp.weixin.qq.com/s?__biz=MzA4MDExMDEyMw==&mid=2247489274&idx=2&sn=d0e1f4eb6ff54aaf74dcbd52bc9abcd3&chksm=9fa861bea8dfe8a80541e3b30ab3444afacf6bdb0928a1410f5e2c3ee7b4e9c495166c14e812&mpshare=1&scene=23&srcid=1216YrgSeUUDBX5vVHXEoC3k&sharer_sharetime=1608098185034&sharer_shareid=3f1a3081900d54d7638a82ca5b9e8a0d#rd
【嵌牛導(dǎo)讀】本文介紹了使用mask-rcnn網(wǎng)絡(luò)實(shí)現(xiàn)對(duì)象檢測(cè)與實(shí)例分割的方法。
【嵌牛鼻子】Mask-RCNN
【嵌牛提問(wèn)】 mask-rcnn網(wǎng)絡(luò)是如何實(shí)現(xiàn)對(duì)象檢測(cè)與實(shí)例分割的?
【嵌牛正文】
Mask-RCNN網(wǎng)絡(luò)模型
Faster-RCNN網(wǎng)絡(luò)主要由三個(gè)部分組成分別是backbone的卷積網(wǎng)絡(luò)、實(shí)現(xiàn)Boxes選擇的區(qū)域推薦網(wǎng)絡(luò)RPN、最終的分類回歸。Mask-RCNN簡(jiǎn)單說(shuō)就是在RPN之后得到對(duì)齊ROI對(duì)齊區(qū)域,完成了一個(gè)全卷積的像素分割分支,Mask-RCNN的網(wǎng)絡(luò)結(jié)構(gòu)如下:
在推理階段,模型輸出下列字典選項(xiàng):
boxes:預(yù)測(cè)矩形的左上角與右下角坐標(biāo)(x1,y1,x2,y2) [Nx4]
labels: 預(yù)測(cè)每個(gè)對(duì)象標(biāo)簽
scores:預(yù)測(cè)每個(gè)對(duì)象的得分,在0~1之間,大于閾值T的即為預(yù)測(cè)輸出
masks:預(yù)測(cè)每個(gè)實(shí)例對(duì)象的mask,mask>0.5作為最終分類mask。[Nx1xHxW]
使用Mask-RCNN實(shí)現(xiàn)實(shí)例分割
Pytorch中使用Mask-RCNN實(shí)現(xiàn)實(shí)例分割,是基于torchvision的預(yù)訓(xùn)練模型庫(kù),首先需要下載預(yù)訓(xùn)練模型,并檢查是否可以支持GPU推理,相關(guān)的代碼如下:
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)model.eval()transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])# 使用GPUtrain_on_gpu = torch.cuda.is_available()if train_on_gpu:model.cuda()
基于輸入圖像,實(shí)現(xiàn)Mask-RCNN模型推理預(yù)測(cè),得到對(duì)象與實(shí)例分割mask的代碼如下:
1frame?=?cv.imread("D:/images/master.jpg")
2blob?=?transform(frame)
3c,?h,?w?=?blob.shape
4input_x?=?blob.view(1,?c,?h,?w)
5output?=?model(input_x.cuda())[0]
6boxes?=?output['boxes'].cpu().detach().numpy()
7scores?=?output['scores'].cpu().detach().numpy()
8labels?=?output['labels'].cpu().detach().numpy()
9masks?=?output['masks'].cpu().detach().numpy()
對(duì)推理預(yù)測(cè)得到四個(gè)輸出結(jié)果,分別進(jìn)行解析,其中score閾值為0.5,mask采用soft版本,對(duì)大于0.5分割為當(dāng)前對(duì)象像素,這部分的代碼實(shí)現(xiàn)如下:
1index?=0
2color_mask?=?np.zeros((h,?w,?c),?dtype=np.uint8)
3mv?=?cv.split(color_mask)
4forx1,?y1,?x2,?y2inboxes:
5ifscores[index]?>0.5:
6cv.rectangle(frame,?(np.int32(x1),?np.int32(y1)),
7(np.int32(x2),?np.int32(y2)),?(0,255,255),1,8,0)
8mask?=?np.squeeze(masks[index]?>0.5)
9np.random.randint(0,256)
10mv[2][mask?==1],?mv[1][mask?==1],?mv[0][mask?==1]?=?\
11[np.random.randint(0,256),?np.random.randint(0,256),?np.random.randint(0,256)]
12
13label_id?=?labels[index]
14label_txt?=?coco_names[str(label_id)]
15cv.putText(frame,?label_txt,?(np.int32(x1),?np.int32(y1)),?cv.FONT_HERSHEY_PLAIN,1.0,?(0,0,255),1)
16index?+=1
其中對(duì)實(shí)例分割的對(duì)象像素進(jìn)行隨機(jī)顏色填充,完成彩色mask圖像生成。最終把彩色mask圖像與輸入圖像進(jìn)行疊加,得到實(shí)例分割輸出結(jié)果如下:
1color_mask?=?cv.merge(mv)
2result?=?cv.addWeighted(frame,0.5,?color_mask,0.5,0)
3cv.imshow("intances?segmentation?demo",?result)
4cv.imwrite("D:/master_test.png",?result)
這里,我測(cè)試了三張圖像,結(jié)果分別如下:
Mask-RCNN實(shí)例分割對(duì)象提取與背景替換
這個(gè)是很久以前我寫過(guò)一個(gè)無(wú)人機(jī)的Mask-RCNN檢測(cè)時(shí)候,別人問(wèn)我的問(wèn)題,其實(shí)這個(gè)就是很簡(jiǎn)單的OpenCV操作就可以很好的提取出來(lái)這些ROI圖像,代碼實(shí)現(xiàn)如下:
1#?簡(jiǎn)單背景替換
2back_ground?=?np.zeros_like(frame)
3back_ground[:,:,:]?=?(255,0,255)
4forrowinrange(h):
5forcolinrange(w):
6b,?g,?r?=?color_mask[row,?col]
7ifb?>0org?>0orr?>0:
8back_ground[row,?col]?=?(0,0,0)
9temp?=?cv.add(back_ground,?frame,?mask=mv[0])
10dst?=?cv.add(back_ground,?temp)
11cv.imshow("background?replacement",?dst)
12cv.waitKey(0)
13cv.destroyAllWindows()
運(yùn)行結(jié)果如下: