diff --git a/CHANGELOG.md b/CHANGELOG.md index c491204..09d6ab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ * In general, naming convention for attriutes has been changed to use the plural form if the attribute is a list of values for each element (i.e., `Scanpaths.xs`) and the singular form if the attribute is a single value (i.e., `Scanpaths.length`, `Fixations.x`). This resulted in renaming `Fixations.subjects` to `Fixations.subject`. The old name is now a deprecated alias. + * Bugfix: Compatibility with torch 2.2 and numpy 2.0 + * Bugfix!: The download location of the RARE2012 model changed. The new source code results in slightly different predictions. + * Feature: The RARE2007 model is now available as `pysaliency.external_models.RARE2007`. It's execution requires MATLAB. + * 0.2.22: * Enhancement: New [Tutorial](notebooks/Tutorial.ipynb). diff --git a/pysaliency/external_models/__init__.py b/pysaliency/external_models/__init__.py index e976563..7f7a5c3 100644 --- a/pysaliency/external_models/__init__.py +++ b/pysaliency/external_models/__init__.py @@ -1,19 +1,18 @@ +from .deepgaze import ( + DeepGazeI, + DeepGazeIIE, +) from .matlab_models import ( AIM, - SUN, - ContextAwareSaliency, BMS, GBVS, - GBVSIttiKoch, - Judd, - IttiKoch, + RARE2007, RARE2012, + SUN, + ContextAwareSaliency, CovSal, + GBVSIttiKoch, + IttiKoch, + Judd, ) - -from .deepgaze import ( - DeepGazeI, - DeepGazeIIE, -) - from .utils import ExternalModelMixin diff --git a/pysaliency/external_models/matlab_models.py b/pysaliency/external_models/matlab_models.py index e9fd732..74ddcfb 100644 --- a/pysaliency/external_models/matlab_models.py +++ b/pysaliency/external_models/matlab_models.py @@ -454,18 +454,61 @@ def _setup(self, saliency_toolbox_archive): f.write(resource_string(__name__, 'scripts/IttiKoch_wrapper.m')) +class RARE2007(ExternalModelMixin, MatlabSaliencyMapModel): + """ + RARE2007 by Mancas. + The original matlab code is used. + + .. note:: + The source code published by the authors is used without modifications. + + .. seealso:: + Matei Mancas. Relative influence of bottom-up and top-down attention. + [International Workshop on Attention in Cognitive Systems 2008] + + https://numediart.github.io/VisualAttention-RareFamily/ + https://github.com/numediart/VisualAttention-Rare2007 + """ + __modelname__ = 'RARE2007' + + def __init__(self, location=None, **kwargs): + self.setup(location) + super(RARE2007, self).__init__(os.path.join(self.location, 'RARE2007_wrapper.m'), only_color_stimuli=True, **kwargs) + + def _setup(self): + source_location = os.path.join(self.location, 'source') + directory = 'VisualAttention-Rare2007-ee7ef25c9b6cc7e96837091e868d03bd97b4b131' + print('Downloading RARE2007 Model...') + url = 'https://github.com/numediart/VisualAttention-Rare2007/archive/ee7ef25c9b6cc7e96837091e868d03bd97b4b131.zip' + download_extract_patch(url, + '7ee05ae059dac10478b5cabc8ee066dc', + os.path.join(source_location, directory), + location_in_archive=True, + patches=None) + + with open(os.path.join(self.location, 'RARE2007_wrapper.m'), 'wb') as f: + f.write(resource_string(__name__, 'scripts/RARE2007_wrapper.m')) + + class RARE2012(ExternalModelMixin, MatlabSaliencyMapModel): """ RARE2012 by Margolin et al. The original matlab code is used. .. note:: - The original code is patched to work from other directories. - The model makes use of the [SaliencyToolbox](http://www.saliencytoolbox.net/). Due - to licence restrictions the Toolbox cannot be downloaded automatically. You have to - download it yourself and provide the location of the zipfile via the - `saliency_toolbox_archive`-keyword to the constructor. + + This page is not available anymore, the RARE models are now hosted + at https://numediart.github.io/VisualAttention-RareFamily/, the RARE2012 + model is published at https://github.com/numediart/VisualAttention-Rare2012. + This model is a wrapper around the published (compiled) matlab code. + + The model used to be hosted at + http://www.tcts.fpms.ac.be/attention/?categorie16/what-and-why. + This page is not available anymore, the RARE models are now hosted + at https://numediart.github.io/VisualAttention-RareFamily/ and GitHub. + With this change, the behaviour of RARE2012 changed slightly + compared to the earlier version (e.g., saliency maps look a bit smoother). This model does not work with octave due to incompabilities of octave with matlab (RARE2012 comes as precompiled matlab file). @@ -477,7 +520,7 @@ class RARE2012(ExternalModelMixin, MatlabSaliencyMapModel): saliency detection with its comparative statistical analysis [Signal Processing: Image Communication, 2013] - http://www.tcts.fpms.ac.be/attention/?categorie16/what-and-why + https://numediart.github.io/VisualAttention-RareFamily/ """ __modelname__ = 'RARE2012' @@ -487,18 +530,12 @@ def __init__(self, location=None, **kwargs): def _setup(self): source_location = os.path.join(self.location, 'source') + directory = 'VisualAttention-Rare2012-55ba7414b971429e5e899ddfa574e4235fc806e6' print('Downloading RARE2012 Model...') - #download_extract_patch('http://www.tcts.fpms.ac.be/attention/data/documents/data/rare2012.zip', - download_extract_patch('http://tcts.fpms.ac.be/attention/data/medias/documents/models/rare2012.zip', - '5a0a0de83e82b46fa70cea8b0a6bae55', - os.path.join(source_location, 'Rare2012'), - location_in_archive=True, - patches=None) - - print('Downloading simplegabortb-v1.0.0') - download_extract_patch('http://www2.it.lut.fi/project/simplegabor/downloads/src/simplegabortb/simplegabortb-v1.0.0.tar.gz', - '92bc6ae7178a7b1301fad52489f5d677', - os.path.join(source_location, 'simplegabortb-v1.0.0'), + url = 'https://github.com/numediart/VisualAttention-Rare2012/archive/55ba7414b971429e5e899ddfa574e4235fc806e6.zip' + download_extract_patch(url, + 'a5bbd8a42c231530834659acfd0d2b64.', + os.path.join(source_location, directory), location_in_archive=True, patches=None) diff --git a/pysaliency/external_models/scripts/RARE2012_wrapper.m b/pysaliency/external_models/scripts/RARE2012_wrapper.m index 27346ee..8da9b80 100644 --- a/pysaliency/external_models/scripts/RARE2012_wrapper.m +++ b/pysaliency/external_models/scripts/RARE2012_wrapper.m @@ -1,9 +1,8 @@ function [ ] = RARE2012(filename, outname) - addpath('source/simplegabortb-v1.0.0') - addpath('source/Rare2012') + addpath('source/VisualAttention-Rare2012-55ba7414b971429e5e899ddfa574e4235fc806e6') I = im2double(imread(filename)); - saliency_map = RARE2012(I); + saliency_map = rare2012(I); save(outname, 'saliency_map'); - + diff --git a/tests/conftest.py b/tests/conftest.py index 1a3045b..c7c58a1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -49,20 +49,14 @@ def matlab(request, pytestconfig): pysaliency.utils.MatlabOptions.octave_names = [] elif request.param == 'octave': if pytestconfig.getoption("--nooctave"): - pytest.skip("skipped octave") + pytest.skip("skipped octave due to command line option") + elif any([marker.name == 'skip_octave' for marker in request.node.own_markers]): + pytest.skip("skipped octave due to test marker") pysaliency.utils.MatlabOptions.matlab_names = [] pysaliency.utils.MatlabOptions.octave_names = ['octave', 'octave.exe'] return request.param - -@pytest.fixture() -def skip_by_matlab(request, matlab): - if request.node.get_marker('skip_octave'): - if matlab == 'octave': - pytest.skip('skipped octave') - - #@pytest.fixture(params=["no_location", "with_location"]) #def location(tmpdir, request): # if request.param == 'no_location': diff --git a/tests/external_models/RARE2007_color_stimulus.npy b/tests/external_models/RARE2007_color_stimulus.npy new file mode 100644 index 0000000..d79af3a Binary files /dev/null and b/tests/external_models/RARE2007_color_stimulus.npy differ diff --git a/tests/external_models/RARE2007_grayscale_stimulus.npy b/tests/external_models/RARE2007_grayscale_stimulus.npy new file mode 100644 index 0000000..29ab10d Binary files /dev/null and b/tests/external_models/RARE2007_grayscale_stimulus.npy differ diff --git a/tests/external_models/RARE2012_color_stimulus.npy b/tests/external_models/RARE2012_color_stimulus.npy index 87f8de5..f880236 100644 Binary files a/tests/external_models/RARE2012_color_stimulus.npy and b/tests/external_models/RARE2012_color_stimulus.npy differ diff --git a/tests/external_models/RARE2012_grayscale_stimulus.npy b/tests/external_models/RARE2012_grayscale_stimulus.npy index 139d309..b08693d 100644 Binary files a/tests/external_models/RARE2012_grayscale_stimulus.npy and b/tests/external_models/RARE2012_grayscale_stimulus.npy differ diff --git a/tests/test_external_models.py b/tests/test_external_models.py index 5b090b5..3940886 100644 --- a/tests/test_external_models.py +++ b/tests/test_external_models.py @@ -120,6 +120,20 @@ def test_IttiKoch(tmpdir, matlab, color_stimulus, grayscale_stimulus): np.load(os.path.join('tests', 'external_models', '{}_grayscale_stimulus.npy'.format(model.__modelname__)))) +@pytest.mark.skip_octave +@pytest.mark.matlab +def test_RARE2007(tmpdir, matlab, color_stimulus, grayscale_stimulus): + model = pysaliency.external_models.RARE2007(location=str(tmpdir)) + print('Testing color') + saliency_map = model.saliency_map(color_stimulus) + np.testing.assert_allclose(saliency_map, + np.load(os.path.join('tests', 'external_models', '{}_color_stimulus.npy'.format(model.__modelname__)))) + print('Testing Grayscale') + saliency_map = model.saliency_map(grayscale_stimulus) + np.testing.assert_allclose(saliency_map, + np.load(os.path.join('tests', 'external_models', '{}_grayscale_stimulus.npy'.format(model.__modelname__)))) + + @pytest.mark.skip_octave @pytest.mark.matlab def test_RARE2012(tmpdir, matlab, color_stimulus, grayscale_stimulus):