WFLW数据集说明

WFLW数据集说明

数据集介绍

数据集由商汤提供, 有98个关键点。里面除了关键点外,还对姿态、表情、照度、化妆、遮挡、模糊等信息进行标注。标签格式如下

  coordinates of 98 landmarks (196) + coordinates of upper left corner and lower right corner of detection rectangle (4) + attributes annotations (6) + image name (1)
  x0 y0 ... x97 y97 x_min_rect y_min_rect x_max_rect y_max_rect pose expression illumination make-up occlusion blur image_name

pose expression illumination make-up occlusion blur这六种信息在标注文件由0,1表示。

小图切分

PFLD为例。原本以为之所以标注x_min_rect, y_min_rect等是为了方便从62种场景中,将图中的人脸切割出来(112x112 送入人脸关键点模型)。但是这个repo里面并没有这么做, 而是选取关键点中最小的x和y,组成左上角坐标, 最大的x和y组成右上角坐标,求得中心点坐标。再以长边为边长, 乘以1.2, resize到112, 最后得到切分的人脸图。保存的关键点坐标信息则更新为, 相对于切分小图左上角的坐标, 再除以切分小图的边长。

def load_data(self, is_train, repeat, mirror=None):
    if (mirror is not None):
        with open(mirror, 'r') as f:
            lines = f.readlines()
            assert len(lines) == 1
            mirror_idx = lines[0].strip().split(',')
            mirror_idx = list(map(int, mirror_idx))
    xy = np.min(self.landmark, axis=0).astype(np.int32) 
    zz = np.max(self.landmark, axis=0).astype(np.int32)
    wh = zz - xy + 1

    center = (xy + wh/2).astype(np.int32)
    img = cv2.imread(self.path)
    boxsize = int(np.max(wh)*1.2)
    xy = center - boxsize//2
    x1, y1 = xy
    x2, y2 = xy + boxsize
    height, width, _ = img.shape
    dx = max(0, -x1)
    dy = max(0, -y1)
    x1 = max(0, x1)
    y1 = max(0, y1)

    edx = max(0, x2 - width)
    edy = max(0, y2 - height)
    x2 = min(width, x2)
    y2 = min(height, y2)

    imgT = img[y1:y2, x1:x2]
    if (dx > 0 or dy > 0 or edx > 0 or edy > 0): ##超出边界
        imgT = cv2.copyMakeBorder(imgT, dy, edy, dx, edx, cv2.BORDER_CONSTANT, 0)
    if imgT.shape[0] == 0 or imgT.shape[1] == 0:
        imgTT = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
        for x, y in (self.landmark+0.5).astype(np.int32):
            cv2.circle(imgTT, (x, y), 1, (0, 0, 255))
        cv2.imshow('0', imgTT)
        if cv2.waitKey(0) == 27:
            exit()
    imgT = cv2.resize(imgT, (self.image_size, self.image_size))
    landmark = (self.landmark - xy)/boxsize
    assert (landmark >= 0).all(), str(landmark) + str([dx, dy])
    assert (landmark <= 1).all(), str(landmark) + str([dx, dy])
    self.imgs.append(imgT)
    self.landmarks.append(landmark)

    if is_train:
        while len(self.imgs) < repeat:
            angle = np.random.randint(-30, 30)
            cx, cy = center
            cx = cx + int(np.random.randint(-boxsize*0.1, boxsize*0.1))
            cy = cy + int(np.random.randint(-boxsize * 0.1, boxsize * 0.1))
            M, landmark = rotate(angle, (cx,cy), self.landmark)

            imgT = cv2.warpAffine(img, M, (int(img.shape[1]*1.1), int(img.shape[0]*1.1)))

            
            wh = np.ptp(landmark, axis=0).astype(np.int32) + 1
            size = np.random.randint(int(np.min(wh)), np.ceil(np.max(wh) * 1.25))
            xy = np.asarray((cx - size // 2, cy - size//2), dtype=np.int32)
            landmark = (landmark - xy) / size
            if (landmark < 0).any() or (landmark > 1).any():
                continue

            x1, y1 = xy
            x2, y2 = xy + size
            height, width, _ = imgT.shape
            dx = max(0, -x1)
            dy = max(0, -y1)
            x1 = max(0, x1)
            y1 = max(0, y1)

            edx = max(0, x2 - width)
            edy = max(0, y2 - height)
            x2 = min(width, x2)
            y2 = min(height, y2)

            imgT = imgT[y1:y2, x1:x2]
            if (dx > 0 or dy > 0 or edx >0 or edy > 0):
                imgT = cv2.copyMakeBorder(imgT, dy, edy, dx, edx, cv2.BORDER_CONSTANT, 0)

            imgT = cv2.resize(imgT, (self.image_size, self.image_size))

            if mirror is not None and np.random.choice((True, False)):
                landmark[:,0] = 1 - landmark[:,0]
                landmark = landmark[mirror_idx]
                imgT = cv2.flip(imgT, 1)
            self.imgs.append(imgT)
            self.landmarks.append(landmark)
posted @ 2023-06-14 16:40  xle97  阅读(560)  评论(0)    收藏  举报