MTCNN中P網絡的輸出格式,根據輸出篩選置信度C比較大的,並找到與C對應的偏移量(使用的時候,不是訓練)

MTCNN中P網絡的輸出格式,根據輸出篩選置信度C比較大的,並找到與C對應的偏移量(使用的時候,不是訓練)

1.首先來看P網絡

class PNet(nn.Module):

    def __init__(self):
        super(PNet, self).__init__()

        self.pre_layer = nn.Sequential(
            nn.Conv2d(3, 10, kernel_size=3, stride=1),  # conv1
            nn.PReLU(),  # PReLU1
            nn.MaxPool2d(kernel_size=3, stride=2),  # pool1
            nn.Conv2d(10, 16, kernel_size=3, stride=1),  # conv2
            nn.PReLU(),  # PReLU2
            nn.Conv2d(16, 32, kernel_size=3, stride=1),  # conv3
            nn.PReLU()  # PReLU3
        )

        self.conv4_1 = nn.Conv2d(32, 1, kernel_size=1, stride=1)
        self.conv4_2 = nn.Conv2d(32, 4, kernel_size=1, stride=1)

    def forward(self, x):
        x = self.pre_layer(x)
        cond = F.sigmoid(self.conv4_1(x))
        offset = self.conv4_2(x)
        return cond, offset

p網絡的輸出有5個量,一個置信度,4個偏移量,又因爲傳入P網絡的圖片肯定要比12×12大,所以經卷積後輸出的特徵圖的尺寸一定大於1,應該是N×N×5
在這裏插入圖片描述
使用的時候是往P網絡中傳入一張圖片,所以批次N是1
P網絡最後的返回值是置信度cond和偏移量offset
cond的格式是[N,C,H,W]=[1,1,H,W]通道是1
offset的格式是[N,C,H,W]=[1,4,H,W]通道是4
2.反算,根據P網絡的輸出到原圖的映射,p網絡輸出了很多框組數據[[_X1,_Y1,_X2,_Y2,C1],[_X1,_Y1,_X2,_Y2,C2]…](偏移量和置信度)想要在原圖上畫框,先選擇C大的,說明有人臉的可能性大,再根據篩選出來的C的索引找到對應的偏移量offset,組成[_X1,_Y1,_X2,_Y2,C1],根據公式計算在原圖中的座標。

 _cls, _offest = self.pnet(img_data)

            cls, offest = _cls[0][0].cpu().data, _offest[0].cpu().data
            idxs = torch.nonzero(torch.gt(cls, 0.6))

            for idx in idxs:
                boxes.append(self.__box(idx, offest, cls[idx[0], idx[1]], scale))

            scale *= 0.7
            _w = int(w * scale)
            _h = int(h * scale)

            img = img.resize((_w, _h))
            min_side_len = min(_w, _h)

        return utils.nms(np.array(boxes), 0.5)

    # 將回歸量還原到原圖上去
    def __box(self, start_index, offset, cls, scale, stride=2, side_len=12):

        _x1 = (start_index[1] * stride) / scale
        _y1 = (start_index[0] * stride) / scale
        _x2 = (start_index[1] * stride + side_len) / scale
        _y2 = (start_index[0] * stride + side_len) / scale

        ow = _x2 - _x1
        oh = _y2 - _y1

        _offset = offset[:, start_index[0], start_index[1]]
        x1 = _x1 + ow * _offset[0]
        y1 = _y1 + oh * _offset[1]
        x2 = _x2 + ow * _offset[2]
        y2 = _y2 + oh * _offset[3]

        return [x1, y1, x2, y2, cls]

_cls的格式是[N,C,H,W]=[1,1,H,W]通道是1
_offset的格式是[N,C,H,W]=[1,4,H,W]通道是4
先看_cls
因爲傳入P網絡的圖片肯定要比12*12大,所以經卷積後輸出的特徵圖的尺寸一定大於1,假設輸出的尺寸是[1,1,2,2]
_offset和_cls一樣的道理

 cls, offest = _cls[0][0].cpu().data, _offest[0].cpu().data

第一步:篩選出來C大的
先看cls。p網絡輸出的_cls如下圖,格式是[1,1,2,2],_cls[0][0],第一個0是批次,全取,第二個0是通道,取第一個通道,實際只有一個通道,也就是批次後面的全取,也就是把這張特徵圖上面的所有置信度c都取出來,所以cls代表所有的置信度。
在這裏插入圖片描述
再看offset,p網絡輸出的_offset[0]格式是[1,4,2,2],_offset[0],第一個0是批次,全取,也就是批次後面的全取,也就是把4個通道的特徵圖都取
在這裏插入圖片描述
好,記住, cls是(二維h,w)
在這裏插入圖片描述
offest是(三維c h w)
在這裏插入圖片描述

idxs = torch.nonzero(torch.gt(cls, 0.6))

從所有的c中篩選出c大於0.6的,並記下索引爲idxs是一個二維數組,爲什麼呢?假如所有c如下
在這裏插入圖片描述
其實索引是

c1[[0,0],
c2[1,0],
c3[2,0],
c4[3,0]]

可以看出c3=0.8,c4=0.7大於0.6,那麼就輸出c3,c4的索引 [[2,0],[3,0]]
在這裏插入圖片描述
好,通過以上工作,已經拿到了想要的置信度的索引(置信度是多少還不知道)
第二步:根據篩選出來的C的索引,拿到與之對應的偏移量offset,start_index是C的索引

_offset = offset[:, start_index[0], start_index[1]]

前面說過,offset是三維的,形狀(c,h,w)=(4,2,2)
舉個例子:offset是一個(c,h,w)=(4,2,2)的數組(Tensor),cls是置信度,cls=0.8,0.7滿足要求,下面我們取cls=0.8,0.7對應的offset

import torch
cls=torch.Tensor([[0.6],
           [0.4],
           [0.8],
           [0.7]])
offset=torch.Tensor([[[0.6],[0.4],
                      [0.3],[0.8]],

                     [[0.5],[0.7],
                      [0.6],[0.4]],

                     [[0.3],[0.8],
                      [0.5],[0.7]],

                     [[0.4],[0.9],
                      [0.5],[0.7]]])
idxs=torch.nonzero(torch.gt(cls,0.6))
print(idxs)#idxs=[[2, 0],[3, 0]]
for idx in idxs:#idx=[2,0],[3,0]
    _offset=offset[:,idx[0],idx[1]]#offset[:,2,0]   offset[:,3,0]   
    print(_offset)

在這裏插入圖片描述
偏移量:
_x1=_offset[0]
_y1=_offset[1]
_x2=_offset[2]
_y2=_offset[3]
這樣就取出來了
在這裏插入圖片描述
到現在爲止,取出了置信度比較大的C的索引 idx,(C具體是多少還不知道)和與C對應的offset。
但是想要反算,去原圖中畫框,必須知道[_X1,_Y1,_X2,_Y2,C](偏移量和置信度),我們現在知道了四個偏移量_X1,_Y1,_X2,_Y2,較大的C的索引,還差C的具體數值,下面介紹方法。
前面的例子

cls=torch.Tensor([[0.6],
           [0.4],
           [0.8],
           [0.7]])

較大的C的索引idxs= [[2,0],[3,0]],用一個for循環一個一個取,先取第一個C,idx=[2,0], C=cls[idx[0],idx[1]] = cls[2,0] = 0.8,再取第二個
idx=[3,0], C=cls[idx[0],idx[1]] = cls[3,0] = 0.7
這樣就得到了兩組數[0.3,0.6,0.5,0.5, 0.8], [0.8,0.4,0.7,0.7, 0.7]
再回到原圖畫兩個框,具體怎麼畫,公式是什麼,看下一篇博文。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章