Example #1
0
    def test_point_dist(self):
        """Test point distance calculation."""
        data = (((0, 0), (8, 9), 12.0416), ((1, 3), (8, 9), 9.2195),
                ((-3, 34), (8, -99), 133.4541), ((3.5, 34.1), (8.0, 99.6),
                                                 65.6544))

        for p1, p2, out in data:
            self.assertEqual(round(ft.point_dist(p1, p2), 4), out)
Example #2
0
    def test_point_dist(self):
        """Test point distance calculation."""
        data = (
            ((0,0),         (8,9),      12.0416),
            ((1,3),         (8,9),      9.2195),
            ((-3,34),       (8,-99),    133.4541),
            ((3.5,34.1),    (8.0,99.6), 65.6544)
        )

        for p1, p2, out in data:
            self.assertEqual( round(ft.point_dist(p1, p2), 4), out )
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)