|
|
|
import json |
|
from pathlib import Path |
|
|
|
import numpy as np |
|
import torch |
|
from PIL import Image |
|
|
|
from panopticapi.utils import rgb2id |
|
from util.box_ops import masks_to_boxes |
|
|
|
from .coco import make_coco_transforms |
|
|
|
|
|
class CocoPanoptic: |
|
def __init__(self, img_folder, ann_folder, ann_file, transforms=None, return_masks=True): |
|
with open(ann_file, 'r') as f: |
|
self.coco = json.load(f) |
|
|
|
|
|
|
|
self.coco['images'] = sorted(self.coco['images'], key=lambda x: x['id']) |
|
|
|
if "annotations" in self.coco: |
|
for img, ann in zip(self.coco['images'], self.coco['annotations']): |
|
assert img['file_name'][:-4] == ann['file_name'][:-4] |
|
|
|
self.img_folder = img_folder |
|
self.ann_folder = ann_folder |
|
self.ann_file = ann_file |
|
self.transforms = transforms |
|
self.return_masks = return_masks |
|
|
|
def __getitem__(self, idx): |
|
ann_info = self.coco['annotations'][idx] if "annotations" in self.coco else self.coco['images'][idx] |
|
img_path = Path(self.img_folder) / ann_info['file_name'].replace('.png', '.jpg') |
|
ann_path = Path(self.ann_folder) / ann_info['file_name'] |
|
|
|
img = Image.open(img_path).convert('RGB') |
|
w, h = img.size |
|
if "segments_info" in ann_info: |
|
masks = np.asarray(Image.open(ann_path), dtype=np.uint32) |
|
masks = rgb2id(masks) |
|
|
|
ids = np.array([ann['id'] for ann in ann_info['segments_info']]) |
|
masks = masks == ids[:, None, None] |
|
|
|
masks = torch.as_tensor(masks, dtype=torch.uint8) |
|
labels = torch.tensor([ann['category_id'] for ann in ann_info['segments_info']], dtype=torch.int64) |
|
|
|
target = {} |
|
target['image_id'] = torch.tensor([ann_info['image_id'] if "image_id" in ann_info else ann_info["id"]]) |
|
if self.return_masks: |
|
target['masks'] = masks |
|
target['labels'] = labels |
|
|
|
target["boxes"] = masks_to_boxes(masks) |
|
|
|
target['size'] = torch.as_tensor([int(h), int(w)]) |
|
target['orig_size'] = torch.as_tensor([int(h), int(w)]) |
|
if "segments_info" in ann_info: |
|
for name in ['iscrowd', 'area']: |
|
target[name] = torch.tensor([ann[name] for ann in ann_info['segments_info']]) |
|
|
|
if self.transforms is not None: |
|
img, target = self.transforms(img, target) |
|
|
|
return img, target |
|
|
|
def __len__(self): |
|
return len(self.coco['images']) |
|
|
|
def get_height_and_width(self, idx): |
|
img_info = self.coco['images'][idx] |
|
height = img_info['height'] |
|
width = img_info['width'] |
|
return height, width |
|
|
|
|
|
def build(image_set, args): |
|
img_folder_root = Path(args.coco_path) |
|
ann_folder_root = Path(args.coco_panoptic_path) |
|
assert img_folder_root.exists(), f'provided COCO path {img_folder_root} does not exist' |
|
assert ann_folder_root.exists(), f'provided COCO path {ann_folder_root} does not exist' |
|
mode = 'panoptic' |
|
PATHS = { |
|
"train": ("train2017", Path("annotations") / f'{mode}_train2017.json'), |
|
"val": ("val2017", Path("annotations") / f'{mode}_val2017.json'), |
|
} |
|
|
|
img_folder, ann_file = PATHS[image_set] |
|
img_folder_path = img_folder_root / img_folder |
|
ann_folder = ann_folder_root / f'{mode}_{img_folder}' |
|
ann_file = ann_folder_root / ann_file |
|
|
|
dataset = CocoPanoptic(img_folder_path, ann_folder, ann_file, |
|
transforms=make_coco_transforms(image_set), return_masks=args.masks) |
|
|
|
return dataset |
|
|