|
|
|
import os.path as osp |
|
import xml.etree.ElementTree as ET |
|
|
|
from mmengine.dist import is_main_process |
|
from mmengine.fileio import get_local_path, list_from_file |
|
from mmengine.utils import ProgressBar |
|
|
|
from mmdet.registry import DATASETS |
|
from mmdet.utils.typing_utils import List, Union |
|
from .xml_style import XMLDataset |
|
|
|
|
|
@DATASETS.register_module() |
|
class WIDERFaceDataset(XMLDataset): |
|
"""Reader for the WIDER Face dataset in PASCAL VOC format. |
|
|
|
Conversion scripts can be found in |
|
https://github.com/sovrasov/wider-face-pascal-voc-annotations |
|
""" |
|
METAINFO = {'classes': ('face', ), 'palette': [(0, 255, 0)]} |
|
|
|
def load_data_list(self) -> List[dict]: |
|
"""Load annotation from XML style ann_file. |
|
|
|
Returns: |
|
list[dict]: Annotation info from XML file. |
|
""" |
|
assert self._metainfo.get('classes', None) is not None, \ |
|
'classes in `XMLDataset` can not be None.' |
|
self.cat2label = { |
|
cat: i |
|
for i, cat in enumerate(self._metainfo['classes']) |
|
} |
|
|
|
data_list = [] |
|
img_ids = list_from_file(self.ann_file, backend_args=self.backend_args) |
|
|
|
|
|
if is_main_process(): |
|
prog_bar = ProgressBar(len(img_ids)) |
|
|
|
for img_id in img_ids: |
|
raw_img_info = {} |
|
raw_img_info['img_id'] = img_id |
|
raw_img_info['file_name'] = f'{img_id}.jpg' |
|
parsed_data_info = self.parse_data_info(raw_img_info) |
|
data_list.append(parsed_data_info) |
|
|
|
if is_main_process(): |
|
prog_bar.update() |
|
return data_list |
|
|
|
def parse_data_info(self, img_info: dict) -> Union[dict, List[dict]]: |
|
"""Parse raw annotation to target format. |
|
|
|
Args: |
|
img_info (dict): Raw image information, usually it includes |
|
`img_id`, `file_name`, and `xml_path`. |
|
|
|
Returns: |
|
Union[dict, List[dict]]: Parsed annotation. |
|
""" |
|
data_info = {} |
|
img_id = img_info['img_id'] |
|
xml_path = osp.join(self.data_prefix['img'], 'Annotations', |
|
f'{img_id}.xml') |
|
data_info['img_id'] = img_id |
|
data_info['xml_path'] = xml_path |
|
|
|
|
|
with get_local_path( |
|
xml_path, backend_args=self.backend_args) as local_path: |
|
raw_ann_info = ET.parse(local_path) |
|
root = raw_ann_info.getroot() |
|
size = root.find('size') |
|
width = int(size.find('width').text) |
|
height = int(size.find('height').text) |
|
folder = root.find('folder').text |
|
img_path = osp.join(self.data_prefix['img'], folder, |
|
img_info['file_name']) |
|
data_info['img_path'] = img_path |
|
|
|
data_info['height'] = height |
|
data_info['width'] = width |
|
|
|
|
|
data_info['instances'] = self._parse_instance_info( |
|
raw_ann_info, minus_one=False) |
|
return data_info |
|
|