A class that specializes in drawing skeleton vertices on images. It uses
specified key points to determine the locations where the vertices should be
drawn.
classVertexAnnotator(BaseKeyPointAnnotator):""" A class that specializes in drawing skeleton vertices on images. It uses specified key points to determine the locations where the vertices should be drawn. """def__init__(self,color:Color=Color.ROBOFLOW,radius:int=4,)->None:""" Args: color (Color): The color to use for annotating key points. radius (int): The radius of the circles used to represent the key points. """self.color=colorself.radius=radius@ensure_cv2_image_for_annotationdefannotate(self,scene:ImageType,key_points:KeyPoints)->ImageType:""" Annotates the given scene with skeleton vertices based on the provided key points. It draws circles at each key point location. Args: scene (ImageType): The image where skeleton vertices will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) vertex_annotator = sv.VertexAnnotator( color=sv.Color.GREEN, radius=10 ) annotated_frame = vertex_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  """assertisinstance(scene,np.ndarray)iflen(key_points)==0:returnsceneforxyinkey_points.xy:forx,yinxy:cv2.circle(img=scene,center=(int(x),int(y)),radius=self.radius,color=self.color.as_bgr(),thickness=-1,)returnscene
def__init__(self,color:Color=Color.ROBOFLOW,radius:int=4,)->None:""" Args: color (Color): The color to use for annotating key points. radius (int): The radius of the circles used to represent the key points. """self.color=colorself.radius=radius
@ensure_cv2_image_for_annotationdefannotate(self,scene:ImageType,key_points:KeyPoints)->ImageType:""" Annotates the given scene with skeleton vertices based on the provided key points. It draws circles at each key point location. Args: scene (ImageType): The image where skeleton vertices will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) vertex_annotator = sv.VertexAnnotator( color=sv.Color.GREEN, radius=10 ) annotated_frame = vertex_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  """assertisinstance(scene,np.ndarray)iflen(key_points)==0:returnsceneforxyinkey_points.xy:forx,yinxy:cv2.circle(img=scene,center=(int(x),int(y)),radius=self.radius,color=self.color.as_bgr(),thickness=-1,)returnscene
A class that specializes in drawing skeleton edges on images using specified key
points. It connects key points with lines to form the skeleton structure.
classEdgeAnnotator(BaseKeyPointAnnotator):""" A class that specializes in drawing skeleton edges on images using specified key points. It connects key points with lines to form the skeleton structure. """def__init__(self,color:Color=Color.ROBOFLOW,thickness:int=2,edges:Optional[List[Tuple[int,int]]]=None,)->None:""" Args: color (Color): The color to use for the edges. thickness (int): The thickness of the edges. edges (Optional[List[Tuple[int, int]]]): The edges to draw. If set to `None`, will attempt to select automatically. """self.color=colorself.thickness=thicknessself.edges=edges@ensure_cv2_image_for_annotationdefannotate(self,scene:ImageType,key_points:KeyPoints)->ImageType:""" Annotates the given scene by drawing lines between specified key points to form edges. Args: scene (ImageType): The image where skeleton edges will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. Returns: Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) edge_annotator = sv.EdgeAnnotator( color=sv.Color.GREEN, thickness=5 ) annotated_frame = edge_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  """assertisinstance(scene,np.ndarray)iflen(key_points)==0:returnsceneforxyinkey_points.xy:edges=self.edgesifnotedges:edges=SKELETONS_BY_VERTEX_COUNT.get(len(xy))ifnotedges:warn(f"No skeleton found with {len(xy)} vertices")returnsceneforclass_a,class_binedges:xy_a=xy[class_a-1]xy_b=xy[class_b-1]missing_a=np.allclose(xy_a,0)missing_b=np.allclose(xy_b,0)ifmissing_aormissing_b:continuecv2.line(img=scene,pt1=(int(xy_a[0]),int(xy_a[1])),pt2=(int(xy_b[0]),int(xy_b[1])),color=self.color.as_bgr(),thickness=self.thickness,)returnscene
def__init__(self,color:Color=Color.ROBOFLOW,thickness:int=2,edges:Optional[List[Tuple[int,int]]]=None,)->None:""" Args: color (Color): The color to use for the edges. thickness (int): The thickness of the edges. edges (Optional[List[Tuple[int, int]]]): The edges to draw. If set to `None`, will attempt to select automatically. """self.color=colorself.thickness=thicknessself.edges=edges
@ensure_cv2_image_for_annotationdefannotate(self,scene:ImageType,key_points:KeyPoints)->ImageType:""" Annotates the given scene by drawing lines between specified key points to form edges. Args: scene (ImageType): The image where skeleton edges will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. Returns: Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) edge_annotator = sv.EdgeAnnotator( color=sv.Color.GREEN, thickness=5 ) annotated_frame = edge_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  """assertisinstance(scene,np.ndarray)iflen(key_points)==0:returnsceneforxyinkey_points.xy:edges=self.edgesifnotedges:edges=SKELETONS_BY_VERTEX_COUNT.get(len(xy))ifnotedges:warn(f"No skeleton found with {len(xy)} vertices")returnsceneforclass_a,class_binedges:xy_a=xy[class_a-1]xy_b=xy[class_b-1]missing_a=np.allclose(xy_a,0)missing_b=np.allclose(xy_b,0)ifmissing_aormissing_b:continuecv2.line(img=scene,pt1=(int(xy_a[0]),int(xy_a[1])),pt2=(int(xy_b[0]),int(xy_b[1])),color=self.color.as_bgr(),thickness=self.thickness,)returnscene
classVertexLabelAnnotator:""" A class that draws labels of skeleton vertices on images. It uses specified key points to determine the locations where the vertices should be drawn. """def__init__(self,color:Union[Color,List[Color]]=Color.ROBOFLOW,text_color:Union[Color,List[Color]]=Color.WHITE,text_scale:float=0.5,text_thickness:int=1,text_padding:int=10,border_radius:int=0,smart_position:bool=False,):""" Args: color (Union[Color, List[Color]]): The color to use for each keypoint label. If a list is provided, the colors will be used in order for each keypoint. text_color (Union[Color, List[Color]]): The color to use for the labels. If a list is provided, the colors will be used in order for each keypoint. text_scale (float): The scale of the text. text_thickness (int): The thickness of the text. text_padding (int): The padding around the text. border_radius (int): The radius of the rounded corners of the boxes. Set to a high value to produce circles. smart_position (bool): Spread out the labels to avoid overlap. """self.border_radius:int=border_radiusself.color:Union[Color,List[Color]]=colorself.text_color:Union[Color,List[Color]]=text_colorself.text_scale:float=text_scaleself.text_thickness:int=text_thicknessself.text_padding:int=text_paddingself.smart_position=smart_positiondefannotate(self,scene:ImageType,key_points:KeyPoints,labels:Optional[List[str]]=None,)->ImageType:""" A class that draws labels of skeleton vertices on images. It uses specified key points to determine the locations where the vertices should be drawn. Args: scene (ImageType): The image where vertex labels will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. labels (Optional[List[str]]): A list of labels to be displayed on the annotated image. If not provided, keypoint indices will be used. Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) vertex_label_annotator = sv.VertexLabelAnnotator( color=sv.Color.GREEN, text_color=sv.Color.BLACK, border_radius=5 ) annotated_frame = vertex_label_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  !!! tip `VertexLabelAnnotator` allows to customize the color of each keypoint label values. Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) LABELS = [ "nose", "left eye", "right eye", "left ear", "right ear", "left shoulder", "right shoulder", "left elbow", "right elbow", "left wrist", "right wrist", "left hip", "right hip", "left knee", "right knee", "left ankle", "right ankle" ] COLORS = [ "#FF6347", "#FF6347", "#FF6347", "#FF6347", "#FF6347", "#FF1493", "#00FF00", "#FF1493", "#00FF00", "#FF1493", "#00FF00", "#FFD700", "#00BFFF", "#FFD700", "#00BFFF", "#FFD700", "#00BFFF" ] COLORS = [sv.Color.from_hex(color_hex=c) for c in COLORS] vertex_label_annotator = sv.VertexLabelAnnotator( color=COLORS, text_color=sv.Color.BLACK, border_radius=5 ) annotated_frame = vertex_label_annotator.annotate( scene=image.copy(), key_points=key_points, labels=labels ) ```  """assertisinstance(scene,np.ndarray)font=cv2.FONT_HERSHEY_SIMPLEXskeletons_count,points_count,_=key_points.xy.shapeifskeletons_count==0:returnsceneanchors=key_points.xy.reshape(points_count*skeletons_count,2).astype(int)mask=np.all(anchors!=0,axis=1)ifnotnp.any(mask):returnscenecolors=self.preprocess_and_validate_colors(colors=self.color,points_count=points_count,skeletons_count=skeletons_count,)text_colors=self.preprocess_and_validate_colors(colors=self.text_color,points_count=points_count,skeletons_count=skeletons_count,)labels=self.preprocess_and_validate_labels(labels=labels,points_count=points_count,skeletons_count=skeletons_count)anchors=anchors[mask]colors=colors[mask]text_colors=text_colors[mask]labels=labels[mask]xyxy=np.array([self.get_text_bounding_box(text=label,font=font,text_scale=self.text_scale,text_thickness=self.text_thickness,center_coordinates=tuple(anchor),)foranchor,labelinzip(anchors,labels)])xyxy_padded=pad_boxes(xyxy=xyxy,px=self.text_padding)ifself.smart_position:xyxy_padded=spread_out_boxes(xyxy_padded)xyxy=pad_boxes(xyxy=xyxy_padded,px=-self.text_padding)fortext,color,text_color,box,box_paddedinzip(labels,colors,text_colors,xyxy,xyxy_padded):draw_rounded_rectangle(scene=scene,rect=Rect.from_xyxy(box_padded),color=color,border_radius=self.border_radius,)cv2.putText(img=scene,text=text,org=(box[0],box[3]),fontFace=font,fontScale=self.text_scale,color=text_color.as_bgr(),thickness=self.text_thickness,lineType=cv2.LINE_AA,)returnscene@staticmethoddefget_text_bounding_box(text:str,font:int,text_scale:float,text_thickness:int,center_coordinates:Tuple[int,int],)->Tuple[int,int,int,int]:text_w,text_h=cv2.getTextSize(text=text,fontFace=font,fontScale=text_scale,thickness=text_thickness,)[0]center_x,center_y=center_coordinatesreturn(center_x-text_w//2,center_y-text_h//2,center_x+text_w//2,center_y+text_h//2,)@staticmethoddefpreprocess_and_validate_labels(labels:Optional[List[str]],points_count:int,skeletons_count:int)->np.ndarray:iflabelsandlen(labels)!=points_count:raiseValueError(f"Number of labels ({len(labels)}) must match number of key points "f"({points_count}).")iflabelsisNone:labels=[str(i)foriinrange(points_count)]returnnp.array(labels*skeletons_count)@staticmethoddefpreprocess_and_validate_colors(colors:Optional[Union[Color,List[Color]]],points_count:int,skeletons_count:int,)->np.ndarray:ifisinstance(colors,list)andlen(colors)!=points_count:raiseValueError(f"Number of colors ({len(colors)}) must match number of key points "f"({points_count}).")return(np.array(colors*skeletons_count)ifisinstance(colors,list)elsenp.array([colors]*points_count*skeletons_count))
def__init__(self,color:Union[Color,List[Color]]=Color.ROBOFLOW,text_color:Union[Color,List[Color]]=Color.WHITE,text_scale:float=0.5,text_thickness:int=1,text_padding:int=10,border_radius:int=0,smart_position:bool=False,):""" Args: color (Union[Color, List[Color]]): The color to use for each keypoint label. If a list is provided, the colors will be used in order for each keypoint. text_color (Union[Color, List[Color]]): The color to use for the labels. If a list is provided, the colors will be used in order for each keypoint. text_scale (float): The scale of the text. text_thickness (int): The thickness of the text. text_padding (int): The padding around the text. border_radius (int): The radius of the rounded corners of the boxes. Set to a high value to produce circles. smart_position (bool): Spread out the labels to avoid overlap. """self.border_radius:int=border_radiusself.color:Union[Color,List[Color]]=colorself.text_color:Union[Color,List[Color]]=text_colorself.text_scale:float=text_scaleself.text_thickness:int=text_thicknessself.text_padding:int=text_paddingself.smart_position=smart_position
defannotate(self,scene:ImageType,key_points:KeyPoints,labels:Optional[List[str]]=None,)->ImageType:""" A class that draws labels of skeleton vertices on images. It uses specified key points to determine the locations where the vertices should be drawn. Args: scene (ImageType): The image where vertex labels will be drawn. `ImageType` is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`. key_points (KeyPoints): A collection of key points where each key point consists of x and y coordinates. labels (Optional[List[str]]): A list of labels to be displayed on the annotated image. If not provided, keypoint indices will be used. Returns: The annotated image, matching the type of `scene` (`numpy.ndarray` or `PIL.Image.Image`) Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) vertex_label_annotator = sv.VertexLabelAnnotator( color=sv.Color.GREEN, text_color=sv.Color.BLACK, border_radius=5 ) annotated_frame = vertex_label_annotator.annotate( scene=image.copy(), key_points=key_points ) ```  !!! tip `VertexLabelAnnotator` allows to customize the color of each keypoint label values. Example: ```python import supervision as sv image = ... key_points = sv.KeyPoints(...) LABELS = [ "nose", "left eye", "right eye", "left ear", "right ear", "left shoulder", "right shoulder", "left elbow", "right elbow", "left wrist", "right wrist", "left hip", "right hip", "left knee", "right knee", "left ankle", "right ankle" ] COLORS = [ "#FF6347", "#FF6347", "#FF6347", "#FF6347", "#FF6347", "#FF1493", "#00FF00", "#FF1493", "#00FF00", "#FF1493", "#00FF00", "#FFD700", "#00BFFF", "#FFD700", "#00BFFF", "#FFD700", "#00BFFF" ] COLORS = [sv.Color.from_hex(color_hex=c) for c in COLORS] vertex_label_annotator = sv.VertexLabelAnnotator( color=COLORS, text_color=sv.Color.BLACK, border_radius=5 ) annotated_frame = vertex_label_annotator.annotate( scene=image.copy(), key_points=key_points, labels=labels ) ```  """assertisinstance(scene,np.ndarray)font=cv2.FONT_HERSHEY_SIMPLEXskeletons_count,points_count,_=key_points.xy.shapeifskeletons_count==0:returnsceneanchors=key_points.xy.reshape(points_count*skeletons_count,2).astype(int)mask=np.all(anchors!=0,axis=1)ifnotnp.any(mask):returnscenecolors=self.preprocess_and_validate_colors(colors=self.color,points_count=points_count,skeletons_count=skeletons_count,)text_colors=self.preprocess_and_validate_colors(colors=self.text_color,points_count=points_count,skeletons_count=skeletons_count,)labels=self.preprocess_and_validate_labels(labels=labels,points_count=points_count,skeletons_count=skeletons_count)anchors=anchors[mask]colors=colors[mask]text_colors=text_colors[mask]labels=labels[mask]xyxy=np.array([self.get_text_bounding_box(text=label,font=font,text_scale=self.text_scale,text_thickness=self.text_thickness,center_coordinates=tuple(anchor),)foranchor,labelinzip(anchors,labels)])xyxy_padded=pad_boxes(xyxy=xyxy,px=self.text_padding)ifself.smart_position:xyxy_padded=spread_out_boxes(xyxy_padded)xyxy=pad_boxes(xyxy=xyxy_padded,px=-self.text_padding)fortext,color,text_color,box,box_paddedinzip(labels,colors,text_colors,xyxy,xyxy_padded):draw_rounded_rectangle(scene=scene,rect=Rect.from_xyxy(box_padded),color=color,border_radius=self.border_radius,)cv2.putText(img=scene,text=text,org=(box[0],box[3]),fontFace=font,fontScale=self.text_scale,color=text_color.as_bgr(),thickness=self.text_thickness,lineType=cv2.LINE_AA,)returnscene