File size: 4,881 Bytes
09462dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# https://github.com/IDEA-Research/DWPose
# Openpose
# Original from CMU https://github.com/CMU-Perceptual-Computing-Lab/openpose
# 2nd Edited by https://github.com/Hzzone/pytorch-openpose
# 3rd Edited by ControlNet
# 4th Edited by ControlNet (added face and correct hands)

import copy
import os

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
import cv2
import numpy as np
import torch
from controlnet_aux.util import HWC3, resize_image
from PIL import Image

from . import util
from .wholebody import Wholebody


class DWposeDetector:
    def __init__(self, use_batch=False):
        self.use_batch = use_batch
        pass

    def to(self, device):
        self.pose_estimation = Wholebody(device, self.use_batch)
        return self

    def _get_multi_result_from_est(self, candidate, score_result, det_result, H, W):
        nums, keys, locs = candidate.shape  # n 所有身体关键点数量,坐标
        candidate[..., 0] /= float(W)
        candidate[..., 1] /= float(H)
        subset_score = score_result[:, :24]              # 按照24个骨骼关键点来区分可见位置
        face_score = score_result[:, 24:92]
        hand_score = score_result[:, 92:113]
        hand_score = np.vstack([hand_score, score_result[:, 113:]])

        body_candidate = candidate[:, :24].copy()     # body(n, 24, 2)
        for i in range(len(subset_score)):  # n 个
            for j in range(len(subset_score[i])):
                if subset_score[i][j] > 0.3:
                    subset_score[i][j] = j      # 标注序号,这样后续用的时候可以快速查出可用点
                else:
                    subset_score[i][j] = -1    # 躯干中去除掉不可见的骨骼

        un_visible = score_result < 0.3       
        candidate[un_visible] = -1      # 全部关键点中去掉不可见骨骼

        faces = candidate[:, 24:92]
        hands = candidate[:, 92:113]    # hands(2*n, 21, 2)
        hands = np.vstack([hands, candidate[:, 113:]]) 

        bodies = dict(candidate=body_candidate, subset=subset_score)
        pose = dict(bodies=bodies, hands=hands, faces=faces)
        score = dict(body_score=subset_score, hand_score=hand_score, face_score=face_score)

        new_det_result = []
        for bbox in det_result:
            x1, y1, x2, y2 = bbox
            new_x1 = x1 / W
            new_y1 = y1 / H
            new_x2 = x2 / W
            new_y2 = y2 / H
            new_bbox = [new_x1, new_y1, new_x2, new_y2]
            new_det_result.append(new_bbox)

        return pose, score, new_det_result     # body_score是原始的躯干骨骼分数

    # def _get_result_from_est(self, input_image, candidate, subset, det_result, image_resolution, output_type, H, W):
    #     nums, keys, locs = candidate.shape
    #     candidate[..., 0] /= float(W)
    #     candidate[..., 1] /= float(H)
    #     score = subset[:, :18]              # 前18个是躯干骨骼  score(n, 18)
    #     max_ind = np.mean(score, axis=-1).argmax(axis=0)    # 返回分数最高的锚框对应的骨骼
    #     score = score[[max_ind]]
    #     body = candidate[:, :18].copy()
    #     body = body[[max_ind]]
    #     nums = 1
    #     body = body.reshape(nums * 18, locs)    # Moore-AA只有一个人体, 0-18表示body
    #     body_score = copy.deepcopy(score)       # 已经去过max_ind
    #     for i in range(len(score)):
    #         for j in range(len(score[i])):
    #             if score[i][j] > 0.3:
    #                 score[i][j] = int(18 * i + j)
    #             else:
    #                 score[i][j] = -1    # 躯干中去除掉不可见的骨骼

    #     un_visible = subset < 0.3       
    #     candidate[un_visible] = -1      # 全部关键点中去掉不可见骨骼

    #     foot = candidate[:, 18:24]

    #     faces = candidate[[max_ind], 24:92]

    #     hands = candidate[[max_ind], 92:113]
    #     hands = np.vstack([hands, candidate[[max_ind], 113:]])

    #     bodies = dict(candidate=body, subset=score)
    #     pose = dict(bodies=bodies, hands=hands, faces=faces)

    #     return pose, body_score, det_result     # body_score是原始的躯干骨骼分数

    def __call__(
        self,
        input,
        **kwargs,
    ):                          
        if not self.use_batch:
            # PIL要不要颜色反转?
            input = cv2.cvtColor(
                np.array(input, dtype=np.uint8), cv2.COLOR_RGB2BGR
            )
            input = HWC3(input)
            H, W, C = input.shape

            with torch.no_grad():
                candidate, subset, det_result = self.pose_estimation(input)   # candidate (n, 134, 2) 候选点 / subset (n, 134) 得分
                return self._get_multi_result_from_est(candidate, subset, det_result, H, W)
        else:
            raise NotImplementedError("DWposeDetector does not support batch mode")