Пример #1
0
def nms(classes,
        offsets,
        anchors,
        class_thresh=0.9,
        iou_thresh=0.2,
        is_soft=True):
    # get all non-zero (non-background) objects
    objects = np.argmax(classes, axis=1)
    nonbg = np.nonzero(objects)[0]
    #print("Candidate non bg: ", nonbg.size)

    indexes = []
    while True:
        scores = np.zeros((classes.shape[0], ))
        scores[nonbg] = np.amax(classes[nonbg], axis=1)
        score_idx = np.argmax(scores, axis=0)
        score_max = scores[score_idx]
        # print(score_max)
        nonbg = nonbg[nonbg != score_idx]
        if score_max < class_thresh:
            if nonbg.size == 0:
                break
            continue
        indexes.append(score_idx)
        score_anc = anchors[score_idx]
        score_off = offsets[score_idx][0:4]
        score_box = score_anc + score_off
        score_box = np.expand_dims(score_box, axis=0)
        nonbg_copy = np.copy(nonbg)
        for idx in nonbg_copy:
            anchor = anchors[idx]
            offset = offsets[idx][0:4]
            box = anchor + offset
            box = np.expand_dims(box, axis=0)
            iou = layer_utils.iou(box, score_box)[0][0]
            if iou >= iou_thresh:
                print(score_idx, "overlaps ", idx, "with iou ", iou)
                if is_soft:
                    iou = iou * iou
                    iou /= 0.5
                    classes[idx] *= math.exp(-iou)
                    print("Scaling...")
                else:
                    nonbg = nonbg[nonbg != idx]
                    print("Removing ...")

        if nonbg.size == 0:
            break

    scores = np.zeros((classes.shape[0], ))
    scores[indexes] = np.amax(classes[indexes], axis=1)
    print("Validated non bg: ", len(indexes))
    #if is_soft:
    #    print("Soft NMS")

    return objects, indexes, scores
Пример #2
0
    def __data_generation(self, keys):
        """Generate train data: images and 
        object detection ground truth labels 

        Arguments:
            keys (array): Randomly sampled keys
                (key is image filename)

        Returns:
            x (tensor): Batch images
            y (tensor): Batch classes, offsets, and masks
        """
        # train input data
        x = np.zeros((self.args.batch_size, *self.input_shape))
        dim = (self.args.batch_size, self.n_boxes, self.n_classes)
        # class ground truth
        gt_class = np.zeros(dim)
        dim = (self.args.batch_size, self.n_boxes, 4)
        # offsets ground truth
        gt_offset = np.zeros(dim)
        # masks of valid bounding boxes
        gt_mask = np.zeros(dim)

        for i, key in enumerate(keys):
            # images are assumed to be stored in self.args.data_path
            # key is the image filename 
            image_path = os.path.join(self.args.data_path, key)
            image = skimage.img_as_float(imread(image_path))
            # assign image to a batch index
            x[i] = image
            # a label entry is made of 4-dim bounding box coords
            # and 1-dim class label
            labels = self.dictionary[key]
            labels = np.array(labels)
            # 4 bounding box coords are 1st four items of labels
            # last item is object class label
            boxes = labels[:,0:-1]
            for index, feature_shape in enumerate(self.feature_shapes):
                # generate anchor boxes
                anchors = anchor_boxes(feature_shape,
                                       image.shape,
                                       index=index,
                                       n_layers=self.args.layers)
                # each feature layer has a row of anchor boxes
                anchors = np.reshape(anchors, [-1, 4])
                # compute IoU of each anchor box 
                # with respect to each bounding boxes
                iou = layer_utils.iou(anchors, boxes)

                # generate ground truth class, offsets & mask
                gt = get_gt_data(iou,
                                 n_classes=self.n_classes,
                                 anchors=anchors,
                                 labels=labels,
                                 normalize=self.args.normalize,
                                 threshold=self.args.threshold)
                gt_cls, gt_off, gt_msk = gt
                if index == 0:
                    cls = np.array(gt_cls)
                    off = np.array(gt_off)
                    msk = np.array(gt_msk)
                else:
                    cls = np.append(cls, gt_cls, axis=0)
                    off = np.append(off, gt_off, axis=0)
                    msk = np.append(msk, gt_msk, axis=0)

            gt_class[i] = cls
            gt_offset[i] = off
            gt_mask[i] = msk


        y = [gt_class, np.concatenate((gt_offset, gt_mask), axis=-1)]

        return x, y
Пример #3
0
    def __data_generation(self, keys):
        data_path = config.params['data_path']
        x = np.empty((self.batch_size, *self.input_shape))
        dim = (self.batch_size, self.n_boxes, self.n_classes)
        gt_class = np.empty(dim)
        dim = (self.batch_size, self.n_boxes, 4)
        gt_offset = np.empty(dim)
        gt_mask = np.empty(dim)

        for i, key in enumerate(keys):
            # images are assumed to be stored in config data_path
            # key is the image filename 
            image_path = os.path.join(data_path, key)
            image = skimage.img_as_float(imread(image_path))

            # if augment data is enabled
            if self.aug_data:
                image = self.apply_random_noise(image)
                image = self.apply_random_intensity_rescale(image)
                image = self.apply_random_exposure_adjust(image)

            x[i] = image
            labels = self.dictionary[key]
            labels = np.array(labels)
            # 4 boxes coords are 1st four items of labels
            boxes = labels[:,0:-1]
            for index, shape in enumerate(self.feature_shapes):
                shape = (1, *shape)
                # generate anchor boxes
                anchors = anchor_boxes(shape,
                                       image.shape,
                                       index=index,
                                       n_layers=self.n_layers)
                anchors = np.reshape(anchors, [-1, 4])
                # compute IoU of each anchor box 
                # with respect to each bounding boxes
                iou = layer_utils.iou(anchors, boxes)

                # generate ground truth class and offsets
                ret = get_gt_data(iou,
                                  n_classes=self.n_classes,
                                  anchors=anchors,
                                  labels=labels,
                                  normalize=self.normalize)
                gt_cls, gt_off, gt_msk = ret
                if index == 0:
                    cls = np.array(gt_cls)
                    off = np.array(gt_off)
                    msk = np.array(gt_msk)
                else:
                    cls = np.append(cls, gt_cls, axis=0)
                    off = np.append(off, gt_off, axis=0)
                    msk = np.append(msk, gt_msk, axis=0)

            gt_class[i] = cls
            gt_offset[i] = off
            gt_mask[i] = msk


        y = [gt_class, np.concatenate((gt_offset, gt_mask), axis=-1)]

        return x, y
Пример #4
0
def nms(args, classes, offsets, anchors):
    """Perform NMS (Algorithm 11.12.1).
    Arguments:
        args : User-defined configurations
        classes (tensor): Predicted classes
        offsets (tensor): Predicted offsets
        
    Returns:
        objects (tensor): class predictions per anchor
        indexes (tensor): indexes of detected objects
            filtered by NMS
        scores (tensor): array of detected objects scores
            filtered by NMS
    """

    # get all non-zero (non-background) objects
    objects = np.argmax(classes, axis=1)
    # non-zero indexes are not background
    nonbg = np.nonzero(objects)[0]

    # D and S indexes in Line 1
    indexes = []
    while True:
        # list of zero probability values
        scores = np.zeros((classes.shape[0], ))
        # set probability values of non-background
        scores[nonbg] = np.amax(classes[nonbg], axis=1)

        # max probability given the list
        # Lines 3 and 4
        score_idx = np.argmax(scores, axis=0)
        score_max = scores[score_idx]

        # get all non max probability & set it as new nonbg
        # Line 5
        nonbg = nonbg[nonbg != score_idx]

        # if max obj probability is less than threshold (def 0.8)
        if score_max < args.class_threshold:
            # we are done
            break

        # Line 5
        indexes.append(score_idx)
        score_anc = anchors[score_idx]
        score_off = offsets[score_idx][0:4]
        score_box = score_anc + score_off
        score_box = np.expand_dims(score_box, axis=0)
        nonbg_copy = np.copy(nonbg)

        # get all overlapping predictions (Line 6)
        # perform Non-Max Suppression (NMS)
        for idx in nonbg_copy:
            anchor = anchors[idx]
            offset = offsets[idx][0:4]
            box = anchor + offset
            box = np.expand_dims(box, axis=0)
            iou = layer_utils.iou(box, score_box)[0][0]
            # if soft NMS is chosen (Line 7)
            if args.soft_nms:
                # adjust score: Line 8
                iou = -2 * iou * iou
                classes[idx] *= math.exp(iou)
            # else NMS (Line 9), (iou threshold def 0.2)
            elif iou >= args.iou_threshold:
                # remove overlapping predictions with iou>threshold
                # Line 10
                nonbg = nonbg[nonbg != idx]

        # Line 2, nothing else to process
        if nonbg.size == 0:
            break

    # get the array of object scores
    scores = np.zeros((classes.shape[0], ))
    scores[indexes] = np.amax(classes[indexes], axis=1)

    return objects, indexes, scores
Пример #5
0
def nms(classes, offsets, anchors):

    class_thresh = config.params['class_thresh']
    iou_thresh = config.params['iou_thresh']
    is_soft = config.params['is_soft_nms']

    # get all non-zero (non-background) objects
    objects = np.argmax(classes, axis=1)
    # non-zero indexes are not background
    nonbg = np.nonzero(objects)[0]
    #print("Candidate non bg: ", nonbg.size)

    indexes = []
    while True:
        # list of zero probability values
        scores = np.zeros((classes.shape[0], ))
        # set probability values of non-background
        scores[nonbg] = np.amax(classes[nonbg], axis=1)

        # max probability given the list
        score_idx = np.argmax(scores, axis=0)
        score_max = scores[score_idx]
        # print(score_max)

        # get all non max probability & set it as new nonbg
        nonbg = nonbg[nonbg != score_idx]

        # if obj probability is less than threshold
        if score_max < class_thresh:
            # we are done
            break

        indexes.append(score_idx)
        score_anc = anchors[score_idx]
        score_off = offsets[score_idx][0:4]
        score_box = score_anc + score_off
        score_box = np.expand_dims(score_box, axis=0)
        nonbg_copy = np.copy(nonbg)

        # get all overlapping predictions
        for idx in nonbg_copy:
            anchor = anchors[idx]
            offset = offsets[idx][0:4]
            box = anchor + offset
            box = np.expand_dims(box, axis=0)
            iou = layer_utils.iou(box, score_box)[0][0]
            if is_soft:
                iou = -2 * iou * iou
                classes[idx] *= math.exp(iou)
                #print("Soft NMS scaling ...", idx)
            elif iou >= iou_thresh:
                #print(score_idx, "overlaps ", idx, "with iou ", iou)
                nonbg = nonbg[nonbg != idx]
                #print("NMS Removing ...", idx)

        if nonbg.size == 0:
            break

    scores = np.zeros((classes.shape[0], ))
    scores[indexes] = np.amax(classes[indexes], axis=1)

    return objects, indexes, scores
Пример #6
0
    def evaluate_test(self):
        # test labels csv path
        path = os.path.join(self.args.data_path,
                            self.args.test_labels)
        # test dictionary
        dictionary, _ = build_label_dictionary(path)
        keys = np.array(list(dictionary.keys()))
        # sum of precision
        s_precision = 0
        # sum of recall
        s_recall = 0
        # sum of IoUs
        s_iou = 0
        # evaluate per image
        for key in keys:
            # grounnd truth labels
            labels = np.array(dictionary[key])
            # 4 boxes coords are 1st four items of labels
            gt_boxes = labels[:, 0:-1]
            # last one is class
            gt_class_ids = labels[:, -1]
            # load image id by key
            image_file = os.path.join(self.args.data_path, key)
            image = skimage.img_as_float(imread(image_file))
            image, classes, offsets = self.detect_objects(image)
            # perform nms
            _, _, class_ids, boxes = show_boxes(args,
                                                image,
                                                classes,
                                                offsets,
                                                self.feature_shapes,
                                                show=False)

            boxes = np.reshape(np.array(boxes), (-1,4))
            # compute IoUs
            iou = layer_utils.iou(gt_boxes, boxes)
            # skip empty IoUs
            if iou.size ==0:
                continue
            # the class of predicted box w/ max iou
            maxiou_class = np.argmax(iou, axis=1)

            # true positive
            tp = 0
            # false positiove
            fp = 0
            # sum of objects iou per image
            s_image_iou = []
            for n in range(iou.shape[0]):
                # ground truth bbox has a label
                if iou[n, maxiou_class[n]] > 0:
                    s_image_iou.append(iou[n, maxiou_class[n]])
                    # true positive has the same class and gt
                    if gt_class_ids[n] == class_ids[maxiou_class[n]]:
                        tp += 1
                    else:
                        fp += 1

            # objects that we missed (false negative)
            fn = abs(len(gt_class_ids) - tp)
            s_iou += (np.sum(s_image_iou) / iou.shape[0])
            s_precision += (tp/(tp + fp))
            s_recall += (tp/(tp + fn))


        n_test = len(keys)
        print_log("mIoU: %f" % (s_iou/n_test),
                  self.args.verbose)
        print_log("Precision: %f" % (s_precision/n_test),
                  self.args.verbose)
        print_log("Recall : %f" % (s_recall/n_test),
                  self.args.verbose)
Пример #7
0
    def evaluate_test(self):
        csv_path = os.path.join(config.params['data_path'],
                                config.params['test_labels'])
        print("CSV", csv_path)
        dictionary, _ = build_label_dictionary(csv_path)
        keys = np.array(list(dictionary.keys()))
        n_iou = 0
        s_iou = 0
        i = 0
        tp = 0
        fp = 0
        for key in keys:
            labels = dictionary[key]
            labels = np.array(labels)
            # 4 boxes coords are 1st four items of labels
            gt_boxes = labels[:, 0:-1]
            gt_class_ids = labels[:, -1]
            image_file = os.path.join(config.params['data_path'], key)
            print("Image: ", image_file)
            image = skimage.img_as_float(imread(image_file))
            image = np.expand_dims(image, axis=0)
            classes, offsets = self.ssd.predict(image)
            image = np.squeeze(image, axis=0)
            classes = np.squeeze(classes)
            offsets = np.squeeze(offsets)
            _, _, class_ids, boxes = show_boxes(image,
                                                classes,
                                                offsets,
                                                self.feature_shapes,
                                                show=False,
                                                normalize=self.normalize)

            boxes = np.reshape(np.array(boxes), (-1, 4))
            iou = layer_utils.iou(gt_boxes, boxes)
            if iou.size == 0:
                continue
            print("--------------")
            print("gt:", gt_class_ids, gt_boxes)
            print("iou w/ gt:", iou)
            print("iou shape:", iou.shape)
            maxiou_class = np.argmax(iou, axis=1)
            print("classes: ", maxiou_class)
            n = iou.shape[0]
            n_iou += n
            s = []
            for j in range(n):
                s.append(iou[j, maxiou_class[j]])
                if gt_class_ids[j] == class_ids[maxiou_class[j]]:
                    tp += 1
                else:
                    fp += 1

            fp += abs(len(class_ids) - len(gt_class_ids))
            print("max ious: ", s)
            s = np.sum(s)
            s_iou += s
            print("pred:", class_ids, boxes)

            print("--------------")
            # i += 1
            #if i==10:
            #    break

        print("sum:", s_iou)
        print("num:", n_iou)
        print("mIoU:", s_iou / n_iou)
        print("tp:", tp)
        print("fp:", fp)
        print("precision:", tp / (tp + fp))