Exemple #1
0
    def Resize(it):
        """
        Resizes images according to the resize dimensions
        image: (array) Image
        resize: (tuple of integers) New dimensions
        target: (Dictionary) Containing BBox, Area, Labels and Index

        Returns normalized_image, target
        """
        image, target = it
        resize = res
        new_target = target.copy()
        bbs = BoundingBoxesOnImage([
            BoundingBox(x1=new_target['boxes'][0].item(),
                        y1=new_target['boxes'][1].item(),
                        x2=new_target['boxes'][2].item(),
                        y2=new_target['boxes'][3].item())
        ], image.shape)
        img = ia.imresize_single_image(np.array(image), resize)
        new_bbs = bbs.on(img)
        bbox = torch.tensor(
            [new_bbs[0].x1, new_bbs[0].y1, new_bbs[0].x2, new_bbs[0].y2])
        new_target['area'] = torch.tensor([
            (new_bbs[0].x2 - new_bbs[0].x1) * (new_bbs[0].y2 - new_bbs[0].y1)
        ])
        new_target['boxes'] = bbox.unsqueeze(0)
        return img, [new_target]
def chapter_examples_bounding_boxes_projection():
    import imgaug as ia
    from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage

    ia.seed(1)

    # Define image with two bounding boxes
    image = ia.quokka(size=(256, 256))
    bbs = BoundingBoxesOnImage([
        BoundingBox(x1=25, x2=75, y1=25, y2=75),
        BoundingBox(x1=100, x2=150, y1=25, y2=75)
    ],
                               shape=image.shape)

    # Rescale image and bounding boxes
    image_rescaled = ia.imresize_single_image(image, (512, 512))
    bbs_rescaled = bbs.on(image_rescaled)

    # Draw image before/after rescaling and with rescaled bounding boxes
    image_bbs = bbs.draw_on_image(image, size=2)
    image_rescaled_bbs = bbs_rescaled.draw_on_image(image_rescaled, size=2)

    # ------------

    save("examples_bounding_boxes",
         "projection.jpg",
         grid([image_bbs, image_rescaled_bbs], cols=2, rows=1),
         quality=90)
Exemple #3
0
def quokka_bounding_boxes(size=None, extract=None):
    """Return example bounding boxes on the standard example quokke image.

    Currently only a single bounding box is returned that covers the quokka.

    Added in 0.5.0. (Moved from ``imgaug.imgaug``.)

    Parameters
    ----------
    size : None or float or tuple of int or tuple of float, optional
        Size of the output image on which the BBs are placed. If ``None``, then
        the BBs are not projected to any new size (positions on the original
        image are used). ``float`` s lead to relative size changes, ``int`` s
        to absolute sizes in pixels.

    extract : None or 'square' or tuple of number or imgaug.augmentables.bbs.BoundingBox or imgaug.augmentables.bbs.BoundingBoxesOnImage
        Subarea to extract from the image. See :func:`~imgaug.imgaug.quokka`.

    Returns
    -------
    imgaug.augmentables.bbs.BoundingBoxesOnImage
        Example BBs on the quokka image.

    """
    # TODO get rid of this deferred import
    from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage

    left, top = 0, 0
    if extract is not None:
        bb_extract = _quokka_normalize_extract(extract)
        left = bb_extract.x1
        top = bb_extract.y1
    with open(_QUOKKA_ANNOTATIONS_FP, "r") as f:
        json_dict = json.load(f)
    bbs = []
    for bb_dict in json_dict["bounding_boxes"]:
        bbs.append(
            BoundingBox(
                x1=bb_dict["x1"] - left,
                y1=bb_dict["y1"] - top,
                x2=bb_dict["x2"] - left,
                y2=bb_dict["y2"] - top
            )
        )
    if extract is not None:
        shape = (bb_extract.height, bb_extract.width, 3)
    else:
        shape = (643, 960, 3)
    bbsoi = BoundingBoxesOnImage(bbs, shape=shape)
    if size is not None:
        shape_resized = _compute_resized_shape(shape, size)
        bbsoi = bbsoi.on(shape_resized)
    return bbsoi
Exemple #4
0
def augment_image_and_bboxes(
    image: np.ndarray,
    cutouts: Union[List[Tuple[float]], np.ndarray, None],
    proposal_boxes: Union[List[Tuple[float]], np.ndarray, None],
    angle: Optional[Union[float, int]],
    new_size: Optional[Union[int, Tuple[int]]],
    verbose: bool = False,
) -> Tuple[Any, Union[List[Tuple[float]], np.ndarray], np.ndarray]:
    bounding_boxes = []
    prop_boxes = []
    seg_boxes = []
    new_size = image.shape[0]
    new_crop = int(
        np.ceil(image.shape[0])
    )  # Is 200 for 282, which is what is wanted, and works for others
    seq = iaa.Sequential([
        iaa.Affine(rotate=angle),
        iaa.CropToFixedSize(width=new_crop, height=new_crop,
                            position="center"),
    ])
    for cutout in cutouts:
        bounding_boxes.append(
            BoundingBox(cutout[1] + 0.5, cutout[0] + 0.5, cutout[3] + 0.5,
                        cutout[2] + 0.5))
    for pbox in proposal_boxes:
        prop_boxes.append(
            BoundingBox(pbox[1] + 0.5, pbox[0] + 0.5, pbox[3] + 0.5,
                        pbox[2] + 0.5))

    bbs = BoundingBoxesOnImage(bounding_boxes, shape=image.shape)
    pbbs = BoundingBoxesOnImage(prop_boxes, shape=image.shape)
    if seg_boxes:
        sbbs = BoundingBoxesOnImage(seg_boxes, shape=image.shape)
        _, sbbs = seq(image=image, bounding_boxes=sbbs)
    _, bbs = seq(image=image, bounding_boxes=bbs)
    image, pbbs = seq(image=image, bounding_boxes=pbbs)
    # Rescale image and bounding boxes
    if type(new_size) == int:
        image_rescaled = ia.imresize_single_image(image, (new_size, new_size))
    else:
        image_rescaled = ia.imresize_single_image(
            image, (image.shape[0], image.shape[1]))
    bbs_rescaled = bbs.on(image_rescaled)
    pbbs_rescaled = pbbs.on(image_rescaled)
    if seg_boxes:
        sbbs_rescaled = sbbs.on(image_rescaled)
        sbbs_rescaled = sbbs_rescaled.remove_out_of_image(
            partly=False).clip_out_of_image()

    # Remove bounding boxes that go out of bounds
    pbbs_rescaled = pbbs_rescaled.remove_out_of_image(
        partly=False).clip_out_of_image()
    # But only clip source bounding boxes that are partly out of frame, so that no sources are lost
    bbs_rescaled = bbs_rescaled.remove_out_of_image(
        partly=False).clip_out_of_image()
    # Also remove those and clip of segmentation maps
    for index, bbox in enumerate(bbs_rescaled):
        cutouts[index][0] = bbox.x1
        cutouts[index][1] = bbox.y1
        cutouts[index][2] = bbox.x2
        cutouts[index][3] = bbox.y2
    # Convert proposal boxes as well
    pbs = []
    for index, bbox in enumerate(pbbs_rescaled):
        pbs.append(np.asarray((bbox.x1, bbox.y1, bbox.x2, bbox.y2)))
    pbs = np.asarray(pbs)
    sbs = []
    try:
        for index, bbox in enumerate(sbbs_rescaled):
            sbs.append(np.asarray((bbox.x1, bbox.y1, bbox.x2, bbox.y2)))
    except:
        if verbose:
            print("Empty sbbs_rescaled")
    sbs = np.asarray(sbs)
    return image_rescaled, cutouts, pbs
Exemple #5
0
def get_random_data_1(annotation_line,
                      input_shape,
                      random=True,
                      max_boxes=20,
                      jitter=.3,
                      hue=.1,
                      sat=1.5,
                      val=1.5,
                      proc_img=True):
    '''random preprocessing for real-time data augmentation'''
    line = annotation_line.split()
    image = Image.open(line[0])
    iw, ih = image.size
    h, w = input_shape
    box = np.array(
        [np.array(list(map(int, box.split(',')))) for box in line[1:]])

    if not random:
        # resize image
        scale = min(w / iw, h / ih)
        nw = int(iw * scale)
        nh = int(ih * scale)
        dx = (w - nw) // 2
        dy = (h - nh) // 2
        image_data = 0
        if proc_img:
            image = image.resize((nw, nh), Image.BICUBIC)
            new_image = Image.new('RGB', (w, h), (128, 128, 128))
            new_image.paste(image, (dx, dy))
            image_data = np.array(new_image) / 255.

        # correct boxes
        box_data = np.zeros((max_boxes, 5))
        if len(box) > 0:
            np.random.shuffle(box)
            if len(box) > max_boxes: box = box[:max_boxes]
            box[:, [0, 2]] = box[:, [0, 2]] * scale + dx
            box[:, [1, 3]] = box[:, [1, 3]] * scale + dy
            box_data[:len(box)] = box

        return image_data, box_data

    img_data = np.array(image)
    bbs = BoundingBoxesOnImage(
        [BoundingBox(x1, y1, x2, y2, label) for x1, y1, x2, y2, label in box],
        shape=img_data.shape)
    image = np.array(image)
    image_rescaled = ia.imresize_single_image(image, input_shape)
    bbs_rescaled = bbs.on(image_rescaled)

    shaped_img, shaped_bbx = seq(image=image_rescaled,
                                 bounding_boxes=bbs_rescaled)
    # boxed = shaped_bbx.draw_on_image(shaped_img)
    shaped_bbx = [[x.x1, x.y1, x.x2, x.y2, x.label]
                  for x in bbs_rescaled.bounding_boxes]
    box = np.array(shaped_bbx)
    box_data = np.zeros((max_boxes, 5))
    if len(box) > 0:
        np.random.shuffle(box)
        if len(box) > max_boxes: box = box[:max_boxes]
        box[:, [0, 2]] = box[:, [0, 2]]
        box[:, [1, 3]] = box[:, [1, 3]]
        box_data[:len(box)] = box
    return shaped_img, box_data
Exemple #6
0
    def __getitem__(self, index):
        """
        Returns
        - path: (str) Image filename
        - img: (Tensor)
        - annos: (Tensor) Annotation with size [100, 5]
            5 = [xc, yc, w, h, label]
        """
        coco = self.coco
        img_id = self.ids[index]
        ann_ids = coco.getAnnIds(imgIds=img_id)
        path = coco.loadImgs(img_id)[0]['file_name']
        img = Image.open(os.path.join(self.root, path)).convert('RGB')
        w, h = img.size
        target = coco.loadAnns(ann_ids)
        annos = torch.zeros(len(target), 5)

        # if self.reso is None, skip the whole image augmentation part.
        # Apply image augmentations before coordinate conversion, resizing and toTensor transform.
        if self.reso is not None:
            #Convert image to numpy array
            img = np.array(img)

            # Get all the annotations (bboxes)
            bboxes = []
            for i in range(len(target)):
                bbox = torch.Tensor(target[i]['bbox'])
                bbox_x = bbox[0]
                bbox_y = bbox[1]
                bbox_w = bbox[2]
                bbox_h = bbox[3]
                bboxes.append(
                    BoundingBox(x1=bbox_x,
                                y1=bbox_y,
                                x2=bbox_x + bbox_w,
                                y2=bbox_y + bbox_h))
            bbs = BoundingBoxesOnImage(bboxes, shape=img.shape)

            # NOTE: resize first, otherwise rotating will crop the image (since image is not square)
            # Rescale image and bounding boxes
            img = ia.imresize_single_image(img, (self.reso, self.reso))
            bbs = bbs.on(img)

            # Define augmentations
            seq = iaa.Sequential([
                iaa.ChangeColorspace(from_colorspace="RGB",
                                     to_colorspace="HSV"),
                iaa.WithChannels(1, iaa.Add((-50, 50))),  # Change saturation
                iaa.WithChannels(2, iaa.Add((-50, 50))),  # Change intensity
                iaa.ChangeColorspace(from_colorspace="HSV",
                                     to_colorspace="RGB"),
                iaa.Sometimes(
                    0.5,
                    iaa.Affine(rotate=90)),  # Rotate 90 deg. (0.5 probability)
                iaa.Affine(shear=(-2, 2)),  # Shear (-2 +2 degrees)
                iaa.Flipud(0.5),  # Flip up-down (with 0.5 probability)
                iaa.Fliplr(0.5)  # Flip left-right (with 0.5 probability)
            ])

            img_aug, bbs_aug = seq(image=img, bounding_boxes=bbs)

            # # DEBUG: output image
            # image_after = bbs_aug.draw_on_image(img_aug)
            # # Convert numpy array to PIL image
            # image_after = Image.fromarray(image_after, 'RGB')
            # image_after.save('debug.png')
            # print(path)
            # print("DEBUG IMAGE SAVED")
            # print(bbox)
            # print(bbs_aug)
            # # sys.exit(0)

            # Overwrite original image
            img = img_aug

        for i in range(len(target)):
            # [x1, y1, w, h] => [xc, yc, w, h]

            # if self.reso is not None it means we have to update the bounding boxes coordinates
            if self.reso is not None:
                bbox = []
                bbox.append(int(bbs_aug.bounding_boxes[i].x1))
                bbox.append(int(bbs_aug.bounding_boxes[i].y1))
                bbox.append(
                    int(bbs_aug.bounding_boxes[i].x2) -
                    int(bbs_aug.bounding_boxes[i].x1))
                bbox.append(
                    int(bbs_aug.bounding_boxes[i].y2) -
                    int(bbs_aug.bounding_boxes[i].y1))
                bbox = torch.Tensor(bbox)
                w = self.reso
                h = self.reso
                # print(bbox)
                # print()
            else:
                bbox = torch.Tensor(target[i]['bbox'])

            annos[i, 0] = (bbox[0] + bbox[2] / 2) / w
            annos[i, 1] = (bbox[1] + bbox[3] / 2) / h
            annos[i, 2] = bbox[2] / w
            annos[i, 3] = bbox[3] / h
            annos[i, 4] = self.class_map[int(target[i]['category_id'])]

        #if self.transform is not None:
        #    img = self.transform(img)

        # ndarray -> Tensor conversion
        img = torch.from_numpy(img.transpose((2, 0, 1)).copy())
        if isinstance(img, torch.ByteTensor):
            img = img.float().div(255)

        return path, img, annos