YoloV3 коробка для подарков слишком большая - PullRequest
1 голос
/ 11 апреля 2019

Я тренирую сеть yolo, чтобы выявлять футбольный мяч, узнавать больше и лучше понимать эту архитектуру Я могу обнаружить мяч в большинстве случаев. Моя проблема здесь в том, что сгенерированный прямоугольник слишком большой, покрывая гораздо больше пикселей, чем реальный шар.

Я знаю, что якоря параметров влияют на будущие коробки. Я экспериментировал с несколькими значениями конфигурации, а также пробовал код для генерации якорей. Якоря, генерируемые кодом, слишком малы, и часто мы даже не видим поле, только заголовок. Я также думал, что это не лучший подход к решению проблемы одного класса, потому что мы используем k-средства для генерации этих якорей. Когда я пытался изменить значения, область покрытия была совершенно неправильной, но поле было действительно маленьким, охватывая меньше, чем исходные якоря.

Вот мой код для генерации якорей. Я удалил некоторые методы, чтобы сделать код более чистым.


    def __init__(self, dir_images, dir_labels, width = 416, height = 416, anchors = 9):
        # dir_images: Directory that contains all images that will be used or
        # already has used to training the neural network
        # Example: /home/enacom/Desktop/darknet_football_resized_images/

        #dir_labels: Directory that contains all labels that will be used or]
        # already has used to training the neural network
        # Example: /home/enacom/Desktop/BBoxLabelTool/Images/labels6/

        # anchors: the number of anchor that you desire
        # default value is 9 on yoloV3, but you can add more if want detect more objects
        self.dir_images = dir_images
        self.dir_labels = dir_labels
        self.grid_w = width/32
        self.grid_h = height/32
        self.anchors = anchors
        self.annotation_dims = []

        file_list = os.listdir(self.dir_images)
        boxes = self.__read_labels()

        for file in file_list:
            actual_dir = self.dir_images + file
            try:
                image = cv2.imread(actual_dir)
                width, height = image.shape[:2]
                cell_w = width / self.grid_w
                cell_h = height / self.grid_h
                box = boxes[file.replace("jpg", "txt")]
                relative_w = (float(box[0][2]) - float(box[0][0])) # / cell_w
                relatice_h = (float(box[0][3]) - float(box[0][1])) # / cell_h
                self.annotation_dims.append(tuple(map(float, (relative_w,relatice_h))))

            except AttributeError:
                print("Failure when reading image")

        self.annotation_dims = np.array(self.annotation_dims)
        print(self.annotation_dims / 32)

    def IOU(self, ann, centroids):
        w, h = ann
        similarities = []

        for centroid in centroids:
            c_w, c_h = centroid

            if c_w >= w and c_h >= h:
                similarity = w * h / (c_w * c_h)
            elif c_w >= w and c_h <= h:
                similarity = w * c_h / (w * h + (c_w - w) * c_h)
            elif c_w <= w and c_h >= h:
                similarity = c_w * h / (w * h + c_w * (c_h - h))
            else:  # means both w,h are bigger than c_w and c_h respectively
                similarity = (c_w * c_h) / (w * h)
            similarities.append(similarity)  # will become (k,) shape

        return np.array(similarities)

    def run_kmeans(self):
        ann_num = self.annotation_dims.shape[0]
        iterations = 0
        prev_assignments = np.ones(ann_num) * (-1)
        iteration = 0
        old_distances = np.zeros((ann_num, self.anchors))

        indices = [random.randrange(self.annotation_dims.shape[0]) for i in range(self.anchors)]
        centroids = self.annotation_dims[indices]
        anchor_dim = self.annotation_dims.shape[1]

        while True:
            distances = []
            iteration += 1
            for i in range(ann_num):
                d = 1 - self.IOU(self.annotation_dims[i], centroids)
                distances.append(d)
            distances = np.array(distances)  # distances.shape = (ann_num, anchor_num)

            print("iteration {}: dists = {}".format(iteration, np.sum(np.abs(old_distances - distances))))

            # assign samples to centroids
            assignments = np.argmin(distances, axis=1)

            if (assignments == prev_assignments).all():
                return centroids

            # calculate new centroids
            centroid_sums = np.zeros((self.anchors, anchor_dim), np.float)
            for i in range(ann_num):
                centroid_sums[assignments[i]] += self.annotation_dims[i]
            for j in range(self.anchors):
                centroids[j] = centroid_sums[j] / (np.sum(assignments == j) + 1e-6)

            prev_assignments = assignments.copy()

            old_distances = distances.copy()


a = AnchorGenerator("/home/myDir/Desktop/BBoxLabelTool/Images/5_images_clean/",
                    "/home/myDir/Desktop/BBoxLabelTool/Labels/005/",
                    anchors = 9)

centroids = a.run_kmeans()
a.print_anchors(centroids)

Результат с оригинальными якорями: https://imgur.com/a/5OhiTfl Результат с созданными моими якорями: https://imgur.com/a/YCW2aam В случае созданного вручную якоря, это близко, чтобы быть правым, но я не знаю, как сделать это более точно. Это якоря, которые я использовал, которые генерируют этот результат.

anchors = 3,1, 7,4 5,5, 12,12, 15,15, 16,16, 18,17
...