def test_get_box_coord(self): """ Bounding box successfully returns the array of the box in coordinates version. """ box = BoundingBox(15, 16, 17, 18) self.assertEqual(box.get_box_coord(), [[15, 16], [32, 16], [15, 34], [32, 34]])
def _process_resource(self, image): """ Processes the specified image in order to get the bounding boxes for the faces. :param image: image resource pointing to a valid URI or containing the image content. If the image is not loaded but is pointing to a valid URI, this method will try to load the image from the URI in grayscale. :return: an array of bounding boxes """ image_content = self._get_loaded_image_content(image, as_gray=True) # The 1 in the second argument indicates that we should upsample the image # 1 time. This will make everything bigger and allow us to detect more # faces. detections = self.detector(image_content, 1) metadata_content = [] for i, d in enumerate(detections): bounding_box = BoundingBox(d.left(), d.top(), d.right() - d.left(), d.bottom() - d.top()) bounding_box.fit_in_size(image.get_size()) metadata_content.append(bounding_box) return metadata_content
def test_expand(self): """ Expansion of bounding box. """ box1 = BoundingBox(3, 3, 100, 100) box1.expand() # expand a default of 20% self.assertEqual( box1.get_box(), [-7, -7, 120, 120]) # If you see something weird here,
def test_intersection_with_other_boundingbox(self): """ Bounding box intersects itself with other bounding boxes. """ for rect_set in self.rect_sets: rect1 = rect_set[0] rect2 = rect_set[1] expectedArea = rect_set[2] expectedPercentage = rect_set[3] box1 = BoundingBox(*rect1) box2 = BoundingBox(*rect2) intersection = box1.intersect_with(box2) number_of_common_pixels = intersection.get_area() # Which one is the smaller rectangle? area_box1 = box1.get_area() area_box2 = box2.get_area() lesser_area = min(area_box1, area_box2) percentage = round((number_of_common_pixels / lesser_area) * 100, 2) self.assertEqual(number_of_common_pixels, expectedArea) self.assertEqual(percentage, expectedPercentage)
def test_apply_proportion(self): """ ProportionSizeNormalizer works correctly with proportions for bounding boxes """ bounding_boxes = [ BoundingBox(100, 100, 500, 500), BoundingBox(50, 100, 200, 500) ] normalizer = ProportionSizeNormalizer(0.5, 0.3) for bounding_box in bounding_boxes: result = normalizer.apply(bounding_box) result_should_be = [int(bounding_box.get_box()[0] * 0.5), int(bounding_box.get_box()[1] * 0.3), int(bounding_box.get_box()[2] * 0.5), int(bounding_box.get_box()[3] * 0.3)] self.assertEqual(result.get_box(), result_should_be)
def _process_resource(self, image): """ Processes the specified image in order to get the bounding boxes for the faces. :param image: image resource pointing to a valid URI or containing the image content. If the image is not loaded but is pointing to a valid URI, this method will try to load the image from the URI in grayscale. :return: an array of bounding boxes. """ image_content = self._get_loaded_image_content(image, as_gray=True) detections = self.detector.detectMultiScale(image_content, 1.3, 5) metadata_content = [] for (x, y, width, height) in detections: bounding_box = BoundingBox(int(x), int(y), int(width), int(height)) bounding_box.fit_in_size(image.get_size()) metadata_content.append(bounding_box) return metadata_content
def test_bounding_box_from_string(self): """ Create a bounding box from a string. """ bbox_string = "22,34,122,432" bbox = BoundingBox.from_string(bbox_string) self.assertEqual(bbox.get_box(), [22, 34, 122, 432]) bbox_string = "22, 34,122,432" bbox = BoundingBox.from_string(bbox_string) self.assertEqual(bbox.get_box(), [22, 34, 122, 432]) bbox_string = "22, 34, 122, 432" bbox = BoundingBox.from_string(bbox_string) self.assertEqual(bbox.get_box(), [22, 34, 122, 432]) bbox_string = " 22, 34, 122, 432 " bbox = BoundingBox.from_string(bbox_string) self.assertEqual(bbox.get_box(), [22, 34, 122, 432]) with self.assertRaises(Exception): bbox_string = "22,34,122 432" bbox = BoundingBox.from_string(bbox_string) with self.assertRaises(Exception): bbox_string = "22,34 122 432" bbox = BoundingBox.from_string(bbox_string)
def apply(self, bounding_box): """ Applies the resize normalizer to the specified bounding box. :param bounding_box: Bounding box to resize. :return: A bounding box clone resized """ box = bounding_box.get_box() return BoundingBox(int(box[0] * self.proportion_width), int(box[1] * self.proportion_height), int(box[2] * self.proportion_width), int(box[3] * self.proportion_height))
def test_get_components(self): """ Bounding box isolated components are accessible. """ box = BoundingBox(15, 16, 17, 18) self.assertEqual(box.get_x(), 15) self.assertEqual(box.get_y(), 16) self.assertEqual(box.get_width(), 17) self.assertEqual(box.get_height(), 18)
def _process_resource(self, image): """ Processes the specified image in order to get the bounding boxes for the faces. :param image: image resource pointing to a valid URI or containing the image content. If the image is not loaded but is pointing to a valid URI, this method will try to load the image from the URI in grayscale. :return: an array of bounding boxes """ # This is a required step because MTCNN has a limitation on the size it can process. # 1024x1024 is an affordable size for MTCNN. if image.get_size() > NORMALIZE_IMAGES_SIZE: normalized_image = self.size_normalizer.apply(image) proportions = [ x / y if y else 1 for x, y in zip(image.get_size(), normalized_image.get_size()) ] proportion_bbox_normalizer = ProportionSizeNormalizer(*proportions) else: normalized_image = image proportion_bbox_normalizer = None image_content = self._get_loaded_image_content(normalized_image, as_gray=False) detections, points = self.detector.detect_faces(image_content) metadata_content = [] for detection in detections: raw_bbox = list([int(x) for x in detection[:4]]) normalized_bounding_box = BoundingBox(raw_bbox[0], raw_bbox[1], raw_bbox[2] - raw_bbox[0], raw_bbox[3] - raw_bbox[1]) # Bounding boxes are relative to the normalized image. We need to resize them back to the original size if proportion_bbox_normalizer is not None: bounding_box = proportion_bbox_normalizer.apply( normalized_bounding_box) else: bounding_box = normalized_bounding_box bounding_box.fit_in_size(image.get_size()) metadata_content.append(bounding_box) return metadata_content
def _crop_by_bounding_box(image, bounding_box_text=None): """ Crops the image by the specified bounding box. If no bounding box is specified, the image will be returned without any filtering. :param image: image to crop. :param bounding_box_text: bounding box to crop by. None to disable cropping. :return: the image filtered or the original image in case the bounding box is None. """ if bounding_box_text is not None: try: bounding_box_text = BoundingBox.from_string(bounding_box_text) bounding_box_text.fit_in_size(image.get_size()) image = image.crop_image(bounding_box_text, "Cropped by boundingbox") except Exception as ex: raise InvalidRequest( "The bounding box format is not valid. " "Format must be: bounding_box=x,y,width,height") return image
def test_center(self): """ Bounding box knows its center point. """ box = BoundingBox(10, 10, 20, 20) self.assertEqual(box.get_center(), [20, 20])
def test_get_box(self): """ Bounding box successfully returns the array of the box dimensions. """ box = BoundingBox(15, 16, 17, 18) self.assertEqual(box.get_box(), [15, 16, 17, 18])
def test_fit_in_size(self): """ Bounding box is able to adapt itself to specified bounds. """ image_size = [300, 300] # Case1 all out of bounds box1 = BoundingBox(-1, -1, 302, 302) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [0, 0, 300, 300]) # Case2 top left out of bounds box1 = BoundingBox(-1, -1, 301, 301) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [0, 0, 300, 300]) # Case left out of bounds box1 = BoundingBox(-15, 10, 100, 100) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [0, 10, 85, 100]) # Case top out of bounds box1 = BoundingBox(15, -10, 100, 100) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [15, 0, 100, 90]) # Case width out of bounds box1 = BoundingBox(15, 0, 290, 100) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [15, 0, 285, 100]) # Case height out of bounds box1 = BoundingBox(15, 15, 200, 290) box1.fit_in_size(image_size) self.assertEqual(box1.get_box(), [15, 15, 200, 285])
def test_get_numpy_format(self): """ Bounding box numpy format is correct. """ box = BoundingBox(15, 16, 17, 18) self.assertEqual(box.get_numpy_format(), [16, 34, 15, 32])
def test_area(self): """ Bounding box knows its area. """ box = BoundingBox(10, 10, 20, 20) self.assertEqual(box.get_area(), 400)
def test_str(self): """ Bounding box describes itself correctly. """ box = BoundingBox(15, 16, 17, 18) self.assertEqual(box.__str__(), "[15, 16, 17, 18]")