Example #1
0
    def test_shape_outline(self):
        """Test the shape:outline feature."""
        path = IMAGES_RECTANGLE[2]
        k = 20

        # Object width and height.
        w, h = (300, 100)

        im_path = os.path.join(self.base_dir, path)
        img = cv2.imread(im_path)
        if img == None or img.size == 0:
            raise SystemError("Failed to read %s" % im_path)

        # Perform segmentation.
        mask = grabcut(img, 1, None, 1)
        bin_mask = np.where((mask == cv2.GC_FGD) + (mask == cv2.GC_PR_FGD),
                            255, 0).astype('uint8')

        # Obtain contours (all points) from the mask.
        contour = ft.get_largest_contour(bin_mask.copy(), cv2.RETR_EXTERNAL,
                                         cv2.CHAIN_APPROX_NONE)

        # Get the outline.
        outline = ft.shape_outline(contour, k)

        # Assert the length of the return value.
        self.assertEqual(len(outline), k)

        # Assert the shape values.
        for x, y in outline:
            delta_x = x[0] - x[1]
            delta_y = y[0] - y[1]
            self.assertLess(error(delta_y, h, mape), 0.0001)
            self.assertLess(error(delta_x, w, mape), 0.0001)
Example #2
0
    def test_shape_outline(self):
        """Test the shape:outline feature."""
        path = IMAGES_RECTANGLE[2]
        k = 20

        # Object width and height.
        w, h = (300, 100)

        im_path = os.path.join(self.base_dir, path)
        img = cv2.imread(im_path)
        if img == None or img.size == 0:
            raise SystemError("Failed to read %s" % im_path)

        # Perform segmentation.
        mask = grabcut(img, 1, None, 1)
        bin_mask = np.where((mask==cv2.GC_FGD) + (mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')

        # Obtain contours (all points) from the mask.
        contour = ft.get_largest_contour(bin_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

        # Get the outline.
        outline = ft.shape_outline(contour, k)

        # Assert the length of the return value.
        self.assertEqual( len(outline), k )

        # Assert the shape values.
        for x, y in outline:
            delta_x = x[0] - x[1]
            delta_y = y[0] - y[1]
            self.assertLess( error(delta_y, h, mape), 0.0001 )
            self.assertLess( error(delta_x, w, mape), 0.0001 )
Example #3
0
    def test_shape_360(self):
        """Test the shape:360 feature.

        Extracts the shape from two slightly rotated versions of the same
        image. Then the medium square error between the two extracted shapes is
        calculated and checked.
        """
        max_error = 0.05

        shape = []
        for i, path in enumerate(IMAGES_ERYCINA):
            im_path = os.path.join(self.base_dir, path)
            img = cv2.imread(im_path)
            if img == None or img.size == 0:
                raise SystemError("Failed to read %s" % im_path)

            # Resize the image if it is larger then the threshold.
            img = scale_max_perimeter(img, MAX_SIZE)

            # Perform segmentation.
            mask = grabcut(img, 5, None, 1)

            # Create a binary mask. Foreground is made white, background black.
            bin_mask = np.where((mask == cv2.GC_FGD) + (mask == cv2.GC_PR_FGD),
                                255, 0).astype('uint8')

            # Obtain contours (all points) from the mask.
            contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL,
                                             cv2.CHAIN_APPROX_NONE)

            # Fit an ellipse on the contour to get the rotation angle.
            box = cv2.fitEllipse(contour)
            rotation = int(box[2])

            # Extract the shape.
            intersects, center = ft.shape_360(contour, rotation)

            # For each angle save the mean distance from center to contour and
            # the standard deviation for the distances.
            means = []
            sds = []
            for angle in range(0, 360):
                distances = []
                for p in intersects[angle]:
                    d = ft.point_dist(center, p)
                    distances.append(d)

                if len(distances) == 0:
                    mean = 0
                    sd = 0
                else:
                    mean = np.mean(distances, dtype=np.float32)
                    if len(distances) > 1:
                        sd = np.std(distances, ddof=1, dtype=np.float32)
                    else:
                        sd = 0

                means.append(mean)
                sds.append(sd)

            # Normalize and save result.
            means = cv2.normalize(np.array(means), None, -1, 1,
                                  cv2.NORM_MINMAX)
            sds = cv2.normalize(np.array(sds), None, -1, 1, cv2.NORM_MINMAX)
            shape.append([means, sds])

        # Check the medium square error for the means.
        self.assertLess(error(shape[0][0].ravel(), shape[1][0].ravel(), mse),
                        max_error)

        # Check the medium square error for the standard deviations.
        self.assertLess(error(shape[0][1].ravel(), shape[1][1].ravel(), mse),
                        max_error)
Example #4
0
    def test_shape_360(self):
        """Test the shape:360 feature.

        Extracts the shape from two slightly rotated versions of the same
        image. Then the medium square error between the two extracted shapes is
        calculated and checked.
        """
        max_error = 0.05

        shape = []
        for i, path in enumerate(IMAGES_ERYCINA):
            im_path = os.path.join(self.base_dir, path)
            img = cv2.imread(im_path)
            if img == None or img.size == 0:
                raise SystemError("Failed to read %s" % im_path)

            # Resize the image if it is larger then the threshold.
            img = scale_max_perimeter(img, MAX_SIZE)

            # Perform segmentation.
            mask = grabcut(img, 5, None, 1)

            # Create a binary mask. Foreground is made white, background black.
            bin_mask = np.where((mask==cv2.GC_FGD) + (mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')

            # Obtain contours (all points) from the mask.
            contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

            # Fit an ellipse on the contour to get the rotation angle.
            box = cv2.fitEllipse(contour)
            rotation = int(box[2])

            # Extract the shape.
            intersects, center = ft.shape_360(contour, rotation)

            # For each angle save the mean distance from center to contour and
            # the standard deviation for the distances.
            means = []
            sds = []
            for angle in range(0, 360):
                distances = []
                for p in intersects[angle]:
                    d = ft.point_dist(center, p)
                    distances.append(d)

                if len(distances) == 0:
                    mean = 0
                    sd = 0
                else:
                    mean = np.mean(distances, dtype=np.float32)
                    if len(distances) > 1:
                        sd = np.std(distances, ddof=1, dtype=np.float32)
                    else:
                        sd = 0

                means.append(mean)
                sds.append(sd)

            # Normalize and save result.
            means = cv2.normalize(np.array(means), None, -1, 1, cv2.NORM_MINMAX)
            sds = cv2.normalize(np.array(sds), None, -1, 1, cv2.NORM_MINMAX)
            shape.append([means, sds])

        # Check the medium square error for the means.
        self.assertLess(error(shape[0][0].ravel(), shape[1][0].ravel(), mse), max_error)

        # Check the medium square error for the standard deviations.
        self.assertLess(error(shape[0][1].ravel(), shape[1][1].ravel(), mse), max_error)