Skip to content

Commit cda84de

Browse files
committed
Fixed issue # 13
1 parent 7968299 commit cda84de

File tree

2 files changed

+58
-27
lines changed

2 files changed

+58
-27
lines changed

label_convert/coco_to_labelImg.py

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pathlib import Path
88
from typing import Any, Dict, List, Tuple, Union
99

10+
import cv2
1011
import numpy as np
1112
from tqdm import tqdm
1213

@@ -65,21 +66,32 @@ def convert(self, info_list: List[Path]) -> None:
6566
id_img_dict = {v["id"]: v for v in data.get("images")}
6667
all_annotaions = data.get("annotations")
6768
for one_anno in tqdm(all_annotaions):
68-
image_info = id_img_dict.get(one_anno["image_id"])
69-
img_name = image_info.get("file_name")
70-
img_height = image_info.get("height")
71-
img_width = image_info.get("width")
72-
73-
seg_info = one_anno.get("segmentation")
74-
if seg_info:
75-
bbox = self.get_bbox(seg_info)
69+
img_info = id_img_dict.get(one_anno["image_id"])
70+
img_name = img_info.get("file_name")
71+
img_height = img_info.get("height")
72+
img_width = img_info.get("width")
73+
category_id = int(one_anno.get("category_id")) - 1
74+
75+
bbox_info = one_anno.get("bbox", None)
76+
seg_info = one_anno.get("segmentation", None)
77+
78+
if bbox_info:
79+
x0, y0, w, h = bbox_info
80+
xyxy_bbox = [x0, y0, x0 + w, y0 + h]
81+
xywh = self.xyxy_to_xywh(xyxy_bbox, img_width, img_height)
82+
elif seg_info:
83+
points = np.array(seg_info).reshape(4, 2)
84+
bbox = self.get_bbox_from_poly(img_height, img_width, points)
7685
xywh = self.xyxy_to_xywh(bbox, img_width, img_height)
77-
category_id = int(one_anno.get("category_id")) - 1
78-
xywh_str = " ".join([str(v) for v in xywh])
79-
label_str = f"{category_id} {xywh_str}"
86+
else:
87+
print("The bbox and segmentation are all None, skip current anno.")
88+
continue
8089

81-
txt_full_path = save_dir / f"{Path(img_name).stem}.txt"
82-
self.write_txt(txt_full_path, label_str, mode="a")
90+
xywh_str = " ".join([str(v) for v in xywh])
91+
label_str = f"{category_id} {xywh_str}"
92+
93+
txt_full_path = save_dir / f"{Path(img_name).stem}.txt"
94+
self.write_txt(txt_full_path, label_str, mode="a")
8395

8496
img_full_path = img_dir / img_name
8597
shutil.copy2(img_full_path, save_dir)
@@ -94,18 +106,42 @@ def gen_classes_txt(self, save_dir: Path, categories_dict: List[Dict[str, str]])
94106
class_info = [value["name"] for value in categories_dict]
95107
self.write_txt(save_dir / "classes.txt", class_info)
96108

97-
def get_bbox(self, seg_info: List[List[float]]) -> List[float]:
98-
seg_info = np.array(seg_info[0]).reshape(4, 2)
99-
x0, y0 = np.min(seg_info, axis=0)
100-
x1, y1 = np.max(seg_info, axis=0)
101-
bbox = [x0, y0, x1, y1]
109+
def get_bbox_from_poly(
110+
self, img_h: int, img_w: int, points: np.ndarray
111+
) -> List[float]:
112+
mask = np.zeros((img_h, img_w), dtype="uint8")
113+
img_mask = cv2.fillPoly(mask, np.int32([points]), 255)
114+
contours, _ = cv2.findContours(img_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
115+
contour = contours[0]
116+
bbox = self.get_mini_boxes(contour)
102117
return bbox
103118

104119
@staticmethod
105-
def write_txt(save_path: str, content: List[str], mode="w") -> None:
106-
if not isinstance(save_path, str):
107-
save_path = str(save_path)
120+
def get_mini_boxes(contour) -> List[int]:
121+
bounding_box = cv2.minAreaRect(contour)
122+
points = sorted(list(cv2.boxPoints(bounding_box)), key=lambda x: x[0])
123+
124+
index_1, index_2, index_3, index_4 = 0, 1, 2, 3
125+
if points[1][1] > points[0][1]:
126+
index_1 = 0
127+
index_4 = 1
128+
else:
129+
index_1 = 1
130+
index_4 = 0
131+
if points[3][1] > points[2][1]:
132+
index_2 = 2
133+
index_3 = 3
134+
else:
135+
index_2 = 3
136+
index_3 = 2
137+
138+
box = [points[index_1], points[index_2], points[index_3], points[index_4]]
139+
box = np.round(box).astype(np.int32).tolist()
140+
left_top, right_bottom = box[0], box[2]
141+
return left_top + right_bottom
108142

143+
@staticmethod
144+
def write_txt(save_path: str, content: List[str], mode="w") -> None:
109145
if isinstance(content, str):
110146
content = [content]
111147

tests/test_files/COCO_dataset/annotations/instances_train2017.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,7 @@
4646
"area": 7482.011104003072,
4747
"iscrowd": 0,
4848
"image_id": 1,
49-
"bbox": [
50-
18.000080000000004,
51-
2.999920000000003,
52-
87.000032,
53-
86.000096
54-
],
49+
"bbox": null,
5550
"category_id": 1,
5651
"id": 1
5752
},

0 commit comments

Comments
 (0)