Browse Source

fix no face bug and adaptive for 360 degree of head

master
寿州 3 years ago
parent
commit
e870d55e28
1 changed files with 53 additions and 83 deletions
  1. +53
    -83
      modelscope/pipelines/cv/easycv_pipelines/face_2d_keypoints_pipeline.py

+ 53
- 83
modelscope/pipelines/cv/easycv_pipelines/face_2d_keypoints_pipeline.py View File

@@ -12,8 +12,11 @@ from modelscope.pipelines import pipeline
from modelscope.pipelines.builder import PIPELINES from modelscope.pipelines.builder import PIPELINES
from modelscope.preprocessors import LoadImage from modelscope.preprocessors import LoadImage
from modelscope.utils.constant import ModelFile, Tasks from modelscope.utils.constant import ModelFile, Tasks
from modelscope.utils.logger import get_logger
from .base import EasyCVPipeline from .base import EasyCVPipeline


logger = get_logger()



@PIPELINES.register_module( @PIPELINES.register_module(
Tasks.face_2d_keypoints, module_name=Pipelines.face_2d_keypoints) Tasks.face_2d_keypoints, module_name=Pipelines.face_2d_keypoints)
@@ -123,54 +126,28 @@ class Face2DKeypointsPipeline(EasyCVPipeline):
return s / 3 * sigma return s / 3 * sigma


def rotate_crop_img(self, img, pts, M): def rotate_crop_img(self, img, pts, M):
image_size = 256
enlarge_ratio = 1.1

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


x1 = pts[5][0] x1 = pts[5][0]
x2 = pts[5][0]
y1 = pts[5][1] y1 = pts[5][1]
x2 = pts[6][0]
y2 = pts[6][1]
w = x2 - x1 + 1
h = y2 - y1 + 1
x1 = int(x1 - (enlarge_ratio - 1.0) / 2.0 * w)
y1 = int(y1 - (enlarge_ratio - 1.0) / 2.0 * h)

new_w = int(enlarge_ratio * (1 + self.random_normal() * 0.1) * w)
new_h = int(enlarge_ratio * (1 + self.random_normal() * 0.1) * h)
new_x1 = x1 + int(self.random_normal() * image_size * 0.05)
new_y1 = y1 + int(self.random_normal() * image_size * 0.05)
new_x2 = new_x1 + new_w
new_y2 = new_y1 + new_h
y2 = pts[5][1]
for i in range(0, 9):
x1 = min(x1, pts[i][0])
x2 = max(x2, pts[i][0])
y1 = min(y1, pts[i][1])
y2 = max(y2, pts[i][1])


height, width, _ = imgT.shape height, width, _ = imgT.shape
dx = max(0, -new_x1)
dy = max(0, -new_y1)
new_x1 = max(0, new_x1)
new_y1 = max(0, new_y1)
x1 = min(max(0, int(x1)), width)
y1 = min(max(0, int(y1)), height)
x2 = min(max(0, int(x2)), width)
y2 = min(max(0, int(y2)), height)
sub_imgT = imgT[y1:y2, x1:x2]


edx = max(0, new_x2 - width)
edy = max(0, new_y2 - height)
new_x2 = min(width, new_x2)
new_y2 = min(height, new_y2)
return sub_imgT, imgT, [x1, y1, x2, y2]


sub_imgT = imgT[new_y1:new_y2, new_x1:new_x2]
if dx > 0 or dy > 0 or edx > 0 or edy > 0:
sub_imgT = cv2.copyMakeBorder(
sub_imgT,
dy,
edy,
dx,
edx,
cv2.BORDER_CONSTANT,
value=(103.94, 116.78, 123.68))

return sub_imgT, imgT, [new_x1, new_y1, new_x2,
new_y2], [dx, dy, edx, edy]

def crop_img(self, imgT, pts, angle):
image_size = 256
def crop_img(self, imgT, pts):
enlarge_ratio = 1.1 enlarge_ratio = 1.1


x1 = np.min(pts[:, 0]) x1 = np.min(pts[:, 0])
@@ -181,94 +158,87 @@ class Face2DKeypointsPipeline(EasyCVPipeline):
h = y2 - y1 + 1 h = y2 - y1 + 1
x1 = int(x1 - (enlarge_ratio - 1.0) / 2.0 * w) x1 = int(x1 - (enlarge_ratio - 1.0) / 2.0 * w)
y1 = int(y1 - (enlarge_ratio - 1.0) / 2.0 * h) y1 = int(y1 - (enlarge_ratio - 1.0) / 2.0 * h)
x1 = max(0, x1)
y1 = max(0, y1)


new_w = int(enlarge_ratio * (1 + self.random_normal() * 0.1) * w)
new_h = int(enlarge_ratio * (1 + self.random_normal() * 0.1) * h)
new_x1 = x1 + int(self.random_normal() * image_size * 0.05)
new_y1 = y1 + int(self.random_normal() * image_size * 0.05)
new_w = int(enlarge_ratio * w)
new_h = int(enlarge_ratio * h)
new_x1 = x1
new_y1 = y1
new_x2 = new_x1 + new_w new_x2 = new_x1 + new_w
new_y2 = new_y1 + new_h new_y2 = new_y1 + new_h


new_xy = new_x1, new_y1
pts = pts - new_xy

height, width, _ = imgT.shape height, width, _ = imgT.shape
dx = max(0, -new_x1)
dy = max(0, -new_y1)
new_x1 = max(0, new_x1)
new_y1 = max(0, new_y1)


edx = max(0, new_x2 - width)
edy = max(0, new_y2 - height)
new_x2 = min(width, new_x2)
new_y2 = min(height, new_y2)
new_x1 = min(max(0, new_x1), width)
new_y1 = min(max(0, new_y1), height)
new_x2 = max(min(width, new_x2), 0)
new_y2 = max(min(height, new_y2), 0)


sub_imgT = imgT[new_y1:new_y2, new_x1:new_x2] sub_imgT = imgT[new_y1:new_y2, new_x1:new_x2]
if dx > 0 or dy > 0 or edx > 0 or edy > 0:
sub_imgT = cv2.copyMakeBorder(
sub_imgT,
dy,
edy,
dx,
edx,
cv2.BORDER_CONSTANT,
value=(103.94, 116.78, 123.68))

return sub_imgT, [new_x1, new_y1, new_x2, new_y2], [dx, dy, edx, edy]


def __call__(self, inputs) -> Any:
image_size = 256
return sub_imgT, [new_x1, new_y1, new_x2, new_y2]


def __call__(self, inputs) -> Any:
img = LoadImage.convert_to_ndarray(inputs) img = LoadImage.convert_to_ndarray(inputs)
h, w, c = img.shape h, w, c = img.shape
img_rgb = copy.deepcopy(img) img_rgb = copy.deepcopy(img)
img_rgb = img_rgb[:, :, ::-1] img_rgb = img_rgb[:, :, ::-1]
det_result = self.face_detection(img_rgb) det_result = self.face_detection(img_rgb)

bboxes = np.array(det_result[OutputKeys.BOXES])
if bboxes.shape[0] == 0:
logger.warn('No face detected!')
results = {
OutputKeys.KEYPOINTS: [],
OutputKeys.POSES: [],
OutputKeys.BOXES: []
}
return results

boxes, keypoints = self._choose_face(det_result) boxes, keypoints = self._choose_face(det_result)


output_boxes = [] output_boxes = []
output_keypoints = [] output_keypoints = []
output_poses = [] output_poses = []
for idx, box_ori in enumerate(boxes):
box = self.expend_box(box_ori, w, h, scalex=0.15, scaley=0.15)
for index, box_ori in enumerate(boxes):
box = self.expend_box(box_ori, w, h, scalex=0.1, scaley=0.1)
y0 = int(box[1]) y0 = int(box[1])
y1 = int(box[3]) y1 = int(box[3])
x0 = int(box[0]) x0 = int(box[0])
x1 = int(box[2]) x1 = int(box[2])
sub_img = img[y0:y1, x0:x1] sub_img = img[y0:y1, x0:x1]


keypoint = keypoints[idx]
keypoint = keypoints[index]
pts = [[keypoint[0], keypoint[1]], [keypoint[2], keypoint[3]], pts = [[keypoint[0], keypoint[1]], [keypoint[2], keypoint[3]],
[keypoint[4], keypoint[5]], [keypoint[6], keypoint[7]], [keypoint[4], keypoint[5]], [keypoint[6], keypoint[7]],
[keypoint[8], keypoint[9]], [box[0], box[1]], [keypoint[8], keypoint[9]], [box[0], box[1]],
[box[2], box[3]]]
[box[2], box[1]], [box[0], box[3]], [box[2], box[3]]]
# radian # radian
angle = math.atan2((pts[1][1] - pts[0][1]), angle = math.atan2((pts[1][1] - pts[0][1]),
(pts[1][0] - pts[0][0])) (pts[1][0] - pts[0][0]))
# angle # angle
theta = angle * (180 / np.pi) theta = angle * (180 / np.pi)


center = [image_size // 2, image_size // 2]
center = [w // 2, h // 2]
cx, cy = center cx, cy = center
M, landmark_ = self.rotate_point(theta, (cx, cy), pts) M, landmark_ = self.rotate_point(theta, (cx, cy), pts)
sub_img, imgT, bbox, delta_border = self.rotate_crop_img(
img, pts, M)
sub_imgT, imgT, bbox = self.rotate_crop_img(img, landmark_, M)


outputs = self.predict_op([sub_img])[0]
outputs = self.predict_op([sub_imgT])[0]
tmp_keypoints = outputs['point'] tmp_keypoints = outputs['point']


for idx in range(0, len(tmp_keypoints)): for idx in range(0, len(tmp_keypoints)):
tmp_keypoints[idx][0] += (delta_border[0] + bbox[0])
tmp_keypoints[idx][1] += (delta_border[1] + bbox[1])
tmp_keypoints[idx][0] += bbox[0]
tmp_keypoints[idx][1] += bbox[1]


for idx in range(0, 3):
sub_img, bbox, delta_border = self.crop_img(
imgT, tmp_keypoints, 0)
for idx in range(0, 6):
sub_img, bbox = self.crop_img(imgT, tmp_keypoints)
outputs = self.predict_op([sub_img])[0] outputs = self.predict_op([sub_img])[0]
tmp_keypoints = outputs['point'] tmp_keypoints = outputs['point']
for idx in range(0, len(tmp_keypoints)): for idx in range(0, len(tmp_keypoints)):
tmp_keypoints[idx][0] += (delta_border[0] + bbox[0])
tmp_keypoints[idx][1] += (delta_border[1] + bbox[1])
tmp_keypoints[idx][0] += bbox[0]
tmp_keypoints[idx][1] += bbox[1]


M2, tmp_keypoints = self.rotate_point(-theta, (cx, cy), M2, tmp_keypoints = self.rotate_point(-theta, (cx, cy),
tmp_keypoints) tmp_keypoints)


Loading…
Cancel
Save