We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Wrong COCO format while exporting a `sv.DetectionDataset` using its `as_coco` method
### The Issue:
I export some annotations using:
 ```python
sv.DetectionDataset(
    classes=CLASSES,
    images=images,
    annotations=annotations
).as_coco(
    annotations_path=ANNOTATIONS_PATH,
    min_image_area_percentage=0,
    max_image_area_percentage=1.,
    approximation_percentage=0
)
```
The resulting `.json` is created successfully. 
Then, loading the annotations using `pycocotools` and plotting annotations of an image:
```python
from pycocotools.coco import COCO
coco=COCO(ANNOTATIONS_PATH)

imgId = 42  # an arbitrary image id
file_name = coco.loadImgs(imgId)[0]["file_name"]

img = plt.imread(file_name)
plt.imshow(img)
plt.axis("off")

annIds = coco.getAnnIds(imgIds=imgId, iscrowd=None)
anns = coco.loadAnns(annIds)
coco.showAnns(anns, draw_bbox=True)
```
which plots wrong annotations for the given `imgId`: the annotations (box & mask) is seen bottom-right and it seems that there is a mismatch between the image and its annotations. 
![image](https://github.com/roboflow/supervision/assets/40141130/2b277d28-7487-49cf-a624-11b31f6e508b)

Actually, for any `imgId`, we have the same issue: the image is shown correctly but the annotations are not. Interestingly, the annotations (`annIds`) are always the same for different `imgId`'s. In my case, there is only 1 box & mask per image and for various values of `imgId`, the `annIds` are always equal to `1`.

### The Cause:
The `annIds` are not unique among all the annotations (the "id" in "annotations" in COCO format). 
I presume they have to be unique among all annotation id's ([see the following issue](https://github.com/cocodataset/cocoapi/issues/95#issuecomment-448038572)). 

However, the current implementation resets the ***annotation id*** to 1 for each image:
https://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L202


### The (possible) Fix:
Simply changing `label_id` to `annotation_id` in the following line will assign a unique id for each annotation:
https://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L218

I would be glad to open a PR.

Wrong COCO format while exporting a `sv.DetectionDataset` using its `as_coco` method
### The Issue:
I export some annotations using:
 ```python
sv.DetectionDataset(
    classes=CLASSES,
    images=images,
    annotations=annotations
).as_coco(
    annotations_path=ANNOTATIONS_PATH,
    min_image_area_percentage=0,
    max_image_area_percentage=1.,
    approximation_percentage=0
)
```
The resulting `.json` is created successfully. 
Then, loading the annotations using `pycocotools` and plotting annotations of an image:
```python
from pycocotools.coco import COCO
coco=COCO(ANNOTATIONS_PATH)

imgId = 42  # an arbitrary image id
file_name = coco.loadImgs(imgId)[0]["file_name"]

img = plt.imread(file_name)
plt.imshow(img)
plt.axis("off")

annIds = coco.getAnnIds(imgIds=imgId, iscrowd=None)
anns = coco.loadAnns(annIds)
coco.showAnns(anns, draw_bbox=True)
```
which plots wrong annotations for the given `imgId`: the annotations (box & mask) is seen bottom-right and it seems that there is a mismatch between the image and its annotations. 
![image](https://github.com/roboflow/supervision/assets/40141130/2b277d28-7487-49cf-a624-11b31f6e508b)

Actually, for any `imgId`, we have the same issue: the image is shown correctly but the annotations are not. Interestingly, the annotations (`annIds`) are always the same for different `imgId`'s. In my case, there is only 1 box & mask per image and for various values of `imgId`, the `annIds` are always equal to `1`.

### The Cause:
The `annIds` are not unique among all the annotations (the "id" in "annotations" in COCO format). 
I presume they have to be unique among all annotation id's ([see the following issue](https://github.com/cocodataset/cocoapi/issues/95#issuecomment-448038572)). 

However, the current implementation resets the ***annotation id*** to 1 for each image:
https://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L202


### The (possible) Fix:
Simply changing `label_id` to `annotation_id` in the following line will assign a unique id for each annotation:
https://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L218

I would be glad to open 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/dataset/formats/coco.py`
Content:
```
1 import os
2 from datetime import datetime
3 from pathlib import Path
4 from typing import Dict, List, Tuple
5 
6 import cv2
7 import numpy as np
8 
9 from supervision.dataset.utils import (
10     approximate_mask_with_polygons,
11     map_detections_class_id,
12 )
13 from supervision.detection.core import Detections
14 from supervision.detection.utils import polygon_to_mask
15 from supervision.utils.file import read_json_file, save_json_file
16 
17 
18 def coco_categories_to_classes(coco_categories: List[dict]) -> List[str]:
19     return [
20         category["name"]
21         for category in sorted(coco_categories, key=lambda category: category["id"])
22     ]
23 
24 
25 def build_coco_class_index_mapping(
26     coco_categories: List[dict], target_classes: List[str]
27 ) -> Dict[int, int]:
28     source_class_to_index = {
29         category["name"]: category["id"] for category in coco_categories
30     }
31     return {
32         source_class_to_index[target_class_name]: target_class_index
33         for target_class_index, target_class_name in enumerate(target_classes)
34     }
35 
36 
37 def classes_to_coco_categories(classes: List[str]) -> List[dict]:
38     return [
39         {
40             "id": class_id,
41             "name": class_name,
42             "supercategory": "common-objects",
43         }
44         for class_id, class_name in enumerate(classes)
45     ]
46 
47 
48 def group_coco_annotations_by_image_id(
49     coco_annotations: List[dict],
50 ) -> Dict[int, List[dict]]:
51     annotations = {}
52     for annotation in coco_annotations:
53         image_id = annotation["image_id"]
54         if image_id not in annotations:
55             annotations[image_id] = []
56         annotations[image_id].append(annotation)
57     return annotations
58 
59 
60 def _polygons_to_masks(
61     polygons: List[np.ndarray], resolution_wh: Tuple[int, int]
62 ) -> np.ndarray:
63     return np.array(
64         [
65             polygon_to_mask(polygon=polygon, resolution_wh=resolution_wh)
66             for polygon in polygons
67         ],
68         dtype=bool,
69     )
70 
71 
72 def coco_annotations_to_detections(
73     image_annotations: List[dict], resolution_wh: Tuple[int, int], with_masks: bool
74 ) -> Detections:
75     if not image_annotations:
76         return Detections.empty()
77 
78     class_ids = [
79         image_annotation["category_id"] for image_annotation in image_annotations
80     ]
81     xyxy = [image_annotation["bbox"] for image_annotation in image_annotations]
82     xyxy = np.asarray(xyxy)
83     xyxy[:, 2:4] += xyxy[:, 0:2]
84 
85     if with_masks:
86         polygons = [
87             np.reshape(
88                 np.asarray(image_annotation["segmentation"], dtype=np.int32), (-1, 2)
89             )
90             for image_annotation in image_annotations
91         ]
92         mask = _polygons_to_masks(polygons=polygons, resolution_wh=resolution_wh)
93         return Detections(
94             class_id=np.asarray(class_ids, dtype=int), xyxy=xyxy, mask=mask
95         )
96 
97     return Detections(xyxy=xyxy, class_id=np.asarray(class_ids, dtype=int))
98 
99 
100 def detections_to_coco_annotations(
101     detections: Detections,
102     image_id: int,
103     annotation_id: int,
104     min_image_area_percentage: float = 0.0,
105     max_image_area_percentage: float = 1.0,
106     approximation_percentage: float = 0.75,
107 ) -> Tuple[List[Dict], int]:
108     coco_annotations = []
109     for xyxy, mask, _, class_id, _ in detections:
110         box_width, box_height = xyxy[2] - xyxy[0], xyxy[3] - xyxy[1]
111         polygon = []
112         if mask is not None:
113             polygon = list(
114                 approximate_mask_with_polygons(
115                     mask=mask,
116                     min_image_area_percentage=min_image_area_percentage,
117                     max_image_area_percentage=max_image_area_percentage,
118                     approximation_percentage=approximation_percentage,
119                 )[0].flatten()
120             )
121         coco_annotation = {
122             "id": annotation_id,
123             "image_id": image_id,
124             "category_id": int(class_id),
125             "bbox": [xyxy[0], xyxy[1], box_width, box_height],
126             "area": box_width * box_height,
127             "segmentation": [polygon] if polygon else [],
128             "iscrowd": 0,
129         }
130         coco_annotations.append(coco_annotation)
131         annotation_id += 1
132     return coco_annotations, annotation_id
133 
134 
135 def load_coco_annotations(
136     images_directory_path: str,
137     annotations_path: str,
138     force_masks: bool = False,
139 ) -> Tuple[List[str], Dict[str, np.ndarray], Dict[str, Detections]]:
140     coco_data = read_json_file(file_path=annotations_path)
141     classes = coco_categories_to_classes(coco_categories=coco_data["categories"])
142     class_index_mapping = build_coco_class_index_mapping(
143         coco_categories=coco_data["categories"], target_classes=classes
144     )
145     coco_images = coco_data["images"]
146     coco_annotations_groups = group_coco_annotations_by_image_id(
147         coco_annotations=coco_data["annotations"]
148     )
149 
150     images = {}
151     annotations = {}
152 
153     for coco_image in coco_images:
154         image_name, image_width, image_height = (
155             coco_image["file_name"],
156             coco_image["width"],
157             coco_image["height"],
158         )
159         image_annotations = coco_annotations_groups.get(coco_image["id"], [])
160         image_path = os.path.join(images_directory_path, image_name)
161 
162         image = cv2.imread(str(image_path))
163         annotation = coco_annotations_to_detections(
164             image_annotations=image_annotations,
165             resolution_wh=(image_width, image_height),
166             with_masks=force_masks,
167         )
168         annotation = map_detections_class_id(
169             source_to_target_mapping=class_index_mapping,
170             detections=annotation,
171         )
172 
173         images[image_name] = image
174         annotations[image_name] = annotation
175 
176     return classes, images, annotations
177 
178 
179 def save_coco_annotations(
180     annotation_path: str,
181     images: Dict[str, np.ndarray],
182     annotations: Dict[str, Detections],
183     classes: List[str],
184     min_image_area_percentage: float = 0.0,
185     max_image_area_percentage: float = 1.0,
186     approximation_percentage: float = 0.75,
187 ) -> None:
188     Path(annotation_path).parent.mkdir(parents=True, exist_ok=True)
189     info = {}
190     licenses = [
191         {
192             "id": 1,
193             "url": "https://creativecommons.org/licenses/by/4.0/",
194             "name": "CC BY 4.0",
195         }
196     ]
197 
198     coco_annotations = []
199     coco_images = []
200     coco_categories = classes_to_coco_categories(classes=classes)
201 
202     image_id, annotation_id = 1, 1
203     for image_name, image in images.items():
204         image_height, image_width, _ = image.shape
205 
206         coco_image = {
207             "id": image_id,
208             "license": 1,
209             "file_name": image_name,
210             "height": image_height,
211             "width": image_width,
212             "date_captured": datetime.now().strftime("%m/%d/%Y,%H:%M:%S"),
213         }
214 
215         coco_images.append(coco_image)
216         detections = annotations[image_name]
217 
218         coco_annotation, label_id = detections_to_coco_annotations(
219             detections=detections,
220             image_id=image_id,
221             annotation_id=annotation_id,
222             min_image_area_percentage=min_image_area_percentage,
223             max_image_area_percentage=max_image_area_percentage,
224             approximation_percentage=approximation_percentage,
225         )
226 
227         coco_annotations.extend(coco_annotation)
228         image_id += 1
229 
230     annotation_dict = {
231         "info": info,
232         "licenses": licenses,
233         "categories": coco_categories,
234         "images": coco_images,
235         "annotations": coco_annotations,
236     }
237     save_json_file(annotation_dict, file_path=annotation_path)
238
```
--- 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/dataset/formats/coco.py b/supervision/dataset/formats/coco.py
--- a/supervision/dataset/formats/coco.py
+++ b/supervision/dataset/formats/coco.py
@@ -215,7 +215,7 @@
         coco_images.append(coco_image)
         detections = annotations[image_name]
 
-        coco_annotation, label_id = detections_to_coco_annotations(
+        coco_annotation, annotation_id = detections_to_coco_annotations(
             detections=detections,
             image_id=image_id,
             annotation_id=annotation_id,

{"golden_diff": "diff --git a/supervision/dataset/formats/coco.py b/supervision/dataset/formats/coco.py\n--- a/supervision/dataset/formats/coco.py\n+++ b/supervision/dataset/formats/coco.py\n@@ -215,7 +215,7 @@\n         coco_images.append(coco_image)\n         detections = annotations[image_name]\n \n-        coco_annotation, label_id = detections_to_coco_annotations(\n+        coco_annotation, annotation_id = detections_to_coco_annotations(\n             detections=detections,\n             image_id=image_id,\n             annotation_id=annotation_id,\n", "issue": "Wrong COCO format while exporting a `sv.DetectionDataset` using its `as_coco` method\n### The Issue:\r\nI export some annotations using:\r\n ```python\r\nsv.DetectionDataset(\r\n    classes=CLASSES,\r\n    images=images,\r\n    annotations=annotations\r\n).as_coco(\r\n    annotations_path=ANNOTATIONS_PATH,\r\n    min_image_area_percentage=0,\r\n    max_image_area_percentage=1.,\r\n    approximation_percentage=0\r\n)\r\n```\r\nThe resulting `.json` is created successfully. \r\nThen, loading the annotations using `pycocotools` and plotting annotations of an image:\r\n```python\r\nfrom pycocotools.coco import COCO\r\ncoco=COCO(ANNOTATIONS_PATH)\r\n\r\nimgId = 42  # an arbitrary image id\r\nfile_name = coco.loadImgs(imgId)[0][\"file_name\"]\r\n\r\nimg = plt.imread(file_name)\r\nplt.imshow(img)\r\nplt.axis(\"off\")\r\n\r\nannIds = coco.getAnnIds(imgIds=imgId, iscrowd=None)\r\nanns = coco.loadAnns(annIds)\r\ncoco.showAnns(anns, draw_bbox=True)\r\n```\r\nwhich plots wrong annotations for the given `imgId`: the annotations (box & mask) is seen bottom-right and it seems that there is a mismatch between the image and its annotations. \r\n![image](https://github.com/roboflow/supervision/assets/40141130/2b277d28-7487-49cf-a624-11b31f6e508b)\r\n\r\nActually, for any `imgId`, we have the same issue: the image is shown correctly but the annotations are not. Interestingly, the annotations (`annIds`) are always the same for different `imgId`'s. In my case, there is only 1 box & mask per image and for various values of `imgId`, the `annIds` are always equal to `1`.\r\n\r\n### The Cause:\r\nThe `annIds` are not unique among all the annotations (the \"id\" in \"annotations\" in COCO format). \r\nI presume they have to be unique among all annotation id's ([see the following issue](https://github.com/cocodataset/cocoapi/issues/95#issuecomment-448038572)). \r\n\r\nHowever, the current implementation resets the ***annotation id*** to 1 for each image:\r\nhttps://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L202\r\n\r\n\r\n### The (possible) Fix:\r\nSimply changing `label_id` to `annotation_id` in the following line will assign a unique id for each annotation:\r\nhttps://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L218\r\n\r\nI would be glad to open a PR.\r\n\nWrong COCO format while exporting a `sv.DetectionDataset` using its `as_coco` method\n### The Issue:\r\nI export some annotations using:\r\n ```python\r\nsv.DetectionDataset(\r\n    classes=CLASSES,\r\n    images=images,\r\n    annotations=annotations\r\n).as_coco(\r\n    annotations_path=ANNOTATIONS_PATH,\r\n    min_image_area_percentage=0,\r\n    max_image_area_percentage=1.,\r\n    approximation_percentage=0\r\n)\r\n```\r\nThe resulting `.json` is created successfully. \r\nThen, loading the annotations using `pycocotools` and plotting annotations of an image:\r\n```python\r\nfrom pycocotools.coco import COCO\r\ncoco=COCO(ANNOTATIONS_PATH)\r\n\r\nimgId = 42  # an arbitrary image id\r\nfile_name = coco.loadImgs(imgId)[0][\"file_name\"]\r\n\r\nimg = plt.imread(file_name)\r\nplt.imshow(img)\r\nplt.axis(\"off\")\r\n\r\nannIds = coco.getAnnIds(imgIds=imgId, iscrowd=None)\r\nanns = coco.loadAnns(annIds)\r\ncoco.showAnns(anns, draw_bbox=True)\r\n```\r\nwhich plots wrong annotations for the given `imgId`: the annotations (box & mask) is seen bottom-right and it seems that there is a mismatch between the image and its annotations. \r\n![image](https://github.com/roboflow/supervision/assets/40141130/2b277d28-7487-49cf-a624-11b31f6e508b)\r\n\r\nActually, for any `imgId`, we have the same issue: the image is shown correctly but the annotations are not. Interestingly, the annotations (`annIds`) are always the same for different `imgId`'s. In my case, there is only 1 box & mask per image and for various values of `imgId`, the `annIds` are always equal to `1`.\r\n\r\n### The Cause:\r\nThe `annIds` are not unique among all the annotations (the \"id\" in \"annotations\" in COCO format). \r\nI presume they have to be unique among all annotation id's ([see the following issue](https://github.com/cocodataset/cocoapi/issues/95#issuecomment-448038572)). \r\n\r\nHowever, the current implementation resets the ***annotation id*** to 1 for each image:\r\nhttps://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L202\r\n\r\n\r\n### The (possible) Fix:\r\nSimply changing `label_id` to `annotation_id` in the following line will assign a unique id for each annotation:\r\nhttps://github.com/roboflow/supervision/blob/4f79d29934ebfbb59d4cb789b70e8e451f545332/supervision/dataset/formats/coco.py#L218\r\n\r\nI would be glad to open a PR.\r\n\n", "before_files": [{"content": "import os\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, List, Tuple\n\nimport cv2\nimport numpy as np\n\nfrom supervision.dataset.utils import (\n    approximate_mask_with_polygons,\n    map_detections_class_id,\n)\nfrom supervision.detection.core import Detections\nfrom supervision.detection.utils import polygon_to_mask\nfrom supervision.utils.file import read_json_file, save_json_file\n\n\ndef coco_categories_to_classes(coco_categories: List[dict]) -> List[str]:\n    return [\n        category[\"name\"]\n        for category in sorted(coco_categories, key=lambda category: category[\"id\"])\n    ]\n\n\ndef build_coco_class_index_mapping(\n    coco_categories: List[dict], target_classes: List[str]\n) -> Dict[int, int]:\n    source_class_to_index = {\n        category[\"name\"]: category[\"id\"] for category in coco_categories\n    }\n    return {\n        source_class_to_index[target_class_name]: target_class_index\n        for target_class_index, target_class_name in enumerate(target_classes)\n    }\n\n\ndef classes_to_coco_categories(classes: List[str]) -> List[dict]:\n    return [\n        {\n            \"id\": class_id,\n            \"name\": class_name,\n            \"supercategory\": \"common-objects\",\n        }\n        for class_id, class_name in enumerate(classes)\n    ]\n\n\ndef group_coco_annotations_by_image_id(\n    coco_annotations: List[dict],\n) -> Dict[int, List[dict]]:\n    annotations = {}\n    for annotation in coco_annotations:\n        image_id = annotation[\"image_id\"]\n        if image_id not in annotations:\n            annotations[image_id] = []\n        annotations[image_id].append(annotation)\n    return annotations\n\n\ndef _polygons_to_masks(\n    polygons: List[np.ndarray], resolution_wh: Tuple[int, int]\n) -> np.ndarray:\n    return np.array(\n        [\n            polygon_to_mask(polygon=polygon, resolution_wh=resolution_wh)\n            for polygon in polygons\n        ],\n        dtype=bool,\n    )\n\n\ndef coco_annotations_to_detections(\n    image_annotations: List[dict], resolution_wh: Tuple[int, int], with_masks: bool\n) -> Detections:\n    if not image_annotations:\n        return Detections.empty()\n\n    class_ids = [\n        image_annotation[\"category_id\"] for image_annotation in image_annotations\n    ]\n    xyxy = [image_annotation[\"bbox\"] for image_annotation in image_annotations]\n    xyxy = np.asarray(xyxy)\n    xyxy[:, 2:4] += xyxy[:, 0:2]\n\n    if with_masks:\n        polygons = [\n            np.reshape(\n                np.asarray(image_annotation[\"segmentation\"], dtype=np.int32), (-1, 2)\n            )\n            for image_annotation in image_annotations\n        ]\n        mask = _polygons_to_masks(polygons=polygons, resolution_wh=resolution_wh)\n        return Detections(\n            class_id=np.asarray(class_ids, dtype=int), xyxy=xyxy, mask=mask\n        )\n\n    return Detections(xyxy=xyxy, class_id=np.asarray(class_ids, dtype=int))\n\n\ndef detections_to_coco_annotations(\n    detections: Detections,\n    image_id: int,\n    annotation_id: int,\n    min_image_area_percentage: float = 0.0,\n    max_image_area_percentage: float = 1.0,\n    approximation_percentage: float = 0.75,\n) -> Tuple[List[Dict], int]:\n    coco_annotations = []\n    for xyxy, mask, _, class_id, _ in detections:\n        box_width, box_height = xyxy[2] - xyxy[0], xyxy[3] - xyxy[1]\n        polygon = []\n        if mask is not None:\n            polygon = list(\n                approximate_mask_with_polygons(\n                    mask=mask,\n                    min_image_area_percentage=min_image_area_percentage,\n                    max_image_area_percentage=max_image_area_percentage,\n                    approximation_percentage=approximation_percentage,\n                )[0].flatten()\n            )\n        coco_annotation = {\n            \"id\": annotation_id,\n            \"image_id\": image_id,\n            \"category_id\": int(class_id),\n            \"bbox\": [xyxy[0], xyxy[1], box_width, box_height],\n            \"area\": box_width * box_height,\n            \"segmentation\": [polygon] if polygon else [],\n            \"iscrowd\": 0,\n        }\n        coco_annotations.append(coco_annotation)\n        annotation_id += 1\n    return coco_annotations, annotation_id\n\n\ndef load_coco_annotations(\n    images_directory_path: str,\n    annotations_path: str,\n    force_masks: bool = False,\n) -> Tuple[List[str], Dict[str, np.ndarray], Dict[str, Detections]]:\n    coco_data = read_json_file(file_path=annotations_path)\n    classes = coco_categories_to_classes(coco_categories=coco_data[\"categories\"])\n    class_index_mapping = build_coco_class_index_mapping(\n        coco_categories=coco_data[\"categories\"], target_classes=classes\n    )\n    coco_images = coco_data[\"images\"]\n    coco_annotations_groups = group_coco_annotations_by_image_id(\n        coco_annotations=coco_data[\"annotations\"]\n    )\n\n    images = {}\n    annotations = {}\n\n    for coco_image in coco_images:\n        image_name, image_width, image_height = (\n            coco_image[\"file_name\"],\n            coco_image[\"width\"],\n            coco_image[\"height\"],\n        )\n        image_annotations = coco_annotations_groups.get(coco_image[\"id\"], [])\n        image_path = os.path.join(images_directory_path, image_name)\n\n        image = cv2.imread(str(image_path))\n        annotation = coco_annotations_to_detections(\n            image_annotations=image_annotations,\n            resolution_wh=(image_width, image_height),\n            with_masks=force_masks,\n        )\n        annotation = map_detections_class_id(\n            source_to_target_mapping=class_index_mapping,\n            detections=annotation,\n        )\n\n        images[image_name] = image\n        annotations[image_name] = annotation\n\n    return classes, images, annotations\n\n\ndef save_coco_annotations(\n    annotation_path: str,\n    images: Dict[str, np.ndarray],\n    annotations: Dict[str, Detections],\n    classes: List[str],\n    min_image_area_percentage: float = 0.0,\n    max_image_area_percentage: float = 1.0,\n    approximation_percentage: float = 0.75,\n) -> None:\n    Path(annotation_path).parent.mkdir(parents=True, exist_ok=True)\n    info = {}\n    licenses = [\n        {\n            \"id\": 1,\n            \"url\": \"https://creativecommons.org/licenses/by/4.0/\",\n            \"name\": \"CC BY 4.0\",\n        }\n    ]\n\n    coco_annotations = []\n    coco_images = []\n    coco_categories = classes_to_coco_categories(classes=classes)\n\n    image_id, annotation_id = 1, 1\n    for image_name, image in images.items():\n        image_height, image_width, _ = image.shape\n\n        coco_image = {\n            \"id\": image_id,\n            \"license\": 1,\n            \"file_name\": image_name,\n            \"height\": image_height,\n            \"width\": image_width,\n            \"date_captured\": datetime.now().strftime(\"%m/%d/%Y,%H:%M:%S\"),\n        }\n\n        coco_images.append(coco_image)\n        detections = annotations[image_name]\n\n        coco_annotation, label_id = detections_to_coco_annotations(\n            detections=detections,\n            image_id=image_id,\n            annotation_id=annotation_id,\n            min_image_area_percentage=min_image_area_percentage,\n            max_image_area_percentage=max_image_area_percentage,\n            approximation_percentage=approximation_percentage,\n        )\n\n        coco_annotations.extend(coco_annotation)\n        image_id += 1\n\n    annotation_dict = {\n        \"info\": info,\n        \"licenses\": licenses,\n        \"categories\": coco_categories,\n        \"images\": coco_images,\n        \"annotations\": coco_annotations,\n    }\n    save_json_file(annotation_dict, file_path=annotation_path)\n", "path": "supervision/dataset/formats/coco.py"}], "after_files": [{"content": "import os\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, List, Tuple\n\nimport cv2\nimport numpy as np\n\nfrom supervision.dataset.utils import (\n    approximate_mask_with_polygons,\n    map_detections_class_id,\n)\nfrom supervision.detection.core import Detections\nfrom supervision.detection.utils import polygon_to_mask\nfrom supervision.utils.file import read_json_file, save_json_file\n\n\ndef coco_categories_to_classes(coco_categories: List[dict]) -> List[str]:\n    return [\n        category[\"name\"]\n        for category in sorted(coco_categories, key=lambda category: category[\"id\"])\n    ]\n\n\ndef build_coco_class_index_mapping(\n    coco_categories: List[dict], target_classes: List[str]\n) -> Dict[int, int]:\n    source_class_to_index = {\n        category[\"name\"]: category[\"id\"] for category in coco_categories\n    }\n    return {\n        source_class_to_index[target_class_name]: target_class_index\n        for target_class_index, target_class_name in enumerate(target_classes)\n    }\n\n\ndef classes_to_coco_categories(classes: List[str]) -> List[dict]:\n    return [\n        {\n            \"id\": class_id,\n            \"name\": class_name,\n            \"supercategory\": \"common-objects\",\n        }\n        for class_id, class_name in enumerate(classes)\n    ]\n\n\ndef group_coco_annotations_by_image_id(\n    coco_annotations: List[dict],\n) -> Dict[int, List[dict]]:\n    annotations = {}\n    for annotation in coco_annotations:\n        image_id = annotation[\"image_id\"]\n        if image_id not in annotations:\n            annotations[image_id] = []\n        annotations[image_id].append(annotation)\n    return annotations\n\n\ndef _polygons_to_masks(\n    polygons: List[np.ndarray], resolution_wh: Tuple[int, int]\n) -> np.ndarray:\n    return np.array(\n        [\n            polygon_to_mask(polygon=polygon, resolution_wh=resolution_wh)\n            for polygon in polygons\n        ],\n        dtype=bool,\n    )\n\n\ndef coco_annotations_to_detections(\n    image_annotations: List[dict], resolution_wh: Tuple[int, int], with_masks: bool\n) -> Detections:\n    if not image_annotations:\n        return Detections.empty()\n\n    class_ids = [\n        image_annotation[\"category_id\"] for image_annotation in image_annotations\n    ]\n    xyxy = [image_annotation[\"bbox\"] for image_annotation in image_annotations]\n    xyxy = np.asarray(xyxy)\n    xyxy[:, 2:4] += xyxy[:, 0:2]\n\n    if with_masks:\n        polygons = [\n            np.reshape(\n                np.asarray(image_annotation[\"segmentation\"], dtype=np.int32), (-1, 2)\n            )\n            for image_annotation in image_annotations\n        ]\n        mask = _polygons_to_masks(polygons=polygons, resolution_wh=resolution_wh)\n        return Detections(\n            class_id=np.asarray(class_ids, dtype=int), xyxy=xyxy, mask=mask\n        )\n\n    return Detections(xyxy=xyxy, class_id=np.asarray(class_ids, dtype=int))\n\n\ndef detections_to_coco_annotations(\n    detections: Detections,\n    image_id: int,\n    annotation_id: int,\n    min_image_area_percentage: float = 0.0,\n    max_image_area_percentage: float = 1.0,\n    approximation_percentage: float = 0.75,\n) -> Tuple[List[Dict], int]:\n    coco_annotations = []\n    for xyxy, mask, _, class_id, _ in detections:\n        box_width, box_height = xyxy[2] - xyxy[0], xyxy[3] - xyxy[1]\n        polygon = []\n        if mask is not None:\n            polygon = list(\n                approximate_mask_with_polygons(\n                    mask=mask,\n                    min_image_area_percentage=min_image_area_percentage,\n                    max_image_area_percentage=max_image_area_percentage,\n                    approximation_percentage=approximation_percentage,\n                )[0].flatten()\n            )\n        coco_annotation = {\n            \"id\": annotation_id,\n            \"image_id\": image_id,\n            \"category_id\": int(class_id),\n            \"bbox\": [xyxy[0], xyxy[1], box_width, box_height],\n            \"area\": box_width * box_height,\n            \"segmentation\": [polygon] if polygon else [],\n            \"iscrowd\": 0,\n        }\n        coco_annotations.append(coco_annotation)\n        annotation_id += 1\n    return coco_annotations, annotation_id\n\n\ndef load_coco_annotations(\n    images_directory_path: str,\n    annotations_path: str,\n    force_masks: bool = False,\n) -> Tuple[List[str], Dict[str, np.ndarray], Dict[str, Detections]]:\n    coco_data = read_json_file(file_path=annotations_path)\n    classes = coco_categories_to_classes(coco_categories=coco_data[\"categories\"])\n    class_index_mapping = build_coco_class_index_mapping(\n        coco_categories=coco_data[\"categories\"], target_classes=classes\n    )\n    coco_images = coco_data[\"images\"]\n    coco_annotations_groups = group_coco_annotations_by_image_id(\n        coco_annotations=coco_data[\"annotations\"]\n    )\n\n    images = {}\n    annotations = {}\n\n    for coco_image in coco_images:\n        image_name, image_width, image_height = (\n            coco_image[\"file_name\"],\n            coco_image[\"width\"],\n            coco_image[\"height\"],\n        )\n        image_annotations = coco_annotations_groups.get(coco_image[\"id\"], [])\n        image_path = os.path.join(images_directory_path, image_name)\n\n        image = cv2.imread(str(image_path))\n        annotation = coco_annotations_to_detections(\n            image_annotations=image_annotations,\n            resolution_wh=(image_width, image_height),\n            with_masks=force_masks,\n        )\n        annotation = map_detections_class_id(\n            source_to_target_mapping=class_index_mapping,\n            detections=annotation,\n        )\n\n        images[image_name] = image\n        annotations[image_name] = annotation\n\n    return classes, images, annotations\n\n\ndef save_coco_annotations(\n    annotation_path: str,\n    images: Dict[str, np.ndarray],\n    annotations: Dict[str, Detections],\n    classes: List[str],\n    min_image_area_percentage: float = 0.0,\n    max_image_area_percentage: float = 1.0,\n    approximation_percentage: float = 0.75,\n) -> None:\n    Path(annotation_path).parent.mkdir(parents=True, exist_ok=True)\n    info = {}\n    licenses = [\n        {\n            \"id\": 1,\n            \"url\": \"https://creativecommons.org/licenses/by/4.0/\",\n            \"name\": \"CC BY 4.0\",\n        }\n    ]\n\n    coco_annotations = []\n    coco_images = []\n    coco_categories = classes_to_coco_categories(classes=classes)\n\n    image_id, annotation_id = 1, 1\n    for image_name, image in images.items():\n        image_height, image_width, _ = image.shape\n\n        coco_image = {\n            \"id\": image_id,\n            \"license\": 1,\n            \"file_name\": image_name,\n            \"height\": image_height,\n            \"width\": image_width,\n            \"date_captured\": datetime.now().strftime(\"%m/%d/%Y,%H:%M:%S\"),\n        }\n\n        coco_images.append(coco_image)\n        detections = annotations[image_name]\n\n        coco_annotation, annotation_id = detections_to_coco_annotations(\n            detections=detections,\n            image_id=image_id,\n            annotation_id=annotation_id,\n            min_image_area_percentage=min_image_area_percentage,\n            max_image_area_percentage=max_image_area_percentage,\n            approximation_percentage=approximation_percentage,\n        )\n\n        coco_annotations.extend(coco_annotation)\n        image_id += 1\n\n    annotation_dict = {\n        \"info\": info,\n        \"licenses\": licenses,\n        \"categories\": coco_categories,\n        \"images\": coco_images,\n        \"annotations\": coco_annotations,\n    }\n    save_json_file(annotation_dict, file_path=annotation_path)\n", "path": "supervision/dataset/formats/coco.py"}]}