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()

```

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

{"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"}]}