| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- # Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import copy
- import math
- import numpy as np
- from PIL import Image
- from ....utils.deps import function_requires_deps, is_dep_available
- from ...common.result import BaseCVResult, JsonMixin
- if is_dep_available("opencv-contrib-python"):
- import cv2
- if is_dep_available("matplotlib"):
- import matplotlib.pyplot as plt
- def get_color(idx):
- idx = idx * 3
- color = ((37 * idx) % 255, (17 * idx) % 255, (29 * idx) % 255)
- return color
- @function_requires_deps("matplotlib", "opencv-contrib-python")
- def draw_keypoints(img, results, visual_thresh=0.1, ids=None):
- plt.switch_backend("agg")
- skeletons = results["keypoints"]
- skeletons = np.array(skeletons)
- if len(skeletons) > 0:
- kpt_nums = skeletons.shape[1]
- if kpt_nums == 17: # plot coco keypoint
- EDGES = [
- (0, 1),
- (0, 2),
- (1, 3),
- (2, 4),
- (3, 5),
- (4, 6),
- (5, 7),
- (6, 8),
- (7, 9),
- (8, 10),
- (5, 11),
- (6, 12),
- (11, 13),
- (12, 14),
- (13, 15),
- (14, 16),
- (11, 12),
- ]
- else: # plot mpii keypoint
- EDGES = [
- (0, 1),
- (1, 2),
- (3, 4),
- (4, 5),
- (2, 6),
- (3, 6),
- (6, 7),
- (7, 8),
- (8, 9),
- (10, 11),
- (11, 12),
- (13, 14),
- (14, 15),
- (8, 12),
- (8, 13),
- ]
- NUM_EDGES = len(EDGES)
- colors = [
- [255, 0, 0],
- [255, 85, 0],
- [255, 170, 0],
- [255, 255, 0],
- [170, 255, 0],
- [85, 255, 0],
- [0, 255, 0],
- [0, 255, 85],
- [0, 255, 170],
- [0, 255, 255],
- [0, 170, 255],
- [0, 85, 255],
- [0, 0, 255],
- [85, 0, 255],
- [170, 0, 255],
- [255, 0, 255],
- [255, 0, 170],
- [255, 0, 85],
- ]
- plt.figure()
- color_set = results["colors"] if "colors" in results else None
- if "bbox" in results and ids is None:
- bboxs = results["bbox"]
- for j, rect in enumerate(bboxs):
- xmin, ymin, xmax, ymax = rect
- color = (
- colors[0] if color_set is None else colors[color_set[j] % len(colors)]
- )
- cv2.rectangle(img, (xmin, ymin), (xmax, ymax), color, 1)
- canvas = img.copy()
- for i in range(kpt_nums):
- for j in range(len(skeletons)):
- if skeletons[j][i, 2] < visual_thresh:
- continue
- if ids is None:
- color = (
- colors[i]
- if color_set is None
- else colors[color_set[j] % len(colors)]
- )
- else:
- color = get_color(ids[j])
- cv2.circle(
- canvas,
- tuple(skeletons[j][i, 0:2].astype("int32")),
- 2,
- color,
- thickness=-1,
- )
- stickwidth = 1
- for i in range(NUM_EDGES):
- for j in range(len(skeletons)):
- edge = EDGES[i]
- if (
- skeletons[j][edge[0], 2] < visual_thresh
- or skeletons[j][edge[1], 2] < visual_thresh
- ):
- continue
- cur_canvas = canvas.copy()
- X = [skeletons[j][edge[0], 1], skeletons[j][edge[1], 1]]
- Y = [skeletons[j][edge[0], 0], skeletons[j][edge[1], 0]]
- mX = np.mean(X)
- mY = np.mean(Y)
- length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5
- angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1]))
- polygon = cv2.ellipse2Poly(
- (int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1
- )
- if ids is None:
- color = (
- colors[i]
- if color_set is None
- else colors[color_set[j] % len(colors)]
- )
- else:
- color = get_color(ids[j])
- cv2.fillConvexPoly(cur_canvas, polygon, color)
- canvas = cv2.addWeighted(canvas, 0.4, cur_canvas, 0.6, 0)
- plt.close()
- return canvas
- class KptResult(BaseCVResult):
- """Save Result Transform"""
- def _to_img(self):
- """apply"""
- if "kpts" in self: # for single module result
- keypoints = [kpt["keypoints"] for kpt in self["kpts"]]
- else:
- keypoints = [
- obj["keypoints"] for obj in self["boxes"]
- ] # for top-down pipeline result
- image = self["input_img"]
- if keypoints:
- image = draw_keypoints(image, dict(keypoints=np.stack(keypoints)))
- image = Image.fromarray(image[..., ::-1])
- return {"res": image}
- def _to_str(self, *args, **kwargs):
- data = copy.deepcopy(self)
- data.pop("input_img")
- return JsonMixin._to_str(data, *args, **kwargs)
- def _to_json(self, *args, **kwargs):
- data = copy.deepcopy(self)
- data.pop("input_img")
- return JsonMixin._to_json(data, *args, **kwargs)
|