Spaces:
Runtime error
Runtime error
| # Copyright (c) OpenMMLab. All rights reserved. | |
| from typing import Any, Callable, List, Optional, Sequence, Tuple, Union | |
| import mmcv | |
| from mmengine.dataset import BaseDataset | |
| from mmocr.registry import DATASETS | |
| class RecogLMDBDataset(BaseDataset): | |
| r"""RecogLMDBDataset for text recognition. | |
| The annotation format should be in lmdb format. The lmdb file should | |
| contain three keys: 'num-samples', 'label-xxxxxxxxx' and 'image-xxxxxxxxx', | |
| where 'xxxxxxxxx' is the index of the image. The value of 'num-samples' is | |
| the total number of images. The value of 'label-xxxxxxx' is the text label | |
| of the image, and the value of 'image-xxxxxxx' is the image data. | |
| following keys: | |
| Each item fetched from this dataset will be a dict containing the | |
| following keys: | |
| - img (ndarray): The loaded image. | |
| - img_path (str): The image key. | |
| - instances (list[dict]): The list of annotations for the image. | |
| Args: | |
| ann_file (str): Annotation file path. Defaults to ''. | |
| img_color_type (str): The flag argument for :func:``mmcv.imfrombytes``, | |
| which determines how the image bytes will be parsed. Defaults to | |
| 'color'. | |
| metainfo (dict, optional): Meta information for dataset, such as class | |
| information. Defaults to None. | |
| data_root (str): The root directory for ``data_prefix`` and | |
| ``ann_file``. Defaults to ''. | |
| data_prefix (dict): Prefix for training data. Defaults to | |
| ``dict(img_path='')``. | |
| filter_cfg (dict, optional): Config for filter data. Defaults to None. | |
| indices (int or Sequence[int], optional): Support using first few | |
| data in annotation file to facilitate training/testing on a smaller | |
| dataset. Defaults to None which means using all ``data_infos``. | |
| serialize_data (bool, optional): Whether to hold memory using | |
| serialized objects, when enabled, data loader workers can use | |
| shared RAM from master process instead of making a copy. Defaults | |
| to True. | |
| pipeline (list, optional): Processing pipeline. Defaults to []. | |
| test_mode (bool, optional): ``test_mode=True`` means in test phase. | |
| Defaults to False. | |
| lazy_init (bool, optional): Whether to load annotation during | |
| instantiation. In some cases, such as visualization, only the meta | |
| information of the dataset is needed, which is not necessary to | |
| load annotation file. ``RecogLMDBDataset`` can skip load | |
| annotations to save time by set ``lazy_init=False``. | |
| Defaults to False. | |
| max_refetch (int, optional): If ``RecogLMDBdataset.prepare_data`` get a | |
| None img. The maximum extra number of cycles to get a valid | |
| image. Defaults to 1000. | |
| """ | |
| def __init__( | |
| self, | |
| ann_file: str = '', | |
| img_color_type: str = 'color', | |
| metainfo: Optional[dict] = None, | |
| data_root: Optional[str] = '', | |
| data_prefix: dict = dict(img_path=''), | |
| filter_cfg: Optional[dict] = None, | |
| indices: Optional[Union[int, Sequence[int]]] = None, | |
| serialize_data: bool = True, | |
| pipeline: List[Union[dict, Callable]] = [], | |
| test_mode: bool = False, | |
| lazy_init: bool = False, | |
| max_refetch: int = 1000, | |
| ) -> None: | |
| super().__init__( | |
| ann_file=ann_file, | |
| metainfo=metainfo, | |
| data_root=data_root, | |
| data_prefix=data_prefix, | |
| filter_cfg=filter_cfg, | |
| indices=indices, | |
| serialize_data=serialize_data, | |
| pipeline=pipeline, | |
| test_mode=test_mode, | |
| lazy_init=lazy_init, | |
| max_refetch=max_refetch) | |
| self.color_type = img_color_type | |
| def load_data_list(self) -> List[dict]: | |
| """Load annotations from an annotation file named as ``self.ann_file`` | |
| Returns: | |
| List[dict]: A list of annotation. | |
| """ | |
| if not hasattr(self, 'env'): | |
| self._make_env() | |
| with self.env.begin(write=False) as txn: | |
| self.total_number = int( | |
| txn.get(b'num-samples').decode('utf-8')) | |
| data_list = [] | |
| with self.env.begin(write=False) as txn: | |
| for i in range(self.total_number): | |
| idx = i + 1 | |
| label_key = f'label-{idx:09d}' | |
| img_key = f'image-{idx:09d}' | |
| text = txn.get(label_key.encode('utf-8')).decode('utf-8') | |
| line = [img_key, text] | |
| data_list.append(self.parse_data_info(line)) | |
| return data_list | |
| def parse_data_info(self, | |
| raw_anno_info: Tuple[Optional[str], | |
| str]) -> Union[dict, List[dict]]: | |
| """Parse raw annotation to target format. | |
| Args: | |
| raw_anno_info (str): One raw data information loaded | |
| from ``ann_file``. | |
| Returns: | |
| (dict): Parsed annotation. | |
| """ | |
| data_info = {} | |
| img_key, text = raw_anno_info | |
| data_info['img_key'] = img_key | |
| data_info['instances'] = [dict(text=text)] | |
| return data_info | |
| def prepare_data(self, idx) -> Any: | |
| """Get data processed by ``self.pipeline``. | |
| Args: | |
| idx (int): The index of ``data_info``. | |
| Returns: | |
| Any: Depends on ``self.pipeline``. | |
| """ | |
| data_info = self.get_data_info(idx) | |
| with self.env.begin(write=False) as txn: | |
| img_bytes = txn.get(data_info['img_key'].encode('utf-8')) | |
| if img_bytes is None: | |
| return None | |
| data_info['img'] = mmcv.imfrombytes( | |
| img_bytes, flag=self.color_type) | |
| return self.pipeline(data_info) | |
| def _make_env(self): | |
| """Create lmdb environment from self.ann_file and save it to | |
| ``self.env``. | |
| Returns: | |
| Lmdb environment. | |
| """ | |
| try: | |
| import lmdb | |
| except ImportError: | |
| raise ImportError( | |
| 'Please install lmdb to enable RecogLMDBDataset.') | |
| if hasattr(self, 'env'): | |
| return | |
| self.env = lmdb.open( | |
| self.ann_file, | |
| max_readers=1, | |
| readonly=True, | |
| lock=False, | |
| readahead=False, | |
| meminit=False, | |
| ) | |
| def close(self): | |
| """Close lmdb environment.""" | |
| if hasattr(self, 'env'): | |
| self.env.close() | |
| del self.env | |