We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
How to train mmOCR models on total text formatted dataset?
total text is a popular scene text format dataset,you will find more info about the dataset and it's format here : https://github.com/cs-chan/Total-Text-Dataset
however in this repo for detection task you used something like coco text formatting dataset,however i want to test some of your models on total text dataset for both detection,recognition task,on the other hand we have prepared synthetic dataset which follows total text formatting,we want to use that dataset to train some of mmOCR models to solve our data problem,can we do that? our dataset is not coco text formatted and we have created it synthetically by following total text format data.i need answer to these questions : 
1. can we directly use total text format data for mmOCR detection , recognition and  keyinformation extraction task?
2.if there is no way to use total text format data directly then can you tell me how to convert total text data format in coco text format using python code?

thank you in advance <3

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/data/textdet/totaltext_converter.py`
Content:
```
1 import argparse
2 import glob
3 import os.path as osp
4 from functools import partial
5 
6 import cv2
7 import mmcv
8 import numpy as np
9 import scipy.io as scio
10 from shapely.geometry import Polygon
11 
12 from mmocr.utils import convert_annotations, drop_orientation, is_not_png
13 
14 
15 def collect_files(img_dir, gt_dir, split):
16     """Collect all images and their corresponding groundtruth files.
17 
18     Args:
19         img_dir(str): The image directory
20         gt_dir(str): The groundtruth directory
21         split(str): The split of dataset. Namely: training or test
22 
23     Returns:
24         files(list): The list of tuples (img_file, groundtruth_file)
25     """
26     assert isinstance(img_dir, str)
27     assert img_dir
28     assert isinstance(gt_dir, str)
29     assert gt_dir
30 
31     # note that we handle png and jpg only. Pls convert others such as gif to
32     # jpg or png offline
33     suffixes = ['.png', '.PNG', '.jpg', '.JPG', '.jpeg', '.JPEG']
34     # suffixes = ['.png']
35 
36     imgs_list = []
37     for suffix in suffixes:
38         imgs_list.extend(glob.glob(osp.join(img_dir, '*' + suffix)))
39 
40     imgs_list = [
41         drop_orientation(f) if is_not_png(f) else f for f in imgs_list
42     ]
43 
44     files = []
45     if split == 'training':
46         for img_file in imgs_list:
47             gt_file = gt_dir + '/gt_' + osp.splitext(
48                 osp.basename(img_file))[0] + '.mat'
49             # gt_file = gt_dir + '/' + osp.splitext(
50             #    osp.basename(img_file))[0] + '.png'
51             files.append((img_file, gt_file))
52         assert len(files), f'No images found in {img_dir}'
53         print(f'Loaded {len(files)} images from {img_dir}')
54     elif split == 'test':
55         for img_file in imgs_list:
56             gt_file = gt_dir + '/poly_gt_' + osp.splitext(
57                 osp.basename(img_file))[0] + '.mat'
58             files.append((img_file, gt_file))
59         assert len(files), f'No images found in {img_dir}'
60         print(f'Loaded {len(files)} images from {img_dir}')
61 
62     return files
63 
64 
65 def collect_annotations(files, split, nproc=1):
66     """Collect the annotation information.
67 
68     Args:
69         files(list): The list of tuples (image_file, groundtruth_file)
70         split(str): The split of dataset. Namely: training or test
71         nproc(int): The number of process to collect annotations
72 
73     Returns:
74         images(list): The list of image information dicts
75     """
76     assert isinstance(files, list)
77     assert isinstance(split, str)
78     assert isinstance(nproc, int)
79 
80     load_img_info_with_split = partial(load_img_info, split=split)
81     if nproc > 1:
82         images = mmcv.track_parallel_progress(
83             load_img_info_with_split, files, nproc=nproc)
84     else:
85         images = mmcv.track_progress(load_img_info_with_split, files)
86 
87     return images
88 
89 
90 def get_contours(gt_path, split):
91     """Get the contours and words for each ground_truth file.
92 
93     Args:
94         gt_path(str): The relative path of the ground_truth mat file
95         split(str): The split of dataset: training or test
96 
97     Returns:
98         contours(list[lists]): A list of lists of contours
99         for the text instances
100         words(list[list]): A list of lists of words (string)
101         for the text instances
102     """
103     assert isinstance(gt_path, str)
104     assert isinstance(split, str)
105 
106     contours = []
107     words = []
108     data = scio.loadmat(gt_path)
109     if split == 'training':
110         data_polygt = data['gt']
111     elif split == 'test':
112         data_polygt = data['polygt']
113 
114     for i, lines in enumerate(data_polygt):
115         X = np.array(lines[1])
116         Y = np.array(lines[3])
117 
118         point_num = len(X[0])
119         word = lines[4]
120         if len(word) == 0:
121             word = '???'
122         else:
123             word = word[0]
124 
125         if word == '#':
126             word = '###'
127             continue
128 
129         words.append(word)
130 
131         arr = np.concatenate([X, Y]).T
132         contour = []
133         for i in range(point_num):
134             contour.append(arr[i][0])
135             contour.append(arr[i][1])
136         contours.append(np.asarray(contour))
137 
138     return contours, words
139 
140 
141 def load_mat_info(img_info, gt_file, split):
142     """Load the information of one ground truth in .mat format.
143 
144     Args:
145         img_info(dict): The dict of only the image information
146         gt_file(str): The relative path of the ground_truth mat
147         file for one image
148         split(str): The split of dataset: training or test
149 
150     Returns:
151         img_info(dict): The dict of the img and annotation information
152     """
153     assert isinstance(img_info, dict)
154     assert isinstance(gt_file, str)
155     assert isinstance(split, str)
156 
157     contours, words = get_contours(gt_file, split)
158     anno_info = []
159     for contour in contours:
160         if contour.shape[0] == 2:
161             continue
162         category_id = 1
163         coordinates = np.array(contour).reshape(-1, 2)
164         polygon = Polygon(coordinates)
165         iscrowd = 0
166 
167         area = polygon.area
168         # convert to COCO style XYWH format
169         min_x, min_y, max_x, max_y = polygon.bounds
170         bbox = [min_x, min_y, max_x - min_x, max_y - min_y]
171 
172         anno = dict(
173             iscrowd=iscrowd,
174             category_id=category_id,
175             bbox=bbox,
176             area=area,
177             segmentation=[contour])
178         anno_info.append(anno)
179 
180     img_info.update(anno_info=anno_info)
181 
182     return img_info
183 
184 
185 def load_png_info(gt_file, img_info):
186     """Load the information of one ground truth in .png format.
187 
188     Args:
189         gt_file(str): The relative path of the ground_truth file for one image
190         img_info(dict): The dict of only the image information
191 
192     Returns:
193         img_info(dict): The dict of the img and annotation information
194     """
195     assert isinstance(gt_file, str)
196     assert isinstance(img_info, dict)
197     gt_img = cv2.imread(gt_file, 0)
198     contours, _ = cv2.findContours(gt_img, cv2.RETR_EXTERNAL,
199                                    cv2.CHAIN_APPROX_SIMPLE)
200 
201     anno_info = []
202     for contour in contours:
203         if contour.shape[0] == 2:
204             continue
205         category_id = 1
206         xy = np.array(contour).flatten().tolist()
207 
208         coordinates = np.array(contour).reshape(-1, 2)
209         polygon = Polygon(coordinates)
210         iscrowd = 0
211 
212         area = polygon.area
213         # convert to COCO style XYWH format
214         min_x, min_y, max_x, max_y = polygon.bounds
215         bbox = [min_x, min_y, max_x - min_x, max_y - min_y]
216 
217         anno = dict(
218             iscrowd=iscrowd,
219             category_id=category_id,
220             bbox=bbox,
221             area=area,
222             segmentation=[xy])
223         anno_info.append(anno)
224 
225     img_info.update(anno_info=anno_info)
226 
227     return img_info
228 
229 
230 def load_img_info(files, split):
231     """Load the information of one image.
232 
233     Args:
234         files(tuple): The tuple of (img_file, groundtruth_file)
235         split(str): The split of dataset: training or test
236 
237     Returns:
238         img_info(dict): The dict of the img and annotation information
239     """
240     assert isinstance(files, tuple)
241     assert isinstance(split, str)
242 
243     img_file, gt_file = files
244     # read imgs with ignoring orientations
245     img = mmcv.imread(img_file, 'unchanged')
246     # read imgs with orientations as dataloader does when training and testing
247     img_color = mmcv.imread(img_file, 'color')
248     # make sure imgs have no orientation info, or annotation gt is wrong.
249     assert img.shape[0:2] == img_color.shape[0:2]
250 
251     split_name = osp.basename(osp.dirname(img_file))
252     img_info = dict(
253         # remove img_prefix for filename
254         file_name=osp.join(split_name, osp.basename(img_file)),
255         height=img.shape[0],
256         width=img.shape[1],
257         # anno_info=anno_info,
258         segm_file=osp.join(split_name, osp.basename(gt_file)))
259 
260     if split == 'training':
261         img_info = load_mat_info(img_info, gt_file, split)
262     elif split == 'test':
263         img_info = load_mat_info(img_info, gt_file, split)
264     else:
265         raise NotImplementedError
266 
267     return img_info
268 
269 
270 def parse_args():
271     parser = argparse.ArgumentParser(
272         description='Convert totaltext annotations to COCO format')
273     parser.add_argument('root_path', help='totaltext root path')
274     parser.add_argument('-o', '--out-dir', help='output path')
275     parser.add_argument(
276         '--split-list',
277         nargs='+',
278         help='a list of splits. e.g., "--split_list training test"')
279 
280     parser.add_argument(
281         '--nproc', default=1, type=int, help='number of process')
282     args = parser.parse_args()
283     return args
284 
285 
286 def main():
287     args = parse_args()
288     root_path = args.root_path
289     out_dir = args.out_dir if args.out_dir else root_path
290     mmcv.mkdir_or_exist(out_dir)
291 
292     img_dir = osp.join(root_path, 'imgs')
293     gt_dir = osp.join(root_path, 'annotations')
294 
295     set_name = {}
296     for split in args.split_list:
297         set_name.update({split: 'instances_' + split + '.json'})
298         assert osp.exists(osp.join(img_dir, split))
299 
300     for split, json_name in set_name.items():
301         print(f'Converting {split} into {json_name}')
302         with mmcv.Timer(
303                 print_tmpl='It takes {}s to convert totaltext annotation'):
304             files = collect_files(
305                 osp.join(img_dir, split), osp.join(gt_dir, split), split)
306             image_infos = collect_annotations(files, split, nproc=args.nproc)
307             convert_annotations(image_infos, osp.join(out_dir, json_name))
308 
309 
310 if __name__ == '__main__':
311     main()
312
```
--- 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/tools/data/textdet/totaltext_converter.py b/tools/data/textdet/totaltext_converter.py
--- a/tools/data/textdet/totaltext_converter.py
+++ b/tools/data/textdet/totaltext_converter.py
@@ -44,17 +44,17 @@
     files = []
     if split == 'training':
         for img_file in imgs_list:
-            gt_file = gt_dir + '/gt_' + osp.splitext(
-                osp.basename(img_file))[0] + '.mat'
-            # gt_file = gt_dir + '/' + osp.splitext(
-            #    osp.basename(img_file))[0] + '.png'
+            gt_file = osp.join(
+                gt_dir,
+                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')
             files.append((img_file, gt_file))
         assert len(files), f'No images found in {img_dir}'
         print(f'Loaded {len(files)} images from {img_dir}')
     elif split == 'test':
         for img_file in imgs_list:
-            gt_file = gt_dir + '/poly_gt_' + osp.splitext(
-                osp.basename(img_file))[0] + '.mat'
+            gt_file = osp.join(
+                gt_dir,
+                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')
             files.append((img_file, gt_file))
         assert len(files), f'No images found in {img_dir}'
         print(f'Loaded {len(files)} images from {img_dir}')
@@ -107,7 +107,7 @@
     words = []
     data = scio.loadmat(gt_path)
     if split == 'training':
-        data_polygt = data['gt']
+        data_polygt = data['polygt']
     elif split == 'test':
         data_polygt = data['polygt']

{"golden_diff": "diff --git a/tools/data/textdet/totaltext_converter.py b/tools/data/textdet/totaltext_converter.py\n--- a/tools/data/textdet/totaltext_converter.py\n+++ b/tools/data/textdet/totaltext_converter.py\n@@ -44,17 +44,17 @@\n     files = []\n     if split == 'training':\n         for img_file in imgs_list:\n-            gt_file = gt_dir + '/gt_' + osp.splitext(\n-                osp.basename(img_file))[0] + '.mat'\n-            # gt_file = gt_dir + '/' + osp.splitext(\n-            #    osp.basename(img_file))[0] + '.png'\n+            gt_file = osp.join(\n+                gt_dir,\n+                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')\n             files.append((img_file, gt_file))\n         assert len(files), f'No images found in {img_dir}'\n         print(f'Loaded {len(files)} images from {img_dir}')\n     elif split == 'test':\n         for img_file in imgs_list:\n-            gt_file = gt_dir + '/poly_gt_' + osp.splitext(\n-                osp.basename(img_file))[0] + '.mat'\n+            gt_file = osp.join(\n+                gt_dir,\n+                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')\n             files.append((img_file, gt_file))\n         assert len(files), f'No images found in {img_dir}'\n         print(f'Loaded {len(files)} images from {img_dir}')\n@@ -107,7 +107,7 @@\n     words = []\n     data = scio.loadmat(gt_path)\n     if split == 'training':\n-        data_polygt = data['gt']\n+        data_polygt = data['polygt']\n     elif split == 'test':\n         data_polygt = data['polygt']\n", "issue": "How to train mmOCR models on total text formatted dataset?\ntotal text is a popular scene text format dataset,you will find more info about the dataset and it's format here : https://github.com/cs-chan/Total-Text-Dataset\r\nhowever in this repo for detection task you used something like coco text formatting dataset,however i want to test some of your models on total text dataset for both detection,recognition task,on the other hand we have prepared synthetic dataset which follows total text formatting,we want to use that dataset to train some of mmOCR models to solve our data problem,can we do that? our dataset is not coco text formatted and we have created it synthetically by following total text format data.i need answer to these questions : \r\n1. can we directly use total text format data for mmOCR detection , recognition and  keyinformation extraction task?\r\n2.if there is no way to use total text format data directly then can you tell me how to convert total text data format in coco text format using python code?\r\n\r\nthank you in advance <3\n", "before_files": [{"content": "import argparse\nimport glob\nimport os.path as osp\nfrom functools import partial\n\nimport cv2\nimport mmcv\nimport numpy as np\nimport scipy.io as scio\nfrom shapely.geometry import Polygon\n\nfrom mmocr.utils import convert_annotations, drop_orientation, is_not_png\n\n\ndef collect_files(img_dir, gt_dir, split):\n    \"\"\"Collect all images and their corresponding groundtruth files.\n\n    Args:\n        img_dir(str): The image directory\n        gt_dir(str): The groundtruth directory\n        split(str): The split of dataset. Namely: training or test\n\n    Returns:\n        files(list): The list of tuples (img_file, groundtruth_file)\n    \"\"\"\n    assert isinstance(img_dir, str)\n    assert img_dir\n    assert isinstance(gt_dir, str)\n    assert gt_dir\n\n    # note that we handle png and jpg only. Pls convert others such as gif to\n    # jpg or png offline\n    suffixes = ['.png', '.PNG', '.jpg', '.JPG', '.jpeg', '.JPEG']\n    # suffixes = ['.png']\n\n    imgs_list = []\n    for suffix in suffixes:\n        imgs_list.extend(glob.glob(osp.join(img_dir, '*' + suffix)))\n\n    imgs_list = [\n        drop_orientation(f) if is_not_png(f) else f for f in imgs_list\n    ]\n\n    files = []\n    if split == 'training':\n        for img_file in imgs_list:\n            gt_file = gt_dir + '/gt_' + osp.splitext(\n                osp.basename(img_file))[0] + '.mat'\n            # gt_file = gt_dir + '/' + osp.splitext(\n            #    osp.basename(img_file))[0] + '.png'\n            files.append((img_file, gt_file))\n        assert len(files), f'No images found in {img_dir}'\n        print(f'Loaded {len(files)} images from {img_dir}')\n    elif split == 'test':\n        for img_file in imgs_list:\n            gt_file = gt_dir + '/poly_gt_' + osp.splitext(\n                osp.basename(img_file))[0] + '.mat'\n            files.append((img_file, gt_file))\n        assert len(files), f'No images found in {img_dir}'\n        print(f'Loaded {len(files)} images from {img_dir}')\n\n    return files\n\n\ndef collect_annotations(files, split, nproc=1):\n    \"\"\"Collect the annotation information.\n\n    Args:\n        files(list): The list of tuples (image_file, groundtruth_file)\n        split(str): The split of dataset. Namely: training or test\n        nproc(int): The number of process to collect annotations\n\n    Returns:\n        images(list): The list of image information dicts\n    \"\"\"\n    assert isinstance(files, list)\n    assert isinstance(split, str)\n    assert isinstance(nproc, int)\n\n    load_img_info_with_split = partial(load_img_info, split=split)\n    if nproc > 1:\n        images = mmcv.track_parallel_progress(\n            load_img_info_with_split, files, nproc=nproc)\n    else:\n        images = mmcv.track_progress(load_img_info_with_split, files)\n\n    return images\n\n\ndef get_contours(gt_path, split):\n    \"\"\"Get the contours and words for each ground_truth file.\n\n    Args:\n        gt_path(str): The relative path of the ground_truth mat file\n        split(str): The split of dataset: training or test\n\n    Returns:\n        contours(list[lists]): A list of lists of contours\n        for the text instances\n        words(list[list]): A list of lists of words (string)\n        for the text instances\n    \"\"\"\n    assert isinstance(gt_path, str)\n    assert isinstance(split, str)\n\n    contours = []\n    words = []\n    data = scio.loadmat(gt_path)\n    if split == 'training':\n        data_polygt = data['gt']\n    elif split == 'test':\n        data_polygt = data['polygt']\n\n    for i, lines in enumerate(data_polygt):\n        X = np.array(lines[1])\n        Y = np.array(lines[3])\n\n        point_num = len(X[0])\n        word = lines[4]\n        if len(word) == 0:\n            word = '???'\n        else:\n            word = word[0]\n\n        if word == '#':\n            word = '###'\n            continue\n\n        words.append(word)\n\n        arr = np.concatenate([X, Y]).T\n        contour = []\n        for i in range(point_num):\n            contour.append(arr[i][0])\n            contour.append(arr[i][1])\n        contours.append(np.asarray(contour))\n\n    return contours, words\n\n\ndef load_mat_info(img_info, gt_file, split):\n    \"\"\"Load the information of one ground truth in .mat format.\n\n    Args:\n        img_info(dict): The dict of only the image information\n        gt_file(str): The relative path of the ground_truth mat\n        file for one image\n        split(str): The split of dataset: training or test\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(img_info, dict)\n    assert isinstance(gt_file, str)\n    assert isinstance(split, str)\n\n    contours, words = get_contours(gt_file, split)\n    anno_info = []\n    for contour in contours:\n        if contour.shape[0] == 2:\n            continue\n        category_id = 1\n        coordinates = np.array(contour).reshape(-1, 2)\n        polygon = Polygon(coordinates)\n        iscrowd = 0\n\n        area = polygon.area\n        # convert to COCO style XYWH format\n        min_x, min_y, max_x, max_y = polygon.bounds\n        bbox = [min_x, min_y, max_x - min_x, max_y - min_y]\n\n        anno = dict(\n            iscrowd=iscrowd,\n            category_id=category_id,\n            bbox=bbox,\n            area=area,\n            segmentation=[contour])\n        anno_info.append(anno)\n\n    img_info.update(anno_info=anno_info)\n\n    return img_info\n\n\ndef load_png_info(gt_file, img_info):\n    \"\"\"Load the information of one ground truth in .png format.\n\n    Args:\n        gt_file(str): The relative path of the ground_truth file for one image\n        img_info(dict): The dict of only the image information\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(gt_file, str)\n    assert isinstance(img_info, dict)\n    gt_img = cv2.imread(gt_file, 0)\n    contours, _ = cv2.findContours(gt_img, cv2.RETR_EXTERNAL,\n                                   cv2.CHAIN_APPROX_SIMPLE)\n\n    anno_info = []\n    for contour in contours:\n        if contour.shape[0] == 2:\n            continue\n        category_id = 1\n        xy = np.array(contour).flatten().tolist()\n\n        coordinates = np.array(contour).reshape(-1, 2)\n        polygon = Polygon(coordinates)\n        iscrowd = 0\n\n        area = polygon.area\n        # convert to COCO style XYWH format\n        min_x, min_y, max_x, max_y = polygon.bounds\n        bbox = [min_x, min_y, max_x - min_x, max_y - min_y]\n\n        anno = dict(\n            iscrowd=iscrowd,\n            category_id=category_id,\n            bbox=bbox,\n            area=area,\n            segmentation=[xy])\n        anno_info.append(anno)\n\n    img_info.update(anno_info=anno_info)\n\n    return img_info\n\n\ndef load_img_info(files, split):\n    \"\"\"Load the information of one image.\n\n    Args:\n        files(tuple): The tuple of (img_file, groundtruth_file)\n        split(str): The split of dataset: training or test\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(files, tuple)\n    assert isinstance(split, str)\n\n    img_file, gt_file = files\n    # read imgs with ignoring orientations\n    img = mmcv.imread(img_file, 'unchanged')\n    # read imgs with orientations as dataloader does when training and testing\n    img_color = mmcv.imread(img_file, 'color')\n    # make sure imgs have no orientation info, or annotation gt is wrong.\n    assert img.shape[0:2] == img_color.shape[0:2]\n\n    split_name = osp.basename(osp.dirname(img_file))\n    img_info = dict(\n        # remove img_prefix for filename\n        file_name=osp.join(split_name, osp.basename(img_file)),\n        height=img.shape[0],\n        width=img.shape[1],\n        # anno_info=anno_info,\n        segm_file=osp.join(split_name, osp.basename(gt_file)))\n\n    if split == 'training':\n        img_info = load_mat_info(img_info, gt_file, split)\n    elif split == 'test':\n        img_info = load_mat_info(img_info, gt_file, split)\n    else:\n        raise NotImplementedError\n\n    return img_info\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description='Convert totaltext annotations to COCO format')\n    parser.add_argument('root_path', help='totaltext root path')\n    parser.add_argument('-o', '--out-dir', help='output path')\n    parser.add_argument(\n        '--split-list',\n        nargs='+',\n        help='a list of splits. e.g., \"--split_list training test\"')\n\n    parser.add_argument(\n        '--nproc', default=1, type=int, help='number of process')\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n    root_path = args.root_path\n    out_dir = args.out_dir if args.out_dir else root_path\n    mmcv.mkdir_or_exist(out_dir)\n\n    img_dir = osp.join(root_path, 'imgs')\n    gt_dir = osp.join(root_path, 'annotations')\n\n    set_name = {}\n    for split in args.split_list:\n        set_name.update({split: 'instances_' + split + '.json'})\n        assert osp.exists(osp.join(img_dir, split))\n\n    for split, json_name in set_name.items():\n        print(f'Converting {split} into {json_name}')\n        with mmcv.Timer(\n                print_tmpl='It takes {}s to convert totaltext annotation'):\n            files = collect_files(\n                osp.join(img_dir, split), osp.join(gt_dir, split), split)\n            image_infos = collect_annotations(files, split, nproc=args.nproc)\n            convert_annotations(image_infos, osp.join(out_dir, json_name))\n\n\nif __name__ == '__main__':\n    main()\n", "path": "tools/data/textdet/totaltext_converter.py"}], "after_files": [{"content": "import argparse\nimport glob\nimport os.path as osp\nfrom functools import partial\n\nimport cv2\nimport mmcv\nimport numpy as np\nimport scipy.io as scio\nfrom shapely.geometry import Polygon\n\nfrom mmocr.utils import convert_annotations, drop_orientation, is_not_png\n\n\ndef collect_files(img_dir, gt_dir, split):\n    \"\"\"Collect all images and their corresponding groundtruth files.\n\n    Args:\n        img_dir(str): The image directory\n        gt_dir(str): The groundtruth directory\n        split(str): The split of dataset. Namely: training or test\n\n    Returns:\n        files(list): The list of tuples (img_file, groundtruth_file)\n    \"\"\"\n    assert isinstance(img_dir, str)\n    assert img_dir\n    assert isinstance(gt_dir, str)\n    assert gt_dir\n\n    # note that we handle png and jpg only. Pls convert others such as gif to\n    # jpg or png offline\n    suffixes = ['.png', '.PNG', '.jpg', '.JPG', '.jpeg', '.JPEG']\n    # suffixes = ['.png']\n\n    imgs_list = []\n    for suffix in suffixes:\n        imgs_list.extend(glob.glob(osp.join(img_dir, '*' + suffix)))\n\n    imgs_list = [\n        drop_orientation(f) if is_not_png(f) else f for f in imgs_list\n    ]\n\n    files = []\n    if split == 'training':\n        for img_file in imgs_list:\n            gt_file = osp.join(\n                gt_dir,\n                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')\n            files.append((img_file, gt_file))\n        assert len(files), f'No images found in {img_dir}'\n        print(f'Loaded {len(files)} images from {img_dir}')\n    elif split == 'test':\n        for img_file in imgs_list:\n            gt_file = osp.join(\n                gt_dir,\n                'poly_gt_' + osp.splitext(osp.basename(img_file))[0] + '.mat')\n            files.append((img_file, gt_file))\n        assert len(files), f'No images found in {img_dir}'\n        print(f'Loaded {len(files)} images from {img_dir}')\n\n    return files\n\n\ndef collect_annotations(files, split, nproc=1):\n    \"\"\"Collect the annotation information.\n\n    Args:\n        files(list): The list of tuples (image_file, groundtruth_file)\n        split(str): The split of dataset. Namely: training or test\n        nproc(int): The number of process to collect annotations\n\n    Returns:\n        images(list): The list of image information dicts\n    \"\"\"\n    assert isinstance(files, list)\n    assert isinstance(split, str)\n    assert isinstance(nproc, int)\n\n    load_img_info_with_split = partial(load_img_info, split=split)\n    if nproc > 1:\n        images = mmcv.track_parallel_progress(\n            load_img_info_with_split, files, nproc=nproc)\n    else:\n        images = mmcv.track_progress(load_img_info_with_split, files)\n\n    return images\n\n\ndef get_contours(gt_path, split):\n    \"\"\"Get the contours and words for each ground_truth file.\n\n    Args:\n        gt_path(str): The relative path of the ground_truth mat file\n        split(str): The split of dataset: training or test\n\n    Returns:\n        contours(list[lists]): A list of lists of contours\n        for the text instances\n        words(list[list]): A list of lists of words (string)\n        for the text instances\n    \"\"\"\n    assert isinstance(gt_path, str)\n    assert isinstance(split, str)\n\n    contours = []\n    words = []\n    data = scio.loadmat(gt_path)\n    if split == 'training':\n        data_polygt = data['polygt']\n    elif split == 'test':\n        data_polygt = data['polygt']\n\n    for i, lines in enumerate(data_polygt):\n        X = np.array(lines[1])\n        Y = np.array(lines[3])\n\n        point_num = len(X[0])\n        word = lines[4]\n        if len(word) == 0:\n            word = '???'\n        else:\n            word = word[0]\n\n        if word == '#':\n            word = '###'\n            continue\n\n        words.append(word)\n\n        arr = np.concatenate([X, Y]).T\n        contour = []\n        for i in range(point_num):\n            contour.append(arr[i][0])\n            contour.append(arr[i][1])\n        contours.append(np.asarray(contour))\n\n    return contours, words\n\n\ndef load_mat_info(img_info, gt_file, split):\n    \"\"\"Load the information of one ground truth in .mat format.\n\n    Args:\n        img_info(dict): The dict of only the image information\n        gt_file(str): The relative path of the ground_truth mat\n        file for one image\n        split(str): The split of dataset: training or test\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(img_info, dict)\n    assert isinstance(gt_file, str)\n    assert isinstance(split, str)\n\n    contours, words = get_contours(gt_file, split)\n    anno_info = []\n    for contour in contours:\n        if contour.shape[0] == 2:\n            continue\n        category_id = 1\n        coordinates = np.array(contour).reshape(-1, 2)\n        polygon = Polygon(coordinates)\n        iscrowd = 0\n\n        area = polygon.area\n        # convert to COCO style XYWH format\n        min_x, min_y, max_x, max_y = polygon.bounds\n        bbox = [min_x, min_y, max_x - min_x, max_y - min_y]\n\n        anno = dict(\n            iscrowd=iscrowd,\n            category_id=category_id,\n            bbox=bbox,\n            area=area,\n            segmentation=[contour])\n        anno_info.append(anno)\n\n    img_info.update(anno_info=anno_info)\n\n    return img_info\n\n\ndef load_png_info(gt_file, img_info):\n    \"\"\"Load the information of one ground truth in .png format.\n\n    Args:\n        gt_file(str): The relative path of the ground_truth file for one image\n        img_info(dict): The dict of only the image information\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(gt_file, str)\n    assert isinstance(img_info, dict)\n    gt_img = cv2.imread(gt_file, 0)\n    contours, _ = cv2.findContours(gt_img, cv2.RETR_EXTERNAL,\n                                   cv2.CHAIN_APPROX_SIMPLE)\n\n    anno_info = []\n    for contour in contours:\n        if contour.shape[0] == 2:\n            continue\n        category_id = 1\n        xy = np.array(contour).flatten().tolist()\n\n        coordinates = np.array(contour).reshape(-1, 2)\n        polygon = Polygon(coordinates)\n        iscrowd = 0\n\n        area = polygon.area\n        # convert to COCO style XYWH format\n        min_x, min_y, max_x, max_y = polygon.bounds\n        bbox = [min_x, min_y, max_x - min_x, max_y - min_y]\n\n        anno = dict(\n            iscrowd=iscrowd,\n            category_id=category_id,\n            bbox=bbox,\n            area=area,\n            segmentation=[xy])\n        anno_info.append(anno)\n\n    img_info.update(anno_info=anno_info)\n\n    return img_info\n\n\ndef load_img_info(files, split):\n    \"\"\"Load the information of one image.\n\n    Args:\n        files(tuple): The tuple of (img_file, groundtruth_file)\n        split(str): The split of dataset: training or test\n\n    Returns:\n        img_info(dict): The dict of the img and annotation information\n    \"\"\"\n    assert isinstance(files, tuple)\n    assert isinstance(split, str)\n\n    img_file, gt_file = files\n    # read imgs with ignoring orientations\n    img = mmcv.imread(img_file, 'unchanged')\n    # read imgs with orientations as dataloader does when training and testing\n    img_color = mmcv.imread(img_file, 'color')\n    # make sure imgs have no orientation info, or annotation gt is wrong.\n    assert img.shape[0:2] == img_color.shape[0:2]\n\n    split_name = osp.basename(osp.dirname(img_file))\n    img_info = dict(\n        # remove img_prefix for filename\n        file_name=osp.join(split_name, osp.basename(img_file)),\n        height=img.shape[0],\n        width=img.shape[1],\n        # anno_info=anno_info,\n        segm_file=osp.join(split_name, osp.basename(gt_file)))\n\n    if split == 'training':\n        img_info = load_mat_info(img_info, gt_file, split)\n    elif split == 'test':\n        img_info = load_mat_info(img_info, gt_file, split)\n    else:\n        raise NotImplementedError\n\n    return img_info\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description='Convert totaltext annotations to COCO format')\n    parser.add_argument('root_path', help='totaltext root path')\n    parser.add_argument('-o', '--out-dir', help='output path')\n    parser.add_argument(\n        '--split-list',\n        nargs='+',\n        help='a list of splits. e.g., \"--split_list training test\"')\n\n    parser.add_argument(\n        '--nproc', default=1, type=int, help='number of process')\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n    root_path = args.root_path\n    out_dir = args.out_dir if args.out_dir else root_path\n    mmcv.mkdir_or_exist(out_dir)\n\n    img_dir = osp.join(root_path, 'imgs')\n    gt_dir = osp.join(root_path, 'annotations')\n\n    set_name = {}\n    for split in args.split_list:\n        set_name.update({split: 'instances_' + split + '.json'})\n        assert osp.exists(osp.join(img_dir, split))\n\n    for split, json_name in set_name.items():\n        print(f'Converting {split} into {json_name}')\n        with mmcv.Timer(\n                print_tmpl='It takes {}s to convert totaltext annotation'):\n            files = collect_files(\n                osp.join(img_dir, split), osp.join(gt_dir, split), split)\n            image_infos = collect_annotations(files, split, nproc=args.nproc)\n            convert_annotations(image_infos, osp.join(out_dir, json_name))\n\n\nif __name__ == '__main__':\n    main()\n", "path": "tools/data/textdet/totaltext_converter.py"}]}