Skip to content
This repository has been archived by the owner on Nov 21, 2023. It is now read-only.

Custom dataset without segmentations #48

Closed
learnbott opened this issue Jan 27, 2018 · 8 comments
Closed

Custom dataset without segmentations #48

learnbott opened this issue Jan 27, 2018 · 8 comments

Comments

@learnbott
Copy link

learnbott commented Jan 27, 2018

Is there a way to run a custom dataset that only has bounding boxes? I have the Wider Face dataset in COCO api json format, but it won't train without a segmentation field in annotations. I had to use two work arounds:

  1. Use annotation['segmenation'] = 0 and annotation['area'] = bbox_height * bbox_width (and of course leaving TRAIN.GT_MIN_AREA = -1)
  2. To allow TRAIN.USE_FLIPPED = True, Detectron/lib/datasets/roidb.py had to have some code commented out in this function:
def extend_with_flipped_entries(roidb, dataset):
    """Flip each entry in the given roidb and return a new roidb that is the
    concatenation of the original roidb and the flipped entries.
    "Flipping" an entry means that that image and associated metadata (e.g.,
    ground truth boxes and object proposals) are horizontally flipped.
    """
    flipped_roidb = []
    for entry in roidb:
        width = entry['width']
        boxes = entry['boxes'].copy()
        oldx1 = boxes[:, 0].copy()
        oldx2 = boxes[:, 2].copy()
        boxes[:, 0] = width - oldx2 - 1
        boxes[:, 2] = width - oldx1 - 1
        assert (boxes[:, 2] >= boxes[:, 0]).all()
        flipped_entry = {}
        dont_copy = ('boxes', 'segms', 'gt_keypoints', 'flipped')
        for k, v in entry.items():
            if k not in dont_copy:
                flipped_entry[k] = v
        flipped_entry['boxes'] = boxes
        ### commenting out to allow flipping for datasets without segmentations annotated
        #flipped_entry['segms'] = segm_utils.flip_segms(
        #   entry['segms'], entry['height'], entry['width']
        #)
        if dataset.keypoints is not None:
            flipped_entry['gt_keypoints'] = keypoint_utils.flip_keypoints(
                dataset.keypoints, dataset.keypoint_flip_map,
                entry['gt_keypoints'], entry['width']
            )
        flipped_entry['flipped'] = True
        flipped_roidb.append(flipped_entry)
    roidb.extend(flipped_roidb)

With those two adjustments the code runs beautifully. Is there a flag or config param that I am missing, or an easier way to run datasets with only bboxes?

Thank you for the code and the docker version!

@ir413
Copy link
Contributor

ir413 commented Jan 28, 2018

Hi @learnbott, I think it may be simpler and less error-prone to preprocess your json annotations to include the following entries:

'segmentation': []
'area': box_width * box_height
'iscrowd': 0

I believe this would allow you to perform training (w/ flipping) without any modifications to the code.

@learnbott
Copy link
Author

learnbott commented Jan 29, 2018 via email

@borisfom
Copy link

borisfom commented Mar 8, 2018

@learnbott : what was the speed of wider faces detector you have trained (on HD frame) ?

@learnbott
Copy link
Author

@borisfom, the speed for training and inference is comparable to those reported on MODEL_ZOO.md and depends which model you use. Unfortunately, Detectron does not currently support CPU inference (see #36).

@borisfom
Copy link

borisfom commented Mar 8, 2018

Thanks learnbott ! I don't care about CPU...
Would you share any of your trained models for the faces ?

@learnbott
Copy link
Author

Mine is pretty simple, but if you want a great face detector I would use Dockerface https://github.com/natanielruiz/dockerface. Its a faster r-cnn trained on multiple face datasets. https://arxiv.org/abs/1708.04370

@shubhbrth
Copy link

Is there a way to run a custom dataset that only has bounding boxes? I have the Wider Face dataset in COCO api json format, but it won't train without a segmentation field in annotations. I had to use two work arounds:

  1. Use annotation['segmenation'] = 0 and annotation['area'] = bbox_height * bbox_width (and of course leaving TRAIN.GT_MIN_AREA = -1)
  2. To allow TRAIN.USE_FLIPPED = True, Detectron/lib/datasets/roidb.py had to have some code commented out in this function:
def extend_with_flipped_entries(roidb, dataset):
    """Flip each entry in the given roidb and return a new roidb that is the
    concatenation of the original roidb and the flipped entries.
    "Flipping" an entry means that that image and associated metadata (e.g.,
    ground truth boxes and object proposals) are horizontally flipped.
    """
    flipped_roidb = []
    for entry in roidb:
        width = entry['width']
        boxes = entry['boxes'].copy()
        oldx1 = boxes[:, 0].copy()
        oldx2 = boxes[:, 2].copy()
        boxes[:, 0] = width - oldx2 - 1
        boxes[:, 2] = width - oldx1 - 1
        assert (boxes[:, 2] >= boxes[:, 0]).all()
        flipped_entry = {}
        dont_copy = ('boxes', 'segms', 'gt_keypoints', 'flipped')
        for k, v in entry.items():
            if k not in dont_copy:
                flipped_entry[k] = v
        flipped_entry['boxes'] = boxes
        ### commenting out to allow flipping for datasets without segmentations annotated
        #flipped_entry['segms'] = segm_utils.flip_segms(
        #   entry['segms'], entry['height'], entry['width']
        #)
        if dataset.keypoints is not None:
            flipped_entry['gt_keypoints'] = keypoint_utils.flip_keypoints(
                dataset.keypoints, dataset.keypoint_flip_map,
                entry['gt_keypoints'], entry['width']
            )
        flipped_entry['flipped'] = True
        flipped_roidb.append(flipped_entry)
    roidb.extend(flipped_roidb)

With those two adjustments the code runs beautifully. Is there a flag or config param that I am missing, or an easier way to run datasets with only bboxes?

Thank you for the code and the docker version!

@learnbott Are your errors resolved after using

'segmentation': []
'area': box_width * box_height
'iscrowd': 0

As I am able to train the model after using above syntax but not able to detect objects from the validation image.

Using below code for detection:

cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth")
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7 # set the testing threshold for this model
cfg.DATASETS.TEST = ("balloon_val", )
predictor = DefaultPredictor(cfg)

from detectron2.utils.visualizer import ColorMode
dataset_dicts = get_balloon_dicts("balloon/val")
for d in random.sample(dataset_dicts, 3):
im = cv2.imread(d["file_name"])
outputs = predictor(im)
v = Visualizer(im[:, :, ::-1],
metadata=balloon_metadata,
scale=0.8,
instance_mode=ColorMode.IMAGE_BW # remove the colors of unsegmented pixels
)
v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2_imshow(v.get_image()[:, :, ::-1])

@ryosuzaki
Copy link

What about depicting bounding boxes as segmentations instead of leaving the segmentation empty? Please give me your opinion.

"segmentation":[[x_min,y_min,x_min,y_max,x_max,y_max,x_max,y_min]],
"area": box_width,box_height,
"bbox": [x_min,y_min,box_width,box_height]

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants