Exemplo n.º 1
0
    def test_image_column_sum_is_calculated_correctly(self):
        """
        Added 04.11.2018
        @return:
        """
        lightning_image = LightningImage(self.sum_array)

        column_sum = lightning_image.column_sum()
        self.assertListEqual([1, 3], list(column_sum))
Exemplo n.º 2
0
    def test_image_row_sum_is_calculated_correctly(self):
        """
        Added 04.11.2018
        @return:
        """
        lightning_image = LightningImage(self.sum_array)

        row_sum = lightning_image.row_sum()
        self.assertListEqual([2, 2], list(row_sum))
Exemplo n.º 3
0
    def test_image_column_sum_scaling_works(self):
        """
        Added 04.11.2018
        @return:
        """
        lightning_image = LightningImage(self.sum_array)

        column_sum = lightning_image.column_sum(scale=1)
        # Here we need to test each element separately because the elements are float and we obviously cannot
        # hard-compare two floats & there is no "ListAlmostEqual" Assertion
        self.assertAlmostEqual(0.333, column_sum[0], 2)
        self.assertAlmostEqual(1.0, column_sum[1], 2)
Exemplo n.º 4
0
    def __call__(self, lightning_image):
        """
        The main function executed, when the engine is called.

        CHANGELOG

        Added 16.11.2018

        @param LightningImage lightning_image:
        @return: List(Tuple())
        """
        # A copy of the image object is being made, so transformations can be used without disturbing the original
        # image
        self.current = LightningImage(lightning_image)

        # Calculating the row and column sums of the grayscale values
        self.x_sums = self.current.row_sum()
        self.y_sums = self.current.column_sum()

        # Calculating the mean value of both these functions
        x_average = np.average(self.x_sums)
        y_average = np.average(self.y_sums)

        # Calculating the thresholds based on the factor given by the config
        self.x_threshold = x_average * self.config['threshold']
        self.y_threshold = y_average * self.config['threshold']

        # Getting all the possible areas
        x_sequences = threshold_sequencing(self.x_sums,
                                           self.config['threshold'])
        y_sequences = threshold_sequencing(self.y_sums,
                                           self.config['threshold'])

        areas = combinations_2d(x_sequences, y_sequences)

        if self.config['checking']:
            # Creating areas only from all the possible combinations of two axis's sub sequences also creates a lot
            # of false areas.
            # Here we go through all the areas and essentially compute the average amount of signal within them. Areas
            # are only part of the final solution, if the average within them surpasses a certain threshold
            result = []
            for area in areas:
                # Calculating the average within these areas and only using these that contain a high enough value
                av = average_2d(self.current.array, area)
                # print("Checking {} with average {}".format(str(area), av))
                if (av / 255) >= self.config['check_threshold']:
                    result.append(area)
            return result

        return areas
Exemplo n.º 5
0
    def test_applying_function_transformation_on_each_element(self):
        """
        Added 16.11.2018
        @return:
        """
        def quadratic(value, index0, index1):
            return value**2

        # Creating the array to test on
        array = np.asarray([[1, 3], [2, 5]])
        image = LightningImage(array)

        # Applying the function
        image.transform_element_wise(quadratic)
        # testing each element
        expected = ([[1, 9], [4, 25]])
        self.assertTrue((image.array == expected).all())
Exemplo n.º 6
0
    def test_height_and_width_values_are_assigned_correctly(self):
        """
        Added 06.11.2018
        @return:
        """
        lightning_image = LightningImage(self.shape_array)

        self.assertEqual(2, lightning_image.height)
        self.assertEqual(4, lightning_image.width)
Exemplo n.º 7
0
    def test_applying_function_masked_element_wise(self):
        """
        Added 16.11.2018
        @return:
        """
        def quadratic(value, index0, index1):
            return value**2

        # Defining the array to test on, the mask to be used and the expected resulting array
        array = np.asarray([[1, 3, 5], [6, 2, 1], [3, 2, 4]])
        mask = np.asarray([[1, 1, 0], [1, 0, 1], [1, 0, 0]])
        expected = np.asarray([[1, 9, 5], [36, 2, 1], [9, 2, 4]])

        # Applying the function on the array
        image = LightningImage(array)
        image.transform_masked(quadratic, mask)

        self.assertTrue((expected == image.array).all())
Exemplo n.º 8
0
    def test_applying_function_element_wise_with_outer_scope_variable(self):
        """
        Added 16.11.2018
        @return:
        """
        summation = 0

        def add(value, index0, index1):
            nonlocal summation
            summation += value
            return value

        # The array to test on
        array = np.asarray([[1, 2, 1], [1, 1, 2]])
        image = LightningImage(array)

        # Applying the function
        image.transform_element_wise(add)
        self.assertEqual(8, summation)
Exemplo n.º 9
0
    def test_applying_function_on_image_that_returns_scalar(self):
        """
        Added 16.11.2018
        @return:
        """
        # Defining a function, that returns the global sum of all elements
        summation = 0

        def add(array):
            nonlocal summation
            it = np.nditer(array)
            while not it.finished:
                summation += it[0]
                it.iternext()
            return array

        # The array to test on
        array = np.asarray([[1, 2, 1], [1, 1, 2]])
        image = LightningImage(array)

        # Applying the function
        image.transform(add)
        self.assertEqual(8, summation)
Exemplo n.º 10
0
class SimpleAreaSegmentationEngine(AbstractAreaSegmentationEngine):
    """
    This procedure assumes the image is already processed.

    Given an Image object, this algorithm will calculate the pixel sums along the rows and the columns of the picture.
    The resulting intensity function is then segmented into sub sequences along the axis's by watching, when the
    function first exceeds a certain threshold and when it drops below it again.
    From these sequences along the axis all possible combinations(=areas on the picture) are computed. These areas are
    suspected to contain intensity maximums. In the last step the average of each area is checked against another
    threshold to remove false positives from the final result.

    CHANGELOG

    Added 16.11.2018
    """
    DEFAULT_CONFIG = {
        'threshold': 1.0,
        'checking': True,
        'check_threshold': 0.03,
    }

    def __init__(self, config):
        """
        The constructor.

        The config dict can have the following parameters:
        - threshold:        A float, which defines the factor between a value of the axis sum function and the global
                            average of the latter that qualifies a value as surpassing the threshold.
                            A threshold RELATIVE to the average of the function. DEFAULT is 1.0
        - checking:         boolean flag of whether or not to perform the last checking operation
        - check_threshold:  A float threshold value relative to 255 the average of an area has to have to qualify as a
                            valid solution to the problem. DEFAULT is 0.03, equates to roughly a grayscale value of 7,
                            which has to be the average of an area.

        CHANGELOG

        Added 16.11.2018

        @param dict config:
        """
        AbstractAreaSegmentationEngine.__init__(self, config)
        self.config = self.DEFAULT_CONFIG.copy()
        self.config.update(config)

        self.current = None

    def __call__(self, lightning_image):
        """
        The main function executed, when the engine is called.

        CHANGELOG

        Added 16.11.2018

        @param LightningImage lightning_image:
        @return: List(Tuple())
        """
        # A copy of the image object is being made, so transformations can be used without disturbing the original
        # image
        self.current = LightningImage(lightning_image)

        # Calculating the row and column sums of the grayscale values
        self.x_sums = self.current.row_sum()
        self.y_sums = self.current.column_sum()

        # Calculating the mean value of both these functions
        x_average = np.average(self.x_sums)
        y_average = np.average(self.y_sums)

        # Calculating the thresholds based on the factor given by the config
        self.x_threshold = x_average * self.config['threshold']
        self.y_threshold = y_average * self.config['threshold']

        # Getting all the possible areas
        x_sequences = threshold_sequencing(self.x_sums,
                                           self.config['threshold'])
        y_sequences = threshold_sequencing(self.y_sums,
                                           self.config['threshold'])

        areas = combinations_2d(x_sequences, y_sequences)

        if self.config['checking']:
            # Creating areas only from all the possible combinations of two axis's sub sequences also creates a lot
            # of false areas.
            # Here we go through all the areas and essentially compute the average amount of signal within them. Areas
            # are only part of the final solution, if the average within them surpasses a certain threshold
            result = []
            for area in areas:
                # Calculating the average within these areas and only using these that contain a high enough value
                av = average_2d(self.current.array, area)
                # print("Checking {} with average {}".format(str(area), av))
                if (av / 255) >= self.config['check_threshold']:
                    result.append(area)
            return result

        return areas