prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Better handling of wrong data types of mask for sv.PolygonZone()
  ### Search before asking
  
  - [X] I have searched the Supervision [issues](https://github.com/roboflow/supervision/issues) and found no similar feature requests.
  
  
  ### Description
  
  <img width="898" alt="image" src="https://github.com/roboflow/supervision/assets/47161914/6eebe556-97f1-452b-8757-17062548ca12">
  
  OpenCV errors out with an uninformative error when the dtype of the mask is wrong. 
  
  Would be good to add catch if dtype != np.int32 and raise an Exception.
  
  ### Use case
  
  I was trying to create a mask in CVAT, the exported segmentation had decimal places, np.array(coords) did not convert to np.int32, and I was confused by the bad error message.
  
  This is likely to happen to other users too .
  
  ### Additional
  
  Happy to submit PR
  
  ### Are you willing to submit a PR?
  
  - [X] Yes I'd like to help by submitting a PR!
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `supervision/detection/tools/polygon_zone.py`
  Content:
  ```
  1 from dataclasses import replace
  2 from typing import Optional, Tuple
  3 
  4 import cv2
  5 import numpy as np
  6 
  7 from supervision import Detections
  8 from supervision.detection.utils import clip_boxes, polygon_to_mask
  9 from supervision.draw.color import Color
  10 from supervision.draw.utils import draw_polygon, draw_text
  11 from supervision.geometry.core import Position
  12 from supervision.geometry.utils import get_polygon_center
  13 
  14 
  15 class PolygonZone:
  16     """
  17     A class for defining a polygon-shaped zone within a frame for detecting objects.
  18 
  19     Attributes:
  20         polygon (np.ndarray): A numpy array defining the polygon vertices
  21         frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)
  22         triggering_position (Position): The position within the bounding box that triggers the zone (default: Position.BOTTOM_CENTER)
  23         current_count (int): The current count of detected objects within the zone
  24         mask (np.ndarray): The 2D bool mask for the polygon zone
  25     """
  26 
  27     def __init__(
  28         self,
  29         polygon: np.ndarray,
  30         frame_resolution_wh: Tuple[int, int],
  31         triggering_position: Position = Position.BOTTOM_CENTER,
  32     ):
  33         self.polygon = polygon
  34         self.frame_resolution_wh = frame_resolution_wh
  35         self.triggering_position = triggering_position
  36         self.current_count = 0
  37 
  38         width, height = frame_resolution_wh
  39         self.mask = polygon_to_mask(
  40             polygon=polygon, resolution_wh=(width + 1, height + 1)
  41         )
  42 
  43     def trigger(self, detections: Detections) -> np.ndarray:
  44         """
  45         Determines if the detections are within the polygon zone.
  46 
  47         Parameters:
  48             detections (Detections): The detections to be checked against the polygon zone
  49 
  50         Returns:
  51             np.ndarray: A boolean numpy array indicating if each detection is within the polygon zone
  52         """
  53 
  54         clipped_xyxy = clip_boxes(
  55             boxes_xyxy=detections.xyxy, frame_resolution_wh=self.frame_resolution_wh
  56         )
  57         clipped_detections = replace(detections, xyxy=clipped_xyxy)
  58         clipped_anchors = np.ceil(
  59             clipped_detections.get_anchor_coordinates(anchor=self.triggering_position)
  60         ).astype(int)
  61         is_in_zone = self.mask[clipped_anchors[:, 1], clipped_anchors[:, 0]]
  62         self.current_count = np.sum(is_in_zone)
  63         return is_in_zone.astype(bool)
  64 
  65 
  66 class PolygonZoneAnnotator:
  67     """
  68     A class for annotating a polygon-shaped zone within a frame with a count of detected objects.
  69 
  70     Attributes:
  71         zone (PolygonZone): The polygon zone to be annotated
  72         color (Color): The color to draw the polygon lines
  73         thickness (int): The thickness of the polygon lines, default is 2
  74         text_color (Color): The color of the text on the polygon, default is black
  75         text_scale (float): The scale of the text on the polygon, default is 0.5
  76         text_thickness (int): The thickness of the text on the polygon, default is 1
  77         text_padding (int): The padding around the text on the polygon, default is 10
  78         font (int): The font type for the text on the polygon, default is cv2.FONT_HERSHEY_SIMPLEX
  79         center (Tuple[int, int]): The center of the polygon for text placement
  80     """
  81 
  82     def __init__(
  83         self,
  84         zone: PolygonZone,
  85         color: Color,
  86         thickness: int = 2,
  87         text_color: Color = Color.black(),
  88         text_scale: float = 0.5,
  89         text_thickness: int = 1,
  90         text_padding: int = 10,
  91     ):
  92         self.zone = zone
  93         self.color = color
  94         self.thickness = thickness
  95         self.text_color = text_color
  96         self.text_scale = text_scale
  97         self.text_thickness = text_thickness
  98         self.text_padding = text_padding
  99         self.font = cv2.FONT_HERSHEY_SIMPLEX
  100         self.center = get_polygon_center(polygon=zone.polygon)
  101 
  102     def annotate(self, scene: np.ndarray, label: Optional[str] = None) -> np.ndarray:
  103         """
  104         Annotates the polygon zone within a frame with a count of detected objects.
  105 
  106         Parameters:
  107             scene (np.ndarray): The image on which the polygon zone will be annotated
  108             label (Optional[str]): An optional label for the count of detected objects within the polygon zone (default: None)
  109 
  110         Returns:
  111             np.ndarray: The image with the polygon zone and count of detected objects
  112         """
  113         annotated_frame = draw_polygon(
  114             scene=scene,
  115             polygon=self.zone.polygon,
  116             color=self.color,
  117             thickness=self.thickness,
  118         )
  119 
  120         annotated_frame = draw_text(
  121             scene=annotated_frame,
  122             text=str(self.zone.current_count) if label is None else label,
  123             text_anchor=self.center,
  124             background_color=self.color,
  125             text_color=self.text_color,
  126             text_scale=self.text_scale,
  127             text_thickness=self.text_thickness,
  128             text_padding=self.text_padding,
  129             text_font=self.font,
  130         )
  131 
  132         return annotated_frame
  133
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/supervision/detection/tools/polygon_zone.py b/supervision/detection/tools/polygon_zone.py
  --- a/supervision/detection/tools/polygon_zone.py
  +++ b/supervision/detection/tools/polygon_zone.py
  @@ -17,7 +17,7 @@
       A class for defining a polygon-shaped zone within a frame for detecting objects.
   
       Attributes:
  -        polygon (np.ndarray): A numpy array defining the polygon vertices
  +        polygon (np.ndarray): A polygon represented by a numpy array of shape `(N, 2)`, containing the `x`, `y` coordinates of the points.
           frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)
           triggering_position (Position): The position within the bounding box that triggers the zone (default: Position.BOTTOM_CENTER)
           current_count (int): The current count of detected objects within the zone
  @@ -30,7 +30,7 @@
           frame_resolution_wh: Tuple[int, int],
           triggering_position: Position = Position.BOTTOM_CENTER,
       ):
  -        self.polygon = polygon
  +        self.polygon = polygon.astype(int)
           self.frame_resolution_wh = frame_resolution_wh
           self.triggering_position = triggering_position
           self.current_count = 0
  
verification_info: {"golden_diff": "diff --git a/supervision/detection/tools/polygon_zone.py b/supervision/detection/tools/polygon_zone.py\n--- a/supervision/detection/tools/polygon_zone.py\n+++ b/supervision/detection/tools/polygon_zone.py\n@@ -17,7 +17,7 @@\n     A class for defining a polygon-shaped zone within a frame for detecting objects.\n \n     Attributes:\n-        polygon (np.ndarray): A numpy array defining the polygon vertices\n+        polygon (np.ndarray): A polygon represented by a numpy array of shape `(N, 2)`, containing the `x`, `y` coordinates of the points.\n         frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)\n         triggering_position (Position): The position within the bounding box that triggers the zone (default: Position.BOTTOM_CENTER)\n         current_count (int): The current count of detected objects within the zone\n@@ -30,7 +30,7 @@\n         frame_resolution_wh: Tuple[int, int],\n         triggering_position: Position = Position.BOTTOM_CENTER,\n     ):\n-        self.polygon = polygon\n+        self.polygon = polygon.astype(int)\n         self.frame_resolution_wh = frame_resolution_wh\n         self.triggering_position = triggering_position\n         self.current_count = 0\n", "issue": "Better handling of wrong data types of mask for sv.PolygonZone()\n### Search before asking\n\n- [X] I have searched the Supervision [issues](https://github.com/roboflow/supervision/issues) and found no similar feature requests.\n\n\n### Description\n\n<img width=\"898\" alt=\"image\" src=\"https://github.com/roboflow/supervision/assets/47161914/6eebe556-97f1-452b-8757-17062548ca12\">\r\n\r\nOpenCV errors out with an uninformative error when the dtype of the mask is wrong. \r\n\r\nWould be good to add catch if dtype != np.int32 and raise an Exception.\n\n### Use case\n\nI was trying to create a mask in CVAT, the exported segmentation had decimal places, np.array(coords) did not convert to np.int32, and I was confused by the bad error message.\r\n\r\nThis is likely to happen to other users too .\n\n### Additional\n\nHappy to submit PR\n\n### Are you willing to submit a PR?\n\n- [X] Yes I'd like to help by submitting a PR!\n", "before_files": [{"content": "from dataclasses import replace\nfrom typing import Optional, Tuple\n\nimport cv2\nimport numpy as np\n\nfrom supervision import Detections\nfrom supervision.detection.utils import clip_boxes, polygon_to_mask\nfrom supervision.draw.color import Color\nfrom supervision.draw.utils import draw_polygon, draw_text\nfrom supervision.geometry.core import Position\nfrom supervision.geometry.utils import get_polygon_center\n\n\nclass PolygonZone:\n    \"\"\"\n    A class for defining a polygon-shaped zone within a frame for detecting objects.\n\n    Attributes:\n        polygon (np.ndarray): A numpy array defining the polygon vertices\n        frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)\n        triggering_position (Position): The position within the bounding box that triggers the zone (default: Position.BOTTOM_CENTER)\n        current_count (int): The current count of detected objects within the zone\n        mask (np.ndarray): The 2D bool mask for the polygon zone\n    \"\"\"\n\n    def __init__(\n        self,\n        polygon: np.ndarray,\n        frame_resolution_wh: Tuple[int, int],\n        triggering_position: Position = Position.BOTTOM_CENTER,\n    ):\n        self.polygon = polygon\n        self.frame_resolution_wh = frame_resolution_wh\n        self.triggering_position = triggering_position\n        self.current_count = 0\n\n        width, height = frame_resolution_wh\n        self.mask = polygon_to_mask(\n            polygon=polygon, resolution_wh=(width + 1, height + 1)\n        )\n\n    def trigger(self, detections: Detections) -> np.ndarray:\n        \"\"\"\n        Determines if the detections are within the polygon zone.\n\n        Parameters:\n            detections (Detections): The detections to be checked against the polygon zone\n\n        Returns:\n            np.ndarray: A boolean numpy array indicating if each detection is within the polygon zone\n        \"\"\"\n\n        clipped_xyxy = clip_boxes(\n            boxes_xyxy=detections.xyxy, frame_resolution_wh=self.frame_resolution_wh\n        )\n        clipped_detections = replace(detections, xyxy=clipped_xyxy)\n        clipped_anchors = np.ceil(\n            clipped_detections.get_anchor_coordinates(anchor=self.triggering_position)\n        ).astype(int)\n        is_in_zone = self.mask[clipped_anchors[:, 1], clipped_anchors[:, 0]]\n        self.current_count = np.sum(is_in_zone)\n        return is_in_zone.astype(bool)\n\n\nclass PolygonZoneAnnotator:\n    \"\"\"\n    A class for annotating a polygon-shaped zone within a frame with a count of detected objects.\n\n    Attributes:\n        zone (PolygonZone): The polygon zone to be annotated\n        color (Color): The color to draw the polygon lines\n        thickness (int): The thickness of the polygon lines, default is 2\n        text_color (Color): The color of the text on the polygon, default is black\n        text_scale (float): The scale of the text on the polygon, default is 0.5\n        text_thickness (int): The thickness of the text on the polygon, default is 1\n        text_padding (int): The padding around the text on the polygon, default is 10\n        font (int): The font type for the text on the polygon, default is cv2.FONT_HERSHEY_SIMPLEX\n        center (Tuple[int, int]): The center of the polygon for text placement\n    \"\"\"\n\n    def __init__(\n        self,\n        zone: PolygonZone,\n        color: Color,\n        thickness: int = 2,\n        text_color: Color = Color.black(),\n        text_scale: float = 0.5,\n        text_thickness: int = 1,\n        text_padding: int = 10,\n    ):\n        self.zone = zone\n        self.color = color\n        self.thickness = thickness\n        self.text_color = text_color\n        self.text_scale = text_scale\n        self.text_thickness = text_thickness\n        self.text_padding = text_padding\n        self.font = cv2.FONT_HERSHEY_SIMPLEX\n        self.center = get_polygon_center(polygon=zone.polygon)\n\n    def annotate(self, scene: np.ndarray, label: Optional[str] = None) -> np.ndarray:\n        \"\"\"\n        Annotates the polygon zone within a frame with a count of detected objects.\n\n        Parameters:\n            scene (np.ndarray): The image on which the polygon zone will be annotated\n            label (Optional[str]): An optional label for the count of detected objects within the polygon zone (default: None)\n\n        Returns:\n            np.ndarray: The image with the polygon zone and count of detected objects\n        \"\"\"\n        annotated_frame = draw_polygon(\n            scene=scene,\n            polygon=self.zone.polygon,\n            color=self.color,\n            thickness=self.thickness,\n        )\n\n        annotated_frame = draw_text(\n            scene=annotated_frame,\n            text=str(self.zone.current_count) if label is None else label,\n            text_anchor=self.center,\n            background_color=self.color,\n            text_color=self.text_color,\n            text_scale=self.text_scale,\n            text_thickness=self.text_thickness,\n            text_padding=self.text_padding,\n            text_font=self.font,\n        )\n\n        return annotated_frame\n", "path": "supervision/detection/tools/polygon_zone.py"}], "after_files": [{"content": "from dataclasses import replace\nfrom typing import Optional, Tuple\n\nimport cv2\nimport numpy as np\n\nfrom supervision import Detections\nfrom supervision.detection.utils import clip_boxes, polygon_to_mask\nfrom supervision.draw.color import Color\nfrom supervision.draw.utils import draw_polygon, draw_text\nfrom supervision.geometry.core import Position\nfrom supervision.geometry.utils import get_polygon_center\n\n\nclass PolygonZone:\n    \"\"\"\n    A class for defining a polygon-shaped zone within a frame for detecting objects.\n\n    Attributes:\n        polygon (np.ndarray): A polygon represented by a numpy array of shape `(N, 2)`, containing the `x`, `y` coordinates of the points.\n        frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)\n        triggering_position (Position): The position within the bounding box that triggers the zone (default: Position.BOTTOM_CENTER)\n        current_count (int): The current count of detected objects within the zone\n        mask (np.ndarray): The 2D bool mask for the polygon zone\n    \"\"\"\n\n    def __init__(\n        self,\n        polygon: np.ndarray,\n        frame_resolution_wh: Tuple[int, int],\n        triggering_position: Position = Position.BOTTOM_CENTER,\n    ):\n        self.polygon = polygon.astype(int)\n        self.frame_resolution_wh = frame_resolution_wh\n        self.triggering_position = triggering_position\n        self.current_count = 0\n\n        width, height = frame_resolution_wh\n        self.mask = polygon_to_mask(\n            polygon=polygon, resolution_wh=(width + 1, height + 1)\n        )\n\n    def trigger(self, detections: Detections) -> np.ndarray:\n        \"\"\"\n        Determines if the detections are within the polygon zone.\n\n        Parameters:\n            detections (Detections): The detections to be checked against the polygon zone\n\n        Returns:\n            np.ndarray: A boolean numpy array indicating if each detection is within the polygon zone\n        \"\"\"\n\n        clipped_xyxy = clip_boxes(\n            boxes_xyxy=detections.xyxy, frame_resolution_wh=self.frame_resolution_wh\n        )\n        clipped_detections = replace(detections, xyxy=clipped_xyxy)\n        clipped_anchors = np.ceil(\n            clipped_detections.get_anchor_coordinates(anchor=self.triggering_position)\n        ).astype(int)\n        is_in_zone = self.mask[clipped_anchors[:, 1], clipped_anchors[:, 0]]\n        self.current_count = np.sum(is_in_zone)\n        return is_in_zone.astype(bool)\n\n\nclass PolygonZoneAnnotator:\n    \"\"\"\n    A class for annotating a polygon-shaped zone within a frame with a count of detected objects.\n\n    Attributes:\n        zone (PolygonZone): The polygon zone to be annotated\n        color (Color): The color to draw the polygon lines\n        thickness (int): The thickness of the polygon lines, default is 2\n        text_color (Color): The color of the text on the polygon, default is black\n        text_scale (float): The scale of the text on the polygon, default is 0.5\n        text_thickness (int): The thickness of the text on the polygon, default is 1\n        text_padding (int): The padding around the text on the polygon, default is 10\n        font (int): The font type for the text on the polygon, default is cv2.FONT_HERSHEY_SIMPLEX\n        center (Tuple[int, int]): The center of the polygon for text placement\n    \"\"\"\n\n    def __init__(\n        self,\n        zone: PolygonZone,\n        color: Color,\n        thickness: int = 2,\n        text_color: Color = Color.black(),\n        text_scale: float = 0.5,\n        text_thickness: int = 1,\n        text_padding: int = 10,\n    ):\n        self.zone = zone\n        self.color = color\n        self.thickness = thickness\n        self.text_color = text_color\n        self.text_scale = text_scale\n        self.text_thickness = text_thickness\n        self.text_padding = text_padding\n        self.font = cv2.FONT_HERSHEY_SIMPLEX\n        self.center = get_polygon_center(polygon=zone.polygon)\n\n    def annotate(self, scene: np.ndarray, label: Optional[str] = None) -> np.ndarray:\n        \"\"\"\n        Annotates the polygon zone within a frame with a count of detected objects.\n\n        Parameters:\n            scene (np.ndarray): The image on which the polygon zone will be annotated\n            label (Optional[str]): An optional label for the count of detected objects within the polygon zone (default: None)\n\n        Returns:\n            np.ndarray: The image with the polygon zone and count of detected objects\n        \"\"\"\n        annotated_frame = draw_polygon(\n            scene=scene,\n            polygon=self.zone.polygon,\n            color=self.color,\n            thickness=self.thickness,\n        )\n\n        annotated_frame = draw_text(\n            scene=annotated_frame,\n            text=str(self.zone.current_count) if label is None else label,\n            text_anchor=self.center,\n            background_color=self.color,\n            text_color=self.text_color,\n            text_scale=self.text_scale,\n            text_thickness=self.text_thickness,\n            text_padding=self.text_padding,\n            text_font=self.font,\n        )\n\n        return annotated_frame\n", "path": "supervision/detection/tools/polygon_zone.py"}]}