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)

浙公网安备 33010602011771号