Skip to content

Commit

Permalink
add PPP dataset
Browse files Browse the repository at this point in the history
  • Loading branch information
msinamsina committed Jan 31, 2023
1 parent a0b2a33 commit d696b49
Show file tree
Hide file tree
Showing 11 changed files with 406 additions and 281 deletions.
10 changes: 5 additions & 5 deletions adet/config/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
_C.MODEL.POLO.INSTANCE_IN_CHANNELS = 256
_C.MODEL.POLO.INSTANCE_CHANNELS = 512
# Convolutions to use in the instance head.
_C.MODEL.POLO.NUM_INSTANCE_CONVS = 4
_C.MODEL.POLO.NUM_INSTANCE_CONVS = 6
_C.MODEL.POLO.USE_DCN_IN_INSTANCE = False
_C.MODEL.POLO.TYPE_DCN = 'DCN'
_C.MODEL.POLO.NUM_GRIDS = [40, 36, 24, 16, 12]
Expand All @@ -366,7 +366,7 @@
# Channel size for the mask tower.
_C.MODEL.POLO.MASK_IN_FEATURES = ["p2", "p3", "p4", "p5"]
_C.MODEL.POLO.MASK_IN_CHANNELS = 256
_C.MODEL.POLO.MASK_CHANNELS = 128
_C.MODEL.POLO.MASK_CHANNELS = 512 #256 #128
_C.MODEL.POLO.NUM_MASKS = 32

# Test cfg.
Expand All @@ -388,10 +388,10 @@
# _C.MODEL.POLO.LOSS.FOCAL_GAMMA = 2.0
# _C.MODEL.POLO.LOSS.FOCAL_WEIGHT = 1.0
# _C.MODEL.POLO.LOSS.DICE_WEIGHT = 3.0
_C.MODEL.POLO.LOSS.OBJ_WEIGHT = 1.0
_C.MODEL.POLO.LOSS.SEGCROSS_WEIGHT = 2.0
_C.MODEL.POLO.LOSS.OBJ_WEIGHT = 0.1
_C.MODEL.POLO.LOSS.SEGCROSS_WEIGHT = 200.0
_C.MODEL.POLO.LOSS.SEGCROSS_CLASSES_WEIGHT = None
_C.MODEL.POLO.LOSS.SEGLOVASZ_WEIGHT = 0.1
_C.MODEL.POLO.LOSS.SEGLOVASZ_WEIGHT = 10.0
_C.MODEL.POLO.LOSS.SEGLOVASZ_PERIMG = True


Expand Down
6 changes: 6 additions & 0 deletions adet/data/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from detectron2.data.datasets.builtin_meta import _get_builtin_metadata
from detectron2.data import MetadataCatalog, DatasetCatalog
from .datasets.cihp import get_cihp_dicts, CIHPDataset
from .datasets.pascal_person_part import PPPDataset

from .datasets.text import register_text_instances

Expand Down Expand Up @@ -68,6 +69,9 @@ def register_all_coco(root="datasets"):
DatasetCatalog.register("CIHP_train_v2", CIHPDataset(root, train=True))
DatasetCatalog.register("CIHP_val_v2", CIHPDataset(root, train=False))

DatasetCatalog.register("PPP_train", PPPDataset(root, train=True))
DatasetCatalog.register("PPP_val", PPPDataset(root, train=False))

DatasetCatalog.register("CIHP_train_person", lambda: get_cihp_dicts(root, train=True, person_only=True))
DatasetCatalog.register("CIHP_val_person", lambda: get_cihp_dicts(root, train=False, person_only=True))

Expand All @@ -81,6 +85,8 @@ def register_all_coco(root="datasets"):
MetadataCatalog.get('CIHP_val').set(thing_classes=thing_classes, stuff_classes=stuff_classes, evaluator_type="coco")
MetadataCatalog.get('CIHP_train_v2').set(thing_classes=thing_classes[1:], stuff_classes=stuff_classes, evaluator_type="parsing")
MetadataCatalog.get('CIHP_val_v2').set(thing_classes=thing_classes[1:], stuff_classes=stuff_classes, evaluator_type="parsing")
MetadataCatalog.get('PPP_train').set(thing_classes=thing_classes, stuff_classes=stuff_classes, evaluator_type="parsing")
MetadataCatalog.get('PPP_val').set(thing_classes=thing_classes, stuff_classes=stuff_classes, evaluator_type="parsing")
MetadataCatalog.get('CIHP_train_person').set(thing_classes=['Person'], evaluator_type="coco")
MetadataCatalog.get('CIHP_val_person').set(thing_classes=['Person'], evaluator_type="coco")
MetadataCatalog.get('CIHP_train_person').set(thing_classes=['Person'], evaluator_type="coco")
Expand Down
142 changes: 142 additions & 0 deletions adet/data/datasets/pascal_person_part.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import os
from detectron2.structures import BoxMode
from imantics import Polygons, Mask
import pickle
import cv2
import numpy as np
from torch.utils.data import Dataset
from scipy.io import loadmat
from matplotlib import pyplot as plt


class PPPDataset(Dataset):
def __init__(self, root, train=False):
self.train = train

# Loading the Colormap
colormap = loadmat(os.path.join(root, 'CIHP/human_colormap.mat')
)["colormap"]
colormap = colormap * 100
self.colormap = colormap.astype(np.uint8)
self.root = os.path.join(root, 'VOCdevkit/VOC2010/')
if train:
dataset = "train_id.txt"
else:
dataset = "val_id.txt"

l = None
with open(os.path.join(self.root, 'pascal_person_part/pascal_person_part_trainval_list', dataset)) as f:
self.anno_ids = f.read()
self.anno_ids = self.anno_ids.split('\n')[:-1]
# try:
# self.anno_ids.remove('2009_003166')
# self.anno_ids.remove('2008_000572')
# self.anno_ids.remove('2009_005085')
# self.anno_ids.remove('2008_000008')
# self.anno_ids.remove('2008_000036')
# except:
# pass


def __call__(self, *args, **kwargs):
return self

def __getitem__(self, idx):
pictur_id = self.anno_ids[idx]

record = {}
filename = os.path.join(self.root, 'JPEGImages', pictur_id + '.jpg')
# print(f'file name: {filename}')
height, width = cv2.imread(filename).shape[:2]

record["file_name"] = filename
record["image_id"] = idx
record["height"] = height
record["width"] = width
record["annotations"] = self.create_annotations(pictur_id)
record['sem_seg_file_name'] = os.path.join(self.root, "pascal_person_part/pascal_person_part_gt", pictur_id + '.png')
return record

def create_annotations(self, pictur_id):
part_anno = loadmat(os.path.join(self.root, "Annotations_Part", pictur_id + '.mat'))
person_part_mask = self.read_mask(os.path.join(self.root, "pascal_person_part/pascal_person_part_gt", pictur_id + '.png'))

# plt.imshow(person_part_mask)
# plt.show()

inst_img = None
cnt = 0
objs = []
for i in range(len(part_anno['anno'][0, 0][1][0])):
# print(part_anno['anno'][0, 0][1][0, i][0][0])
if part_anno['anno'][0, 0][1][0, i][0][0] == 'person':
inst_img = part_anno['anno'][0, 0][1][0, i][2] * person_part_mask

# plt.imshow(inst_img)
# plt.show()
flg = False
instances = np.unique(inst_img)
for inst in instances:
if inst == 0:
continue
mask = inst_img.copy()
mask[mask != inst] = 0
mask[mask == inst] = 1

polygons = Mask(mask).polygons()
xy = polygons.bbox()

poly = polygons.segmentation

# filter out small polygons
true_polygons_list = []
for p in poly:
if len(p) > 5:
true_polygons_list.append(p)

if len(true_polygons_list) < 1:
continue

obj = {
"bbox": list(xy),
"bbox_mode": BoxMode.XYXY_ABS,
"segmentation": true_polygons_list,
"category_id": inst ,
"parent_id": cnt,
}
if obj['category_id'] < 0:
print(obj)
print(instances)
objs.append(obj)
flg = True
# print(np.unique(inst_img))
if flg:
cnt += 1
# cnt += 1
return objs

def __len__(self):
# return 1
return len(self.anno_ids)

def get_dicts(self):
return [self.__getitem__(i) for i in range(len(self))]

def read_mask(self, filename):
mask = cv2.imread(filename)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)

mask[mask == 255] = 0
mask[mask == 15] = 4
mask[mask == 38] = 1
mask[mask == 53] = 5
mask[mask == 75] = 2
mask[mask == 90] = 6
mask[mask == 113] = 3
return mask


if __name__ == '__main__':
dataset = PPPDataset('/media/aras_vision/SSD/sina/Other-src/datasets/', train=True)
for i in range(len(dataset)):
print(dataset[i])
88 changes: 61 additions & 27 deletions adet/evaluation/parsing_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import numpy as np
from PIL import Image, ImageDraw
import time


def poly_to_mask(polygon, width, height):
Expand All @@ -16,6 +17,7 @@ def poly_to_mask(polygon, width, height):
mask = np.array(img)
return mask


def decode_segmentation_masks(mask, colormap, n_classes):
r = np.zeros_like(mask).astype(np.uint8)
g = np.zeros_like(mask).astype(np.uint8)
Expand All @@ -28,7 +30,8 @@ def decode_segmentation_masks(mask, colormap, n_classes):
rgb = np.stack([r, g, b], axis=2)
return rgb

def plot_mask(mask, colormap, classes = 20, row=1, mask_name=None):

def plot_mask(mask, colormap, classes=20, row=1, mask_name=None):
col = ((mask.size(0)) // row) + 2
fig, ax = plt.subplots(col, row, figsize=(10, 10))
for i in range(mask.size(0)):
Expand All @@ -38,6 +41,7 @@ def plot_mask(mask, colormap, classes = 20, row=1, mask_name=None):
if mask_name is not None:
plt.savefig(mask_name)


def voc_ap(rec, prec, use_07_metric=False):
""" ap = voc_ap(rec, prec, [use_07_metric])
Compute VOC AP given precision and recall.
Expand Down Expand Up @@ -97,16 +101,25 @@ def __init__(self, dataset_name, cfg, distributed, output_dir=None):
self.dataset_dicts = DatasetCatalog.get(dataset_name)
self.metadata = MetadataCatalog.get(dataset_name)
self.ovthresh_seg = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

# if not os.path.exists(output_dir):
try:
os.makedirs(output_dir)
except OSError:
pass
def reset(self):
self.tp = {}
self.fp = {}
for i in self.ovthresh_seg:
self.tp[i] = []
self.fp[i] = []
self.npos = 0
self.total_time = 0
self.delta_time = time.time()
self.num_images = 0

def process(self, inputs, outputs):
self.num_images += len(inputs)
self.total_time += (time.time() - self.delta_time)
for input, output in zip(inputs, outputs):
# self.npos += len(self.dataset_dicts[input['image_id']]['annotations'])
if len(output["instances"]) == 0:
Expand All @@ -116,6 +129,7 @@ def process(self, inputs, outputs):
w, h = output["instances"].pred_masks.size(1), output["instances"].pred_masks.size(2)
seg_gt = self.mix_parts_of_instance(self.dataset_dicts[input['image_id']]['annotations'], (w, h))
self.npos += seg_gt.size(0)
# print(seg_gt.shape)
seg_pred = output["instances"].pred_masks
# seg_pred = seg_gt.clone()
list_mious = []
Expand All @@ -126,24 +140,29 @@ def process(self, inputs, outputs):
a = seg_pred[i].clone().to('cpu')
for j in range(seg_gt.size(0)):
b = seg_gt[j].clone().to('cpu')
b[b >= 20] = 0
a[a == 15] = 14
b[b == 15] = 14
a[a == 17] = 16
b[b == 17] = 16
a[a == 19] = 18
b[b == 19] = 18
a[a == 6] = 5
b[b == 6] = 5
a[a == 7] = 5
b[b == 7] = 5
b[b >= 7] = 0
# a[a == 15] = 14
# b[b == 15] = 14
# a[a == 17] = 16
# b[b == 17] = 16
# a[a == 19] = 18
# b[b == 19] = 18
# a[a == 6] = 5
# b[b == 6] = 5
# a[a == 7] = 5
# b[b == 7] = 5
# a[a == 10] = 5
# b[b == 10] = 5
# a[a == 12] = 5
# b[b == 12] = 5
# a[a > 0] = 1
# b[b > 0] = 1

# print(a.unique())
# print(b.unique())
seg_iou = cal_one_mean_iou(a.numpy().astype(np.uint8), b.numpy().astype(np.uint8), 20)
seg_iou = cal_one_mean_iou(a.numpy().astype(np.uint8), b.numpy().astype(np.uint8), 7)
# print(seg_iou)
seg_iou = seg_iou[b.unique().cpu().numpy().astype(np.uint8)]
# seg_iou = seg_iou[b.unique().cpu().numpy().astype(np.uint8)]
# seg_iou[seg_iou == 0] = np.nan
mean_seg_iou = np.nanmean(seg_iou[0:])
# print(mean_seg_iou)
Expand All @@ -152,20 +171,31 @@ def process(self, inputs, outputs):
max_iou_id = j

list_mious.append({"id": max_iou_id, "iou": max_iou})
# print(list_mious)
for i in list_mious:
for j in self.ovthresh_seg:
if i["iou"] > j:
self.tp[j].append(1)
self.fp[j].append(0)

list_mious = sorted(list_mious, key=lambda x: x["iou"], reverse=True)
print([f"{x['id']}:{x['iou']:.3f}" for x in list_mious])
for j in self.ovthresh_seg:
id_list = []
for i in list_mious:
if i['id'] not in id_list:
if i["iou"] >= j:
id_list.append(i['id'])
self.tp[j].append(1)
self.fp[j].append(0)
else:
self.tp[j].append(0)
self.fp[j].append(1)
else:
# pass
self.tp[j].append(0)
self.fp[j].append(1)

plot_mask(seg_gt, self.dataset_dicts.colormap, 20, 2, os.path.join(self._output_dir, str(input['image_id']) + "_gt.png"))
plot_mask(seg_pred, self.dataset_dicts.colormap, 20, 2, os.path.join(self._output_dir, str(input['image_id']) + "_pred.png"))
# plot_mask(seg_gt, self.dataset_dicts.colormap, 20, 2, os.path.join(self._output_dir, str(input['image_id']) + "_gt.png"))
# plot_mask(seg_pred, self.dataset_dicts.colormap, 20, 2, os.path.join(self._output_dir, str(input['image_id']) + "_pred.png"))
# plt.show()
# self.evaluate()
self.delta_time = time.time()
# return self.evaluate()

def mix_parts_of_instance(self, instances, size):
person_ids = set()
Expand All @@ -174,7 +204,7 @@ def mix_parts_of_instance(self, instances, size):

h, w = size
seg_mask = torch.zeros((len(person_ids), h, w))

# print(person_ids)
for i in person_ids:
for j in instances:
if j['parent_id'] == i:
Expand All @@ -184,7 +214,6 @@ def mix_parts_of_instance(self, instances, size):

return seg_mask


def evaluate(self):
result = {}
for i in self.ovthresh_seg:
Expand All @@ -194,10 +223,15 @@ def evaluate(self):
fp = np.cumsum(fp)
rec = tp / self.npos
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)

ap = voc_ap(rec, prec)
print(f"APp@{i}: ", ap)
print(f"APp@{i}: {ap:.3f}, {self.npos}, {tp[-1]}, {fp[-1]}")
result[f"APp@{i}"] = ap

result["APpvol"] = sum(result.values()) / len(result)
print(f"APpvol: ", result["APpvol"])
result["total_time"] = self.total_time
result["fps"] = self.num_images / self.total_time
print(f"APpvol: {result['APpvol']:.3f}")
print(f"total_time: {result['total_time']:.2f}")
print(f"fps: {result['fps']:.2f}")
return result
Loading

0 comments on commit d696b49

Please sign in to comment.