From b7dae086fd0b42c398c292ac8018ac17daa46016 Mon Sep 17 00:00:00 2001 From: Amit Moryossef Date: Thu, 9 Jan 2025 11:59:26 +0100 Subject: [PATCH 1/3] fix(visualizer): painter algorithm was in reverse --- src/js/pose_viewer/package.json | 2 +- .../pose-viewer/renderers/pose-renderer.tsx | 2 +- src/python/pose_format/pose_visualizer.py | 35 ++++++++++--------- .../tensorflow/pose_representation_test.py | 2 +- src/python/pose_format/utils/generic.py | 2 +- src/python/pose_format/utils/holistic.py | 4 +-- src/python/pose_format/utils/openpose.py | 2 +- src/python/pose_format/utils/openpose_135.py | 2 +- 8 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/js/pose_viewer/package.json b/src/js/pose_viewer/package.json index 5f5cb3e..31a26f7 100644 --- a/src/js/pose_viewer/package.json +++ b/src/js/pose_viewer/package.json @@ -1,6 +1,6 @@ { "name": "pose-viewer", - "version": "1.0.0", + "version": "1.0.1", "description": "Stencil Component Starter", "homepage": "https://github.com/sign-language-processing/pose", "main": "dist/index.cjs.js", diff --git a/src/js/pose_viewer/src/components/pose-viewer/renderers/pose-renderer.tsx b/src/js/pose_viewer/src/components/pose-viewer/renderers/pose-renderer.tsx index a56c635..acb2142 100644 --- a/src/js/pose_viewer/src/components/pose-viewer/renderers/pose-renderer.tsx +++ b/src/js/pose_viewer/src/components/pose-viewer/renderers/pose-renderer.tsx @@ -59,7 +59,7 @@ export abstract class PoseRenderer { return lines .filter(Boolean) // Remove invalid lines - .sort((a, b) => a.z - b.z) // Sort lines by depth + .sort((a, b) => b.z - a.z) // Sort lines by depth .map(({from, to, color}) => this.renderLimb(from, to, color)); } diff --git a/src/python/pose_format/pose_visualizer.py b/src/python/pose_format/pose_visualizer.py index 86e1ccd..701a541 100644 --- a/src/python/pose_format/pose_visualizer.py +++ b/src/python/pose_format/pose_visualizer.py @@ -40,7 +40,8 @@ def __init__(self, pose: Pose, thickness=None): except ImportError: raise ImportError("Please install OpenCV with: pip install opencv-python") - def _draw_frame(self, frame: ma.MaskedArray, frame_confidence: np.ndarray, img, + def _draw_frame(self, frame: ma.MaskedArray, + frame_confidence: np.ndarray, img, transparency: bool = False) -> np.ndarray: """ Draw frame of pose data of an image. @@ -74,7 +75,6 @@ def _draw_frame(self, frame: ma.MaskedArray, frame_confidence: np.ndarray, img, for person, person_confidence in zip(frame, frame_confidence): c = person_confidence.tolist() - points = [p for p in person.tolist()] idx = 0 for component in self.pose.header.components: colors = [np.array(c[::-1]) for c in component.colors] @@ -91,7 +91,7 @@ def _point_color(p_i: int): # Collect Points for i, point_name in enumerate(component.points): if c[i + idx] > 0: - center = points[i + idx] + center = person[i + idx] draw_operations.append({ 'type': 'circle', 'center': center, @@ -103,8 +103,8 @@ def _point_color(p_i: int): }) if self.pose.header.is_bbox: - point1 = points[0 + idx] - point2 = points[1 + idx] + point1 = person[0 + idx] + point2 = person[1 + idx] color = tuple(np.mean([_point_color(0), _point_color(1)], axis=0)) draw_operations.append({ @@ -119,8 +119,8 @@ def _point_color(p_i: int): # Collect Limbs for (p1, p2) in component.limbs: if c[p1 + idx] > 0 and c[p2 + idx] > 0: - point1 = points[p1 + idx] - point2 = points[p2 + idx] + point1 = person[p1 + idx] + point2 = person[p2 + idx] color = tuple(np.mean([_point_color(p1), _point_color(p2)], axis=0)) @@ -136,27 +136,30 @@ def _point_color(p_i: int): idx += len(component.points) - draw_operations = sorted(draw_operations, key=lambda op: op['z']) + draw_operations = sorted(draw_operations, key=lambda op: op['z'], reverse=True) + + def point_to_xy(point: ma.MaskedArray): + return tuple([round(p) for p in point[:2]]) # Execute draw operations for op in draw_operations: if op['type'] == 'circle': self.cv2.circle(img=img, - center=tuple(op['center'][:2]), + center=point_to_xy(op['center']), radius=op['radius'], color=op['color'], thickness=op['thickness'], lineType=op['lineType']) elif op['type'] == 'rectangle': self.cv2.rectangle(img=img, - pt1=tuple(op['pt1'][:2]), - pt2=tuple(op['pt2'][:2]), + pt1=point_to_xy(op['pt1']), + pt2=point_to_xy(op['pt2']), color=op['color'], thickness=op['thickness']) elif op['type'] == 'line': self.cv2.line(img, - pt1=tuple(op['pt1'][:2]), - pt2=tuple(op['pt2'][:2]), + pt1=point_to_xy(op['pt1']), + pt2=point_to_xy(op['pt2']), color=op['color'], thickness=op['thickness'], lineType=op['lineType']) @@ -184,12 +187,11 @@ def draw(self, background_color: Tuple[int, int, int] = (255, 255, 255), max_fra # ... if transparency: background_color += (0,) - int_frames = np.array(np.around(self.pose.body.data.data), dtype="int32") background = np.full( (self.pose.header.dimensions.height, self.pose.header.dimensions.width, len(background_color)), fill_value=background_color, dtype="uint8") - for frame, confidence in itertools.islice(zip(int_frames, self.pose.body.confidence), max_frames): + for frame, confidence in itertools.islice(zip(self.pose.body.data, self.pose.body.confidence), max_frames): yield self._draw_frame(frame, confidence, img=background.copy(), transparency=transparency) def draw_on_video(self, background_video, max_frames: int = None, blur=False): @@ -471,9 +473,8 @@ def draw(self, background_color: int = 0, foreground_color: int = 255): np.ndarray frames with drawn pose """ - int_frames = np.array(np.around(self.pose.body.data.data), dtype="int32") background = np.full((self.pose.header.dimensions.height, self.pose.header.dimensions.width), fill_value=background_color, dtype="uint8") - for frame in int_frames: + for frame in self.pose.body.data: yield self._draw_frame(frame, img=background.copy(), color=foreground_color) diff --git a/src/python/pose_format/tensorflow/pose_representation_test.py b/src/python/pose_format/tensorflow/pose_representation_test.py index b449a45..98b868f 100644 --- a/src/python/pose_format/tensorflow/pose_representation_test.py +++ b/src/python/pose_format/tensorflow/pose_representation_test.py @@ -16,7 +16,7 @@ dimensions = PoseHeaderDimensions(width=0, height=0, depth=0) components = [OpenPose_Hand_Component("hand_left_keypoints_2d")] -header: PoseHeader = PoseHeader(version=0.1, dimensions=dimensions, components=components) +header: PoseHeader = PoseHeader(version=0.2, dimensions=dimensions, components=components) representation = TensorflowPoseRepresentation( header=header, diff --git a/src/python/pose_format/utils/generic.py b/src/python/pose_format/utils/generic.py index de6fbb6..4a06c13 100644 --- a/src/python/pose_format/utils/generic.py +++ b/src/python/pose_format/utils/generic.py @@ -109,7 +109,7 @@ def normalize_hands_3d(pose: Pose, left_hand=True, right_hand=True): def fake_pose(num_frames: int, fps=25, dims=2, components=OpenPose_Components): dimensions = PoseHeaderDimensions(width=1, height=1, depth=1) - header = PoseHeader(version=0.1, dimensions=dimensions, components=components) + header = PoseHeader(version=0.2, dimensions=dimensions, components=components) total_points = header.total_points() data = np.random.randn(num_frames, 1, total_points, dims) diff --git a/src/python/pose_format/utils/holistic.py b/src/python/pose_format/utils/holistic.py index 999ad0e..b254472 100644 --- a/src/python/pose_format/utils/holistic.py +++ b/src/python/pose_format/utils/holistic.py @@ -327,7 +327,7 @@ def load_holistic(frames: list, refine_face_landmarks = 'refine_face_landmarks' in additional_holistic_config and additional_holistic_config[ 'refine_face_landmarks'] additional_face_points = 10 if refine_face_landmarks else 0 - header: PoseHeader = PoseHeader(version=0.1, + header: PoseHeader = PoseHeader(version=0.2, dimensions=dimensions, components=holistic_components(pf, additional_face_points)) body: NumPyPoseBody = process_holistic(frames, fps, width, height, kinect, progress, additional_face_points, @@ -355,7 +355,7 @@ def formatted_holistic_pose(width: int, height: int, additional_face_points: int Formatted pose components """ dimensions = PoseHeaderDimensions(width=width, height=height, depth=1000) - header = PoseHeader(version=0.1, + header = PoseHeader(version=0.2, dimensions=dimensions, components=holistic_components("XYZC", additional_face_points)) body = NumPyPoseBody( diff --git a/src/python/pose_format/utils/openpose.py b/src/python/pose_format/utils/openpose.py index 12f7b3f..36daed2 100644 --- a/src/python/pose_format/utils/openpose.py +++ b/src/python/pose_format/utils/openpose.py @@ -250,7 +250,7 @@ def load_openpose(frames: OpenPoseFrames, """ dimensions = PoseHeaderDimensions(width=width, height=height, depth=depth) - header: PoseHeader = PoseHeader(version=0.1, dimensions=dimensions, components=OpenPose_Components) + header: PoseHeader = PoseHeader(version=0.2, dimensions=dimensions, components=OpenPose_Components) total_points = header.total_points() diff --git a/src/python/pose_format/utils/openpose_135.py b/src/python/pose_format/utils/openpose_135.py index 68c2c22..9acfa3c 100644 --- a/src/python/pose_format/utils/openpose_135.py +++ b/src/python/pose_format/utils/openpose_135.py @@ -128,7 +128,7 @@ def load_openpose_135_directory(*args, **kwargs) -> Pose: if __name__ == "__main__": dimensions = PoseHeaderDimensions(width=512, height=512, depth=0) - header = PoseHeader(version=0.1, dimensions=dimensions, components=OpenPose_Components) + header = PoseHeader(version=0.2, dimensions=dimensions, components=OpenPose_Components) with open( "/home/nlp/amit/sign-language/sign-language-datasets/sign_language_datasets/datasets/autsl/openpose_135.poseheader", From d92f4643f174a2fdfeb58fe05ae375bc5b0e2cc2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 9 Jan 2025 11:00:55 +0000 Subject: [PATCH 2/3] Bump version to 0.8.2 --- src/python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/pyproject.toml b/src/python/pyproject.toml index 98e2769..581fa8e 100644 --- a/src/python/pyproject.toml +++ b/src/python/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "pose_format" description = "Library for viewing, augmenting, and handling .pose files" -version = "0.8.1" +version = "0.8.2" keywords = ["Pose Files", "Pose Interpolation", "Pose Augmentation"] authors = [ { name = "Amit Moryossef", email = "amitmoryossef@gmail.com" }, From 3995b01e8575692e3528134560fe23d49a4d0dfe Mon Sep 17 00:00:00 2001 From: cleong110 <122366389+cleong110@users.noreply.github.com> Date: Thu, 9 Jan 2025 06:13:24 -0500 Subject: [PATCH 3/3] Bugfix: raise ValueError not return ValueError (#143) * CDL: minor doc typo fix * Undoing some changes that got mixed in * Update holistic.py: return ValueError-> raise ValueError --- src/python/pose_format/utils/holistic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/pose_format/utils/holistic.py b/src/python/pose_format/utils/holistic.py index b254472..d9696a1 100644 --- a/src/python/pose_format/utils/holistic.py +++ b/src/python/pose_format/utils/holistic.py @@ -399,7 +399,7 @@ def load_mediapipe_directory(directory: str, fps: int, width: int, height: int, num_right_hand_points = first_frame["right_hand_landmarks"]["num_landmarks"] additional_face_points = 10 if (num_face_points == 478 or num_face_points == 128) else 0 else: - return ValueError("No frames found in directory: {}".format(directory)) + raise ValueError("No frames found in directory: {}".format(directory)) def load_mediapipe_frame(frame): """