We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cannot import captions with double quotes ICDAR Word Recognition
The original ICDAR 13/15 dataset for word recognition task contains captions with double quotes (e.g "READER\\"").
When I try to load this dataset, Datumaro throws an exception with the message:
`Line word_136.png, "(412\")": unexpected number of quotes in filename`.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `datumaro/plugins/icdar_format/extractor.py`
Content:
```
1 # Copyright (C) 2020 Intel Corporation
2 #
3 # SPDX-License-Identifier: MIT
4 
5 from glob import iglob
6 import os.path as osp
7 
8 import numpy as np
9 
10 from datumaro.components.extractor import (
11     Bbox, Caption, DatasetItem, Importer, Mask, MaskCategories, Polygon,
12     SourceExtractor,
13 )
14 from datumaro.util.image import find_images
15 from datumaro.util.mask_tools import lazy_mask
16 
17 from .format import IcdarPath, IcdarTask
18 
19 
20 class _IcdarExtractor(SourceExtractor):
21     def __init__(self, path, task, subset=None):
22         self._path = path
23         self._task = task
24 
25         if task is IcdarTask.word_recognition:
26             if not osp.isfile(path):
27                 raise FileNotFoundError(
28                     "Can't read annotation file '%s'" % path)
29 
30             if not subset:
31                 subset = osp.basename(osp.dirname(path))
32             super().__init__(subset=subset)
33 
34             self._dataset_dir = osp.dirname(osp.dirname(path))
35 
36             self._items = list(self._load_recognition_items().values())
37         elif task in {IcdarTask.text_localization, IcdarTask.text_segmentation}:
38             if not osp.isdir(path):
39                 raise NotADirectoryError(
40                     "Can't open folder with annotation files '%s'" % path)
41 
42             if not subset:
43                 subset = osp.basename(path)
44             super().__init__(subset=subset)
45 
46             self._dataset_dir = osp.dirname(path)
47 
48             if task is IcdarTask.text_localization:
49                 self._items = list(self._load_localization_items().values())
50             else:
51                 self._items = list(self._load_segmentation_items().values())
52 
53     def _load_recognition_items(self):
54         items = {}
55 
56         with open(self._path, encoding='utf-8') as f:
57             for line in f:
58                 line = line.strip()
59                 objects = line.split(', ')
60                 if len(objects) == 2:
61                     image = objects[0]
62                     objects = objects[1].split('\"')
63                     if 1 < len(objects):
64                         if len(objects) % 2:
65                             captions = [objects[2 * i + 1]
66                                 for i in range(int(len(objects) / 2))]
67                         else:
68                             raise Exception("Line %s: unexpected number "
69                                 "of quotes in filename" % line)
70                     else:
71                         captions = objects[0].split()
72                 else:
73                     image = objects[0][:-1]
74                     captions = []
75 
76                 item_id = osp.splitext(image)[0]
77                 image_path = osp.join(osp.dirname(self._path),
78                     IcdarPath.IMAGES_DIR, image)
79                 if item_id not in items:
80                     items[item_id] = DatasetItem(item_id, subset=self._subset,
81                         image=image_path)
82 
83                 annotations = items[item_id].annotations
84                 for caption in captions:
85                     annotations.append(Caption(caption))
86 
87         return items
88 
89     def _load_localization_items(self):
90         items = {}
91 
92         image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)
93         if osp.isdir(image_dir):
94             images = { osp.splitext(osp.relpath(p, image_dir))[0]: p
95                 for p in find_images(image_dir, recursive=True) }
96         else:
97             images = {}
98 
99         for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):
100             item_id = osp.splitext(osp.relpath(path, self._path))[0]
101             if osp.basename(item_id).startswith('gt_'):
102                 item_id = osp.join(osp.dirname(item_id), osp.basename(item_id)[3:])
103             item_id = item_id.replace('\\', '/')
104 
105             if item_id not in items:
106                 items[item_id] = DatasetItem(item_id, subset=self._subset,
107                     image=images.get(item_id))
108             annotations = items[item_id].annotations
109 
110             with open(path, encoding='utf-8') as f:
111                 for line in f:
112                     line = line.strip()
113                     objects = line.split('\"')
114                     if 1 < len(objects):
115                         if len(objects) == 3:
116                             text = objects[1]
117                         else:
118                             raise Exception("Line %s: unexpected number "
119                                 "of quotes in filename" % line)
120                     else:
121                         text = ''
122                     objects = objects[0].split()
123                     if len(objects) == 1:
124                         objects = objects[0].split(',')
125 
126                     if 8 <= len(objects):
127                         points = [float(p) for p in objects[:8]]
128 
129                         attributes = {}
130                         if 0 < len(text):
131                             attributes['text'] = text
132                         elif len(objects) == 9:
133                             text = objects[8]
134                             attributes['text'] = text
135 
136                         annotations.append(
137                             Polygon(points, attributes=attributes))
138                     elif 4 <= len(objects):
139                         x = float(objects[0])
140                         y = float(objects[1])
141                         w = float(objects[2]) - x
142                         h = float(objects[3]) - y
143 
144                         attributes = {}
145                         if 0 < len(text):
146                             attributes['text'] = text
147                         elif len(objects) == 5:
148                             text = objects[4]
149                             attributes['text'] = text
150 
151                         annotations.append(
152                             Bbox(x, y, w, h, attributes=attributes))
153         return items
154 
155     def _load_segmentation_items(self):
156         items = {}
157 
158         image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)
159         if osp.isdir(image_dir):
160             images = { osp.splitext(osp.relpath(p, image_dir))[0]: p
161                 for p in find_images(image_dir, recursive=True) }
162         else:
163             images = {}
164 
165         for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):
166             item_id = osp.splitext(osp.relpath(path, self._path))[0]
167             item_id = item_id.replace('\\', '/')
168             if item_id.endswith('_GT'):
169                 item_id = item_id[:-3]
170 
171             if item_id not in items:
172                 items[item_id] = DatasetItem(item_id, subset=self._subset,
173                     image=images.get(item_id))
174             annotations = items[item_id].annotations
175 
176             colors = [(255, 255, 255)]
177             chars = ['']
178             centers = [0]
179             groups = [0]
180             group = 1
181             number_in_group = 0
182             with open(path, encoding='utf-8') as f:
183                 for line in f:
184                     line = line.strip()
185                     if line == '':
186                         if number_in_group == 1:
187                             groups[len(groups) - 1] = 0
188                         else:
189                             group += 1
190                         number_in_group = 0
191                         continue
192 
193                     objects = line.split()
194                     if objects[0][0] == '#':
195                         objects[0] = objects[0][1:]
196                         objects[9] = '\" \"'
197                         objects.pop()
198                     if len(objects) != 10:
199                         raise Exception("Line %s contains the wrong number "
200                             "of arguments, e.g. '241 73 144 1 4 0 3 1 4 \"h\"" % line)
201 
202                     centers.append(objects[3] + ' ' + objects[4])
203                     groups.append(group)
204                     colors.append(tuple(int(o) for o in objects[:3]))
205                     char = objects[9]
206                     if char[0] == '\"' and char[-1] == '\"':
207                         char = char[1:-1]
208                     chars.append(char)
209                     number_in_group += 1
210             if number_in_group == 1:
211                 groups[len(groups) - 1] = 0
212 
213             mask_categories = MaskCategories(
214                 {i: colors[i] for i in range(len(colors))})
215             inverse_cls_colormap = mask_categories.inverse_colormap
216 
217             gt_path = osp.join(self._path, item_id + '_GT' + IcdarPath.GT_EXT)
218             if osp.isfile(gt_path):
219                 # load mask through cache
220                 mask = lazy_mask(gt_path, inverse_cls_colormap)
221                 mask = mask()
222 
223                 classes = np.unique(mask)
224                 for label_id in classes:
225                     if label_id == 0:
226                         continue
227                     i = int(label_id)
228                     annotations.append(Mask(group=groups[i],
229                         image=self._lazy_extract_mask(mask, label_id),
230                         attributes={ 'index': i - 1,
231                             'color': ' '.join(str(p) for p in colors[i]),
232                             'text': chars[i], 'center': centers[i] }
233                     ))
234         return items
235 
236     @staticmethod
237     def _lazy_extract_mask(mask, c):
238         return lambda: mask == c
239 
240 class IcdarWordRecognitionExtractor(_IcdarExtractor):
241     def __init__(self, path, **kwargs):
242         kwargs['task'] = IcdarTask.word_recognition
243         super().__init__(path, **kwargs)
244 
245 class IcdarTextLocalizationExtractor(_IcdarExtractor):
246     def __init__(self, path, **kwargs):
247         kwargs['task'] = IcdarTask.text_localization
248         super().__init__(path, **kwargs)
249 
250 class IcdarTextSegmentationExtractor(_IcdarExtractor):
251     def __init__(self, path, **kwargs):
252         kwargs['task'] = IcdarTask.text_segmentation
253         super().__init__(path, **kwargs)
254 
255 
256 class IcdarWordRecognitionImporter(Importer):
257     @classmethod
258     def find_sources(cls, path):
259         return cls._find_sources_recursive(path, '.txt', 'icdar_word_recognition')
260 
261 class IcdarTextLocalizationImporter(Importer):
262     @classmethod
263     def find_sources(cls, path):
264         return cls._find_sources_recursive(path, '', 'icdar_text_localization')
265 
266 class IcdarTextSegmentationImporter(Importer):
267     @classmethod
268     def find_sources(cls, path):
269         return cls._find_sources_recursive(path, '', 'icdar_text_segmentation')
270
```
--- 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/datumaro/plugins/icdar_format/extractor.py b/datumaro/plugins/icdar_format/extractor.py
--- a/datumaro/plugins/icdar_format/extractor.py
+++ b/datumaro/plugins/icdar_format/extractor.py
@@ -3,6 +3,7 @@
 # SPDX-License-Identifier: MIT
 
 from glob import iglob
+import logging as log
 import os.path as osp
 
 import numpy as np
@@ -59,16 +60,13 @@
                 objects = line.split(', ')
                 if len(objects) == 2:
                     image = objects[0]
-                    objects = objects[1].split('\"')
-                    if 1 < len(objects):
-                        if len(objects) % 2:
-                            captions = [objects[2 * i + 1]
-                                for i in range(int(len(objects) / 2))]
+                    captions = []
+                    for caption in objects[1:]:
+                        if caption[0] != '\"' or caption[-1] != '\"':
+                            log.warning("Line %s: unexpected number "
+                                "of quotes" % line)
                         else:
-                            raise Exception("Line %s: unexpected number "
-                                "of quotes in filename" % line)
-                    else:
-                        captions = objects[0].split()
+                            captions.append(caption.replace('\\', '')[1:-1])
                 else:
                     image = objects[0][:-1]
                     captions = []

{"golden_diff": "diff --git a/datumaro/plugins/icdar_format/extractor.py b/datumaro/plugins/icdar_format/extractor.py\n--- a/datumaro/plugins/icdar_format/extractor.py\n+++ b/datumaro/plugins/icdar_format/extractor.py\n@@ -3,6 +3,7 @@\n # SPDX-License-Identifier: MIT\n \n from glob import iglob\n+import logging as log\n import os.path as osp\n \n import numpy as np\n@@ -59,16 +60,13 @@\n                 objects = line.split(', ')\n                 if len(objects) == 2:\n                     image = objects[0]\n-                    objects = objects[1].split('\\\"')\n-                    if 1 < len(objects):\n-                        if len(objects) % 2:\n-                            captions = [objects[2 * i + 1]\n-                                for i in range(int(len(objects) / 2))]\n+                    captions = []\n+                    for caption in objects[1:]:\n+                        if caption[0] != '\\\"' or caption[-1] != '\\\"':\n+                            log.warning(\"Line %s: unexpected number \"\n+                                \"of quotes\" % line)\n                         else:\n-                            raise Exception(\"Line %s: unexpected number \"\n-                                \"of quotes in filename\" % line)\n-                    else:\n-                        captions = objects[0].split()\n+                            captions.append(caption.replace('\\\\', '')[1:-1])\n                 else:\n                     image = objects[0][:-1]\n                     captions = []\n", "issue": "Cannot import captions with double quotes ICDAR Word Recognition\nThe original ICDAR 13/15 dataset for word recognition task contains captions with double quotes (e.g \"READER\\\\\"\").\r\nWhen I try to load this dataset, Datumaro throws an exception with the message:\r\n`Line word_136.png, \"(412\\\")\": unexpected number of quotes in filename`.\n", "before_files": [{"content": "# Copyright (C) 2020 Intel Corporation\n#\n# SPDX-License-Identifier: MIT\n\nfrom glob import iglob\nimport os.path as osp\n\nimport numpy as np\n\nfrom datumaro.components.extractor import (\n    Bbox, Caption, DatasetItem, Importer, Mask, MaskCategories, Polygon,\n    SourceExtractor,\n)\nfrom datumaro.util.image import find_images\nfrom datumaro.util.mask_tools import lazy_mask\n\nfrom .format import IcdarPath, IcdarTask\n\n\nclass _IcdarExtractor(SourceExtractor):\n    def __init__(self, path, task, subset=None):\n        self._path = path\n        self._task = task\n\n        if task is IcdarTask.word_recognition:\n            if not osp.isfile(path):\n                raise FileNotFoundError(\n                    \"Can't read annotation file '%s'\" % path)\n\n            if not subset:\n                subset = osp.basename(osp.dirname(path))\n            super().__init__(subset=subset)\n\n            self._dataset_dir = osp.dirname(osp.dirname(path))\n\n            self._items = list(self._load_recognition_items().values())\n        elif task in {IcdarTask.text_localization, IcdarTask.text_segmentation}:\n            if not osp.isdir(path):\n                raise NotADirectoryError(\n                    \"Can't open folder with annotation files '%s'\" % path)\n\n            if not subset:\n                subset = osp.basename(path)\n            super().__init__(subset=subset)\n\n            self._dataset_dir = osp.dirname(path)\n\n            if task is IcdarTask.text_localization:\n                self._items = list(self._load_localization_items().values())\n            else:\n                self._items = list(self._load_segmentation_items().values())\n\n    def _load_recognition_items(self):\n        items = {}\n\n        with open(self._path, encoding='utf-8') as f:\n            for line in f:\n                line = line.strip()\n                objects = line.split(', ')\n                if len(objects) == 2:\n                    image = objects[0]\n                    objects = objects[1].split('\\\"')\n                    if 1 < len(objects):\n                        if len(objects) % 2:\n                            captions = [objects[2 * i + 1]\n                                for i in range(int(len(objects) / 2))]\n                        else:\n                            raise Exception(\"Line %s: unexpected number \"\n                                \"of quotes in filename\" % line)\n                    else:\n                        captions = objects[0].split()\n                else:\n                    image = objects[0][:-1]\n                    captions = []\n\n                item_id = osp.splitext(image)[0]\n                image_path = osp.join(osp.dirname(self._path),\n                    IcdarPath.IMAGES_DIR, image)\n                if item_id not in items:\n                    items[item_id] = DatasetItem(item_id, subset=self._subset,\n                        image=image_path)\n\n                annotations = items[item_id].annotations\n                for caption in captions:\n                    annotations.append(Caption(caption))\n\n        return items\n\n    def _load_localization_items(self):\n        items = {}\n\n        image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)\n        if osp.isdir(image_dir):\n            images = { osp.splitext(osp.relpath(p, image_dir))[0]: p\n                for p in find_images(image_dir, recursive=True) }\n        else:\n            images = {}\n\n        for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):\n            item_id = osp.splitext(osp.relpath(path, self._path))[0]\n            if osp.basename(item_id).startswith('gt_'):\n                item_id = osp.join(osp.dirname(item_id), osp.basename(item_id)[3:])\n            item_id = item_id.replace('\\\\', '/')\n\n            if item_id not in items:\n                items[item_id] = DatasetItem(item_id, subset=self._subset,\n                    image=images.get(item_id))\n            annotations = items[item_id].annotations\n\n            with open(path, encoding='utf-8') as f:\n                for line in f:\n                    line = line.strip()\n                    objects = line.split('\\\"')\n                    if 1 < len(objects):\n                        if len(objects) == 3:\n                            text = objects[1]\n                        else:\n                            raise Exception(\"Line %s: unexpected number \"\n                                \"of quotes in filename\" % line)\n                    else:\n                        text = ''\n                    objects = objects[0].split()\n                    if len(objects) == 1:\n                        objects = objects[0].split(',')\n\n                    if 8 <= len(objects):\n                        points = [float(p) for p in objects[:8]]\n\n                        attributes = {}\n                        if 0 < len(text):\n                            attributes['text'] = text\n                        elif len(objects) == 9:\n                            text = objects[8]\n                            attributes['text'] = text\n\n                        annotations.append(\n                            Polygon(points, attributes=attributes))\n                    elif 4 <= len(objects):\n                        x = float(objects[0])\n                        y = float(objects[1])\n                        w = float(objects[2]) - x\n                        h = float(objects[3]) - y\n\n                        attributes = {}\n                        if 0 < len(text):\n                            attributes['text'] = text\n                        elif len(objects) == 5:\n                            text = objects[4]\n                            attributes['text'] = text\n\n                        annotations.append(\n                            Bbox(x, y, w, h, attributes=attributes))\n        return items\n\n    def _load_segmentation_items(self):\n        items = {}\n\n        image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)\n        if osp.isdir(image_dir):\n            images = { osp.splitext(osp.relpath(p, image_dir))[0]: p\n                for p in find_images(image_dir, recursive=True) }\n        else:\n            images = {}\n\n        for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):\n            item_id = osp.splitext(osp.relpath(path, self._path))[0]\n            item_id = item_id.replace('\\\\', '/')\n            if item_id.endswith('_GT'):\n                item_id = item_id[:-3]\n\n            if item_id not in items:\n                items[item_id] = DatasetItem(item_id, subset=self._subset,\n                    image=images.get(item_id))\n            annotations = items[item_id].annotations\n\n            colors = [(255, 255, 255)]\n            chars = ['']\n            centers = [0]\n            groups = [0]\n            group = 1\n            number_in_group = 0\n            with open(path, encoding='utf-8') as f:\n                for line in f:\n                    line = line.strip()\n                    if line == '':\n                        if number_in_group == 1:\n                            groups[len(groups) - 1] = 0\n                        else:\n                            group += 1\n                        number_in_group = 0\n                        continue\n\n                    objects = line.split()\n                    if objects[0][0] == '#':\n                        objects[0] = objects[0][1:]\n                        objects[9] = '\\\" \\\"'\n                        objects.pop()\n                    if len(objects) != 10:\n                        raise Exception(\"Line %s contains the wrong number \"\n                            \"of arguments, e.g. '241 73 144 1 4 0 3 1 4 \\\"h\\\"\" % line)\n\n                    centers.append(objects[3] + ' ' + objects[4])\n                    groups.append(group)\n                    colors.append(tuple(int(o) for o in objects[:3]))\n                    char = objects[9]\n                    if char[0] == '\\\"' and char[-1] == '\\\"':\n                        char = char[1:-1]\n                    chars.append(char)\n                    number_in_group += 1\n            if number_in_group == 1:\n                groups[len(groups) - 1] = 0\n\n            mask_categories = MaskCategories(\n                {i: colors[i] for i in range(len(colors))})\n            inverse_cls_colormap = mask_categories.inverse_colormap\n\n            gt_path = osp.join(self._path, item_id + '_GT' + IcdarPath.GT_EXT)\n            if osp.isfile(gt_path):\n                # load mask through cache\n                mask = lazy_mask(gt_path, inverse_cls_colormap)\n                mask = mask()\n\n                classes = np.unique(mask)\n                for label_id in classes:\n                    if label_id == 0:\n                        continue\n                    i = int(label_id)\n                    annotations.append(Mask(group=groups[i],\n                        image=self._lazy_extract_mask(mask, label_id),\n                        attributes={ 'index': i - 1,\n                            'color': ' '.join(str(p) for p in colors[i]),\n                            'text': chars[i], 'center': centers[i] }\n                    ))\n        return items\n\n    @staticmethod\n    def _lazy_extract_mask(mask, c):\n        return lambda: mask == c\n\nclass IcdarWordRecognitionExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.word_recognition\n        super().__init__(path, **kwargs)\n\nclass IcdarTextLocalizationExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.text_localization\n        super().__init__(path, **kwargs)\n\nclass IcdarTextSegmentationExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.text_segmentation\n        super().__init__(path, **kwargs)\n\n\nclass IcdarWordRecognitionImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '.txt', 'icdar_word_recognition')\n\nclass IcdarTextLocalizationImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '', 'icdar_text_localization')\n\nclass IcdarTextSegmentationImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '', 'icdar_text_segmentation')\n", "path": "datumaro/plugins/icdar_format/extractor.py"}], "after_files": [{"content": "# Copyright (C) 2020 Intel Corporation\n#\n# SPDX-License-Identifier: MIT\n\nfrom glob import iglob\nimport logging as log\nimport os.path as osp\n\nimport numpy as np\n\nfrom datumaro.components.extractor import (\n    Bbox, Caption, DatasetItem, Importer, Mask, MaskCategories, Polygon,\n    SourceExtractor,\n)\nfrom datumaro.util.image import find_images\nfrom datumaro.util.mask_tools import lazy_mask\n\nfrom .format import IcdarPath, IcdarTask\n\n\nclass _IcdarExtractor(SourceExtractor):\n    def __init__(self, path, task, subset=None):\n        self._path = path\n        self._task = task\n\n        if task is IcdarTask.word_recognition:\n            if not osp.isfile(path):\n                raise FileNotFoundError(\n                    \"Can't read annotation file '%s'\" % path)\n\n            if not subset:\n                subset = osp.basename(osp.dirname(path))\n            super().__init__(subset=subset)\n\n            self._dataset_dir = osp.dirname(osp.dirname(path))\n\n            self._items = list(self._load_recognition_items().values())\n        elif task in {IcdarTask.text_localization, IcdarTask.text_segmentation}:\n            if not osp.isdir(path):\n                raise NotADirectoryError(\n                    \"Can't open folder with annotation files '%s'\" % path)\n\n            if not subset:\n                subset = osp.basename(path)\n            super().__init__(subset=subset)\n\n            self._dataset_dir = osp.dirname(path)\n\n            if task is IcdarTask.text_localization:\n                self._items = list(self._load_localization_items().values())\n            else:\n                self._items = list(self._load_segmentation_items().values())\n\n    def _load_recognition_items(self):\n        items = {}\n\n        with open(self._path, encoding='utf-8') as f:\n            for line in f:\n                line = line.strip()\n                objects = line.split(', ')\n                if len(objects) == 2:\n                    image = objects[0]\n                    captions = []\n                    for caption in objects[1:]:\n                        if caption[0] != '\\\"' or caption[-1] != '\\\"':\n                            log.warning(\"Line %s: unexpected number \"\n                                \"of quotes\" % line)\n                        else:\n                            captions.append(caption.replace('\\\\', '')[1:-1])\n                else:\n                    image = objects[0][:-1]\n                    captions = []\n\n                item_id = osp.splitext(image)[0]\n                image_path = osp.join(osp.dirname(self._path),\n                    IcdarPath.IMAGES_DIR, image)\n                if item_id not in items:\n                    items[item_id] = DatasetItem(item_id, subset=self._subset,\n                        image=image_path)\n\n                annotations = items[item_id].annotations\n                for caption in captions:\n                    annotations.append(Caption(caption))\n\n        return items\n\n    def _load_localization_items(self):\n        items = {}\n\n        image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)\n        if osp.isdir(image_dir):\n            images = { osp.splitext(osp.relpath(p, image_dir))[0]: p\n                for p in find_images(image_dir, recursive=True) }\n        else:\n            images = {}\n\n        for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):\n            item_id = osp.splitext(osp.relpath(path, self._path))[0]\n            if osp.basename(item_id).startswith('gt_'):\n                item_id = osp.join(osp.dirname(item_id), osp.basename(item_id)[3:])\n            item_id = item_id.replace('\\\\', '/')\n\n            if item_id not in items:\n                items[item_id] = DatasetItem(item_id, subset=self._subset,\n                    image=images.get(item_id))\n            annotations = items[item_id].annotations\n\n            with open(path, encoding='utf-8') as f:\n                for line in f:\n                    line = line.strip()\n                    objects = line.split('\\\"')\n                    if 1 < len(objects):\n                        if len(objects) == 3:\n                            text = objects[1]\n                        else:\n                            raise Exception(\"Line %s: unexpected number \"\n                                \"of quotes in filename\" % line)\n                    else:\n                        text = ''\n                    objects = objects[0].split()\n                    if len(objects) == 1:\n                        objects = objects[0].split(',')\n\n                    if 8 <= len(objects):\n                        points = [float(p) for p in objects[:8]]\n\n                        attributes = {}\n                        if 0 < len(text):\n                            attributes['text'] = text\n                        elif len(objects) == 9:\n                            text = objects[8]\n                            attributes['text'] = text\n\n                        annotations.append(\n                            Polygon(points, attributes=attributes))\n                    elif 4 <= len(objects):\n                        x = float(objects[0])\n                        y = float(objects[1])\n                        w = float(objects[2]) - x\n                        h = float(objects[3]) - y\n\n                        attributes = {}\n                        if 0 < len(text):\n                            attributes['text'] = text\n                        elif len(objects) == 5:\n                            text = objects[4]\n                            attributes['text'] = text\n\n                        annotations.append(\n                            Bbox(x, y, w, h, attributes=attributes))\n        return items\n\n    def _load_segmentation_items(self):\n        items = {}\n\n        image_dir = osp.join(self._path, IcdarPath.IMAGES_DIR)\n        if osp.isdir(image_dir):\n            images = { osp.splitext(osp.relpath(p, image_dir))[0]: p\n                for p in find_images(image_dir, recursive=True) }\n        else:\n            images = {}\n\n        for path in iglob(osp.join(self._path, '**', '*.txt'), recursive=True):\n            item_id = osp.splitext(osp.relpath(path, self._path))[0]\n            item_id = item_id.replace('\\\\', '/')\n            if item_id.endswith('_GT'):\n                item_id = item_id[:-3]\n\n            if item_id not in items:\n                items[item_id] = DatasetItem(item_id, subset=self._subset,\n                    image=images.get(item_id))\n            annotations = items[item_id].annotations\n\n            colors = [(255, 255, 255)]\n            chars = ['']\n            centers = [0]\n            groups = [0]\n            group = 1\n            number_in_group = 0\n            with open(path, encoding='utf-8') as f:\n                for line in f:\n                    line = line.strip()\n                    if line == '':\n                        if number_in_group == 1:\n                            groups[len(groups) - 1] = 0\n                        else:\n                            group += 1\n                        number_in_group = 0\n                        continue\n\n                    objects = line.split()\n                    if objects[0][0] == '#':\n                        objects[0] = objects[0][1:]\n                        objects[9] = '\\\" \\\"'\n                        objects.pop()\n                    if len(objects) != 10:\n                        raise Exception(\"Line %s contains the wrong number \"\n                            \"of arguments, e.g. '241 73 144 1 4 0 3 1 4 \\\"h\\\"\" % line)\n\n                    centers.append(objects[3] + ' ' + objects[4])\n                    groups.append(group)\n                    colors.append(tuple(int(o) for o in objects[:3]))\n                    char = objects[9]\n                    if char[0] == '\\\"' and char[-1] == '\\\"':\n                        char = char[1:-1]\n                    chars.append(char)\n                    number_in_group += 1\n            if number_in_group == 1:\n                groups[len(groups) - 1] = 0\n\n            mask_categories = MaskCategories(\n                {i: colors[i] for i in range(len(colors))})\n            inverse_cls_colormap = mask_categories.inverse_colormap\n\n            gt_path = osp.join(self._path, item_id + '_GT' + IcdarPath.GT_EXT)\n            if osp.isfile(gt_path):\n                # load mask through cache\n                mask = lazy_mask(gt_path, inverse_cls_colormap)\n                mask = mask()\n\n                classes = np.unique(mask)\n                for label_id in classes:\n                    if label_id == 0:\n                        continue\n                    i = int(label_id)\n                    annotations.append(Mask(group=groups[i],\n                        image=self._lazy_extract_mask(mask, label_id),\n                        attributes={ 'index': i - 1,\n                            'color': ' '.join(str(p) for p in colors[i]),\n                            'text': chars[i], 'center': centers[i] }\n                    ))\n        return items\n\n    @staticmethod\n    def _lazy_extract_mask(mask, c):\n        return lambda: mask == c\n\nclass IcdarWordRecognitionExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.word_recognition\n        super().__init__(path, **kwargs)\n\nclass IcdarTextLocalizationExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.text_localization\n        super().__init__(path, **kwargs)\n\nclass IcdarTextSegmentationExtractor(_IcdarExtractor):\n    def __init__(self, path, **kwargs):\n        kwargs['task'] = IcdarTask.text_segmentation\n        super().__init__(path, **kwargs)\n\n\nclass IcdarWordRecognitionImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '.txt', 'icdar_word_recognition')\n\nclass IcdarTextLocalizationImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '', 'icdar_text_localization')\n\nclass IcdarTextSegmentationImporter(Importer):\n    @classmethod\n    def find_sources(cls, path):\n        return cls._find_sources_recursive(path, '', 'icdar_text_segmentation')\n", "path": "datumaro/plugins/icdar_format/extractor.py"}]}