openpose操作(四)-关键点检测

在这里插入图片描述

threshold = 0.1
part = 1
probMap = output[0, part, :,:]
mapSmooth = cv2.GaussianBlur(probMap, (3, 3), 0, 0)
mapMask = np.uint8(mapSmooth > threshold)

plt.subplot(1, 3, 1)
plt.imshow(probMap)
plt.title("probMap")
plt.axis("off")
plt.subplot(1, 3, 2)
plt.imshow(mapSmooth)
plt.title("mapSmooth")
plt.axis("off")
plt.subplot(1, 3, 3)
plt.imshow(mapMask)
plt.title("mapMask")
plt.axis("off")
plt.show()

一,关键点检测
流程如下:probmap->高斯滤波->得到mapMask
1.cv2.GaussianBlur:高斯滤波,是一种线性平滑滤波,对于除去高斯噪声有很好的效果。
2.mapMask为prob二值图,>threshold为1,其他为0
在这里插入图片描述
二,关键点坐标值
为了找到关键点的确切位置,我们需要找到每个blob的极大值。通过以下步骤实现:
1.首先找出每个关键点区域的全部轮廓
2.生成这个区域的遮盖(blob mask)
3.通过用probMap乘以这个遮盖,提取该区域的probMap
4.找到这个区域的本地极大值。要对每个轮廓(即关键点区域)进行处理。

threshold = 0.1
part = 1
probMap = output[0, part, :,:]
probMap = cv2.resize(probMap, (img_cv2.shape[1], img_cv2.shape[0]))
mapSmooth = cv2.GaussianBlur(probMap, (3, 3), 0, 0)
mapMask = np.uint8(mapSmooth > threshold)

keypoints = []
#找出每个关键点区域的全部轮廓
contours, hierarchy = cv2.findContours(mapMask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    blobMask = np.zeros(mapMask.shape)
    blobMask = cv2.fillConvexPoly(blobMask, cnt, 1)
    maskedProbMap = mapSmooth * blobMask
    _, maxVal, _, maxLoc = cv2.minMaxLoc(maskedProbMap)
    keypoints.append(maxLoc + (probMap[maxLoc[1], maxLoc[0]],))

img_cv2_copy = img_cv2.copy()
for keypoint in keypoints:
    cv2.circle(img_cv2_copy, (keypoint[0], keypoint[1]), 5, (255, 0, 0), -1, cv2.LINE_AA)

plt.figure()
plt.imshow(img_cv2_copy[:, :, ::-1])
plt.title("Keypoints")
plt.axis("off")
plt.show()

在这里插入图片描述
三,关键点对的检测
[1] - 将关键点对的两个点之间的连线进行划分,得到该连线上的 n 个点(Divide the line joining the two points comprising the pair. Find n points on this line.);
[2] - 判断这些点上的 PAF 是否与连接该关键点的线的方向相同(Check if the PAF on these points have the same direction as that of the line joining the points for this pair);
[3] - 如果方向满足特定程度,则为有效的关键点对(If the direction matches to a certain extent, then it is valid pair.)


# Find valid connections between the different 
#  joints of a all persons present
def getValidPairs(output):
    valid_pairs = []
    invalid_pairs = []
    n_interp_samples = 10
    paf_score_th = 0.1
    conf_th = 0.7
    # loop for every POSE_PAIR
    for k in range(len(mapIdx)):
        # A->B constitute a limb
        pafA = output[0, mapIdx[k][0], :, :]
        pafB = output[0, mapIdx[k][1], :, :]
        pafA = cv2.resize(pafA, (imgWidth, imgHeight))
        pafB = cv2.resize(pafB, (imgWidth, imgHeight))

        # 检测第一个 limb 和第二个 limb 的关键点位置
        candA = detected_keypoints[POSE_PAIRS[k][0]]
        candB = detected_keypoints[POSE_PAIRS[k][1]]
        nA = len(candA)
        nB = len(candB)

        # 如果检测到 joint-pair 的关键点位置,则,
        #  检查 candA 和 candB 中每个 joint.
        # 计算两个 joints 之间的距离向量(distance vector).
        # 计算两个 joints 之间插值点集合的 PAF 值.
        # 根据上述公式,计算 score 值,判断连接的有效性.
        if (nA != 0 and nB != 0):
            valid_pair = np.zeros((0, 3))
            for i in range(nA):
                max_j = -1
                maxScore = -1
                found = 0
                for j in range(nB):
                    # Find d_ij
                    d_ij = np.subtract(candB[j][:2], candA[i][:2])
                    norm = np.linalg.norm(d_ij)
                    if norm:
                        d_ij = d_ij / norm
                    else:
                        continue
                    # Find p(u)
                    interp_coord = list(
                        zip(np.linspace(candA[i][0],
                                        candB[j][0],
                                        num=n_interp_samples),
                            np.linspace(candA[i][1],
                                        candB[j][1],
                                        num=n_interp_samples)))
                    # Find L(p(u))
                    paf_interp = []
                    for k in range(len(interp_coord)):
                        paf_interp.append(
                            [pafA[int(round(interp_coord[k][1])),
                                  int(round(interp_coord[k][0]))],
                             pafB[int(round(interp_coord[k][1])),
                                  int(round(interp_coord[k][0]))]
                             ])
                        # Find E
                    paf_scores = np.dot(paf_interp, d_ij)
                    avg_paf_score = sum(paf_scores) / len(paf_scores)

                    # 判断连接是否有效.
                    # 如果对应于 PAF 的插值向量值大于阈值,则连接有效.
                    if (len(np.where(paf_scores > paf_score_th)[0]) /
                        n_interp_samples) > conf_th:
                        if avg_paf_score > maxScore:
                            max_j = j
                            maxScore = avg_paf_score
                            found = 1
                # Append the connection to the list
                if found:
                    valid_pair = np.append(
                        valid_pair,
                        [[candA[i][3], candB[max_j][3], maxScore]],
                        axis=0)

            # Append the detected connections to the global list
            valid_pairs.append(valid_pair)
        else:  # If no keypoints are detected
            print("No Connection : k = {}".format(k))
            invalid_pairs.append(k)
            valid_pairs.append([])
    print(valid_pairs)

    return valid_pairs, invalid_pairs

[1] - 选择属于同一个关键点对的关键点. 并分别存放在两个列表: candA 和 candB. candA 列表中的每个关键点可以与 candB 中的某些关键点相连接
[2] - 计算两个关键点之间的单位向量,其给定了关节点之间连线的方向.
[3] - 计算两个关键点之间连线的 10 个插值点.
[4] - 计算插值点的 PAF 与单位向量 d_ij 之间的点积(dot product).
[5] - 如果这些插值点的 70% 的都满足判定标准,则该关键点对是有效的.

四.关键点组合的具体实现分析
对于每个检测到的有效 joint pair,分配属于一个人体的 joints
[1] - 首先创建保存每个人体的所有关键点的空列表.
[2] - 如果 partA 不在任一人体列表里,则表示该关键点对属于一个新出现的人体,故创建新的列表.

def getPersonwiseKeypoints(valid_pairs, invalid_pairs):
# 每一行的最后一个值为 overall score.
personwiseKeypoints = -1 * np.ones((0, 19))

for k in range(len(mapIdx)):
    if k not in invalid_pairs:
        partAs = valid_pairs[k][:,0]
        partBs = valid_pairs[k][:,1]
        indexA, indexB = np.array(POSE_PAIRS[k])

        for i in range(len(valid_pairs[k])): 
            found = 0
            person_idx = -1
            for j in range(len(personwiseKeypoints)):
                if personwiseKeypoints[j][indexA] == partAs[i]:
                    person_idx = j
                    found = 1
                    break

            if found:
                personwiseKeypoints[person_idx][indexB] = partBs[i]
                personwiseKeypoints[person_idx][-1] += 
                	keypoints_list[partBs[i].astype(int), 2] + 
                    valid_pairs[k][i][2]

            # if find no partA in the subset, create a new subset
            elif not found and k < 17:
                row = -1 * np.ones(19)
                row[indexA] = partAs[i]
                row[indexB] = partBs[i]
                # add the keypoint_scores for the two keypoints and the paf_score 
                row[-1] = sum(
                    keypoints_list[valid_pairs[k][i,:2].astype(int), 2]) 
                + valid_pairs[k][i][2]
                personwiseKeypoints = np.vstack([personwiseKeypoints, row])
return personwiseKeypoints```python


版权声明:本文为qq_43258953原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。