class TestHistogramFeatureExtractor:
    channel1 = np.arange(12).reshape([3, 4])
    channel2 = np.arange(100, 112).reshape([3, 4])
    channel3 = np.array([100, ] * 6 + [200, ] * 6).reshape([3, 4])
    test_image = np.stack([channel1, channel2, channel3], axis=2)
    test_image_1d = np.stack([channel1], axis=2)

    descr1 = Descriptor([0.1 / 16, 1 / 16])
    descr2 = Descriptor([0.2 / 16, 4])
    descr3 = Descriptor([5, 6])

    mocked_calc_histo_1d = MockingNPFunction([channel1, channel2, channel3],
                                             [descr1, descr2, descr3])

    def test_calculate_histogram_shape(self):
        histo = HistogramFeatureExtractor().calculate(self.test_image)
        assert isinstance(histo, Descriptor)
        assert histo.vector.shape == (EXPECTED_1D_HISTO_LENGTH * 3,)

    def test_for_3_channel(self):
        with mock.patch('impl.feature_engine.histogram_feature_extractor.calculate_histogram_1d', new=self.mocked_calc_histo_1d):
            histo = HistogramFeatureExtractor().calculate(self.test_image)
        assert np.allclose(histo.vector, np.array([0.1, 1, 0.2, 1, 1, 1]))

    def test_for_1_channel(self):
        with mock.patch('impl.feature_engine.histogram_feature_extractor.calculate_histogram_1d', new=self.mocked_calc_histo_1d):
            histo = HistogramFeatureExtractor().calculate(self.test_image_1d)
        assert np.allclose(histo.vector, [0.1, 1] * 3)

    def test_for_2d_image(self):
        with mock.patch('impl.feature_engine.histogram_feature_extractor.calculate_histogram_1d', new=self.mocked_calc_histo_1d):
            histo = HistogramFeatureExtractor().calculate(self.channel1)
        assert np.allclose(histo.vector, [0.1, 1] * 3)
Exemple #2
0
 def calculate(self, image: np.ndarray) -> Descriptor:
     channels = get_channels(image)
     descriptors_1d = [calculate_histogram_1d(channel).vector for channel in channels]
     vector = np.hstack(descriptors_1d)
     vector_clipped = np.clip(vector * self._SCALE_FACTOR, 0.0, 1.0)
     descriptor = Descriptor(vector=vector_clipped)
     return descriptor
Exemple #3
0
class TestSearchTermsCreator:
    descriptor = Descriptor([1, 2, 3, 4, 5, 6])
    quantized_vector = np.array([0, 1, 2, 3, 3, 3])
    composed_values = np.array([0, 10, 20])

    def test_get_dictionary_of_words(self, mocked_words_composer,
                                     mocked_quantizer):
        mocked_words_composer.return_value.compose.return_value = self.composed_values
        mocked_quantizer.return_value.quantize_vector.return_value = self.quantized_vector

        quantizer = SearchTermsCreator(DESCRIPTOR_LENGTH)
        words = quantizer.get_dictionary_of_words(self.descriptor)

        assert isinstance(words, dict)
        assert all([type(value) == int for value in words.values()])
        assert words == {
            "word_0000": self.composed_values[0],
            "word_0001": self.composed_values[1],
            "word_0002": self.composed_values[2],
        }
        mocked_words_composer.assert_called_once_with(
            np.prod(DESCRIPTOR_LENGTH), mocked_config.LENGTH_OF_WORD,
            mocked_config.NUMBER_OF_LEVELS)
        mocked_words_composer.return_value.compose.assert_called_once_with(
            self.quantized_vector)
        mocked_quantizer.assert_called_once_with(
            mocked_config.NUMBER_OF_LEVELS)
        mocked_quantizer.return_value.quantize_vector.assert_called_once_with(
            self.descriptor.vector)
Exemple #4
0
def calculate_histogram_1d(image: np.array) -> Descriptor:
    def shape_is_good(img):
        return len(img.shape) == 2 or (len(img.shape) == 3 and img.shape[-1] == 1)

    if not shape_is_good(image):
        raise HistogramBasedFeatureExtractorException("only 1 channel images are supported here")

    image_clipped = np.clip(image, 0, 255)
    h = np.histogram(a=image_clipped, bins=16, range=[0, 256])[0]
    histogram_normalized = h / image_clipped.size
    return Descriptor(vector=histogram_normalized)
Exemple #5
0
class TestDescriptorSearch:
    descriptor = Descriptor([1])
    image_region = ImageRegion(descriptor)

    expected_result1 = {
        SearchResult.FIELD_DESCRIPTOR: [1],
        SearchResult.FIELD_SOURCE_ID: "some_id1"
    }
    expected_result2 = {
        SearchResult.FIELD_DESCRIPTOR: [2],
        SearchResult.FIELD_SOURCE_ID: "some_id2"
    }

    repo_find_results = [expected_result1, expected_result2]

    descriptor_shape = (16 * 3, )

    @mock.patch('impl.search.descriptor_search.RegionRepository',
                autospec=True)
    @mock.patch('impl.search.descriptor_search.CleanedSearchResult',
                autospec=True)
    def test_find_similar_behaviour(self, cleaned_search_result,
                                    region_repository):
        cleaned_search_result.return_value = search_result
        region_repository.return_value.find.return_value = self.repo_find_results

        similar = DescriptorSearch(
            descriptor_shape=self.descriptor_shape).find_similar_for_region(
                self.image_region)

        assert similar == search_result
        region_repository.assert_called_once_with((48, ), flush_data=False)
        region_repository.return_value.find.assert_called_once_with(
            self.descriptor)
        region_repository.return_value.save.assert_not_called()
        cleaned_search_result.assert_called_once_with(self.image_region,
                                                      self.repo_find_results)

    @mock.patch('impl.search.descriptor_search.RegionRepository',
                autospec=True)
    def test_add_region(self, region_repository):
        region_repository.return_value.save.return_value = "region_reference"
        reference_to_source = "ref1"

        similar = DescriptorSearch(
            descriptor_shape=self.descriptor_shape).add_region(
                self.image_region, reference_to_source)

        assert similar == "region_reference"
        region_repository.assert_called_once_with(self.descriptor_shape,
                                                  flush_data=False)
        region_repository.return_value.find.assert_not_called()
        region_repository.return_value.save.assert_called_once_with(
            self.image_region, reference_to_source)
class TestSubimageFeatureEngine:
    descriptor1 = Descriptor([1])
    descriptor2 = Descriptor([2])
    expected_image_regions = [
        ImageRegion(descriptor1),
        ImageRegion(descriptor2),
    ]
    ref_source = "some reference to source"
    feature_extractor = mock.create_autospec(FeatureExtractor)
    subimage_extractor = mock.create_autospec(SubimageExtractor)

    def test_should_have_extract_features_method(self):
        extractor = SubimageFeatureEngine(FeatureExtractor, SubimageExtractor)
        assert hasattr(extractor, 'extract_features')

    @mock.patch('impl.feature_engine.subimage_feature_engine.ImageEncoder',
                spec=True)
    @mock.patch(
        'impl.feature_engine.subimage_feature_engine.SubimagesProcessor',
        spec=True)
    def test_steps(self, mocked_subimage_processor, mocked_image_encoder):
        mocked_image_encoder.return_value.binary_to_array.return_value = whole_image
        mocked_subimage_processor.return_value.extract_features_and_create_regions.return_value = self.expected_image_regions
        extracted_subimages = ["subimage1", "subimage2"]
        self.subimage_extractor.extract.return_value = extracted_subimages

        engine = SubimageFeatureEngine(self.feature_extractor,
                                       self.subimage_extractor)
        image_regions = engine.extract_features(binary_image)

        assert image_regions == self.expected_image_regions
        mocked_image_encoder.assert_called_once_with(image_format="jpeg")
        mocked_image_encoder.return_value.binary_to_array.assert_called_once_with(
            binary_image)
        self.subimage_extractor.extract.assert_called_once_with(whole_image)
        mocked_subimage_processor.assert_called_once_with(
            self.feature_extractor)
        mocked_subimage_processor.return_value.extract_features_and_create_regions.assert_called_once_with(
            extracted_subimages)
Exemple #7
0
 def calculate(self, image: np.ndarray) -> Descriptor:
     channels = get_channels(image)
     average_per_channel = [np.mean(channel) / 255. for channel in channels]
     descriptor = Descriptor(vector=np.array(average_per_channel))
     return descriptor
Exemple #8
0
import numpy as np

from kolasimagecommon import Descriptor
from impl.domain.image_region import ImageRegion
from impl.feature_engine.histogram_feature_extractor import FeatureExtractor
from kolasimagecommon import SubImage
from impl.feature_engine.subimage_processor import SubimagesProcessor

mocked_feature_extractor = mock.create_autospec(spec=FeatureExtractor)
img1 = np.ones([3, 4])
img2 = np.ones([3, 4]) * 123
subimage1 = SubImage(img1)
subimage2 = SubImage(img2)
some_reference = "some_refg"

descriptor1 = Descriptor([12, 3])
descriptor2 = Descriptor([4, 5])


class TestSubimagesProcessor:
    def test_subimages_processor_process(self):
        mocked_feature_extractor.calculate.side_effect = [
            descriptor1, descriptor2
        ]

        processor = SubimagesProcessor(mocked_feature_extractor)
        regions = processor.extract_features_and_create_regions(
            [subimage1, subimage2])

        assert regions == [ImageRegion(descriptor1), ImageRegion(descriptor2)]
        mocked_feature_extractor.calculate.assert_has_calls(
Exemple #9
0
 def __init__(self, data):
     self._data = data
     self._descriptor = Descriptor(self._data[self.FIELD_DESCRIPTOR])
     self._source_id = str(self._data[self.FIELD_SOURCE_ID])
Exemple #10
0
class TestRegionRepository:
    descriptor_as_list = [[1, 2, 3], [12, 12, 34]]
    descriptor1 = Descriptor(descriptor_as_list)
    reference_to_source = "ref1"
    image_region = ImageRegion(descriptor1)
    expected_image_region_elastic_id = "some_image_region_elastic_id"
    serialized_dict = {"key": "value"}
    words = {"word1": "value1", "word2": "value2"}
    expected_search_results = [
        mock.MagicMock(SearchResult),
        mock.MagicMock(SearchResult)
    ]

    @mock.patch('impl.storage.region_repository.config')
    @mock.patch('impl.storage.region_repository.ElasticSearchDriver',
                autospec=True)
    @mock.patch('impl.storage.region_repository.SearchTermsCreator',
                autospec=True)
    def test_save(self, mock_search_terms_creator, mock_elastic_search_driver,
                  mock_config):
        mock_config.ELASTIC_DESCRIPTOR_INDEX = "ELASTIC_DESCRIPTOR_INDEX"
        mock_config.ELASTIC_DESCRIPTOR_TYPE = "ELASTIC_DESCRIPTOR_TYPE"
        mock_search_terms_creator.return_value.get_dictionary_of_words.return_value = self.serialized_dict
        mock_elastic_search_driver.return_value.index.return_value = self.expected_image_region_elastic_id

        result = RegionRepository(descriptor_shape).save(
            self.image_region, self.reference_to_source)

        assert result == self.expected_image_region_elastic_id
        mock_search_terms_creator.assert_called_once_with(descriptor_shape)
        mock_search_terms_creator.return_value.get_dictionary_of_words.assert_called_once_with(
            self.image_region.descriptor)
        mock_elastic_search_driver.assert_called_once_with(
            index=mock_config.ELASTIC_DESCRIPTOR_INDEX,
            doc_type=mock_config.ELASTIC_DESCRIPTOR_TYPE,
            flush_data=False)
        mock_elastic_search_driver.return_value.index.assert_called_once_with({
            'descriptor':
            self.descriptor_as_list,
            'key':
            'value',
            'source_id':
            self.reference_to_source
        })

    @mock.patch('impl.storage.region_repository.config')
    @mock.patch('impl.storage.region_repository.ElasticSearchDriver',
                autospec=True)
    @mock.patch('impl.storage.region_repository.SearchTermsCreator',
                autospec=True)
    def test_find(self, mock_search_terms_creator, mock_elastic_search_driver,
                  mock_config):
        mock_config.ELASTIC_DESCRIPTOR_INDEX = "ELASTIC_DESCRIPTOR_INDEX"
        mock_config.ELASTIC_DESCRIPTOR_TYPE = "ELASTIC_DESCRIPTOR_TYPE"
        mock_search_terms_creator.return_value.get_dictionary_of_words.return_value = self.words
        mock_elastic_search_driver.return_value.search_by_words.return_value = self.expected_search_results

        result = RegionRepository(descriptor_shape).find(self.descriptor1)

        assert result == self.expected_search_results
        mock_search_terms_creator.assert_called_once_with(descriptor_shape)
        mock_search_terms_creator.return_value.get_dictionary_of_words.assert_called_once_with(
            self.descriptor1)
        mock_elastic_search_driver.assert_called_once_with(
            index=mock_config.ELASTIC_DESCRIPTOR_INDEX,
            doc_type=mock_config.ELASTIC_DESCRIPTOR_TYPE,
            flush_data=False)
        mock_elastic_search_driver.return_value.search_by_words.assert_called_once_with(
            self.words, list(self.words.keys()))

    @mock.patch('impl.storage.region_repository.config')
    @mock.patch('impl.storage.region_repository.ElasticSearchDriver',
                autospec=True)
    def test_with_flush_data(self, mock_elastic_search_driver, mock_config):
        RegionRepository(descriptor_shape, True)

        mock_elastic_search_driver.assert_called_once_with(
            index=mock_config.ELASTIC_DESCRIPTOR_INDEX,
            doc_type=mock_config.ELASTIC_DESCRIPTOR_TYPE,
            flush_data=True)