diff --git a/.travis.yml b/.travis.yml index fcf1574..b7f476e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ install: - pip install -r requirements-tests.txt # command to run tests script: - - nosetests -v tests/*.py + - make tests diff --git a/Makefile b/Makefile index 4f55f9e..134268a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +.PHONY: tests build: python3 setup.py sdist @@ -10,3 +11,11 @@ doc: clean: rm -rf *.egg-info build dist src/keras_video_generators.egg-info + +tests: + nosetests -v tests/*.py --with-coverage --cover-package keras_video + +tests-html: + nosetests -v tests/*.py --with-coverage --cover-package keras_video \ + --cover-html --cover-html-dir=coverage + xdg-open coverage/index.html diff --git a/README.md b/README.md index 10c2478..2c1ca2e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ The package contains 3 generators that inherits `Sequence` interface. So they ma - `VideoFrameGenerator` that will take the choosen number of frames from the entire video - `SlidingFrameGenerator` that takes frames with decay for the entire video or with a sequence time -- `OpticalFlowGenerator` that gives optical flow sequence from frames with different methods +- `OpticalFlowGenerator` that gives optical flow sequence from frames with different methods (experimental) Each of these generators accepts parameters: @@ -61,6 +61,8 @@ Each of these generators accepts parameters: # Changelog +## v1.0.12 +- fix transformation error with SlidingFrameGenerator ## v1.0.11 - set generator to be Iterable diff --git a/requirements-tests.txt b/requirements-tests.txt index fc0e9f6..08ec0c7 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -1,2 +1,3 @@ nose +coverage tensorflow diff --git a/setup.py b/setup.py index dcdd427..b7ad838 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name='keras-video-generators', - version='1.0.11', + version='1.0.12', description='Keras sequence generators for video data', long_description=long_description, long_description_content_type="text/markdown", diff --git a/src/keras_video/__init__.py b/src/keras_video/__init__.py index 67e5969..446fa70 100644 --- a/src/keras_video/__init__.py +++ b/src/keras_video/__init__.py @@ -28,7 +28,7 @@ """ -__version__ = "1.0.11" +__version__ = "1.0.12" from . import flow from . import generator diff --git a/src/keras_video/generator.py b/src/keras_video/generator.py index 8bd86e4..52c1e47 100644 --- a/src/keras_video/generator.py +++ b/src/keras_video/generator.py @@ -199,7 +199,8 @@ def __init__( self.classes_count = len(classes) # to initialize transformations and shuffle indices - self.on_epoch_end() + if 'no_epoch_at_init' not in kwargs: + self.on_epoch_end() kind = "train" if _validation_data is not None: diff --git a/src/keras_video/sliding.py b/src/keras_video/sliding.py index 7be7d61..a78aaaf 100644 --- a/src/keras_video/sliding.py +++ b/src/keras_video/sliding.py @@ -53,7 +53,7 @@ class SlidingFrameGenerator(VideoFrameGenerator): """ def __init__(self, *args, sequence_time: int = None, **kwargs): - super().__init__(*args, **kwargs) + super().__init__(no_epoch_at_init=True, *args, **kwargs) self.sequence_time = sequence_time self.sample_count = 0 diff --git a/tests/basic.py b/tests/basic.py index 8a8f5ee..c241339 100644 --- a/tests/basic.py +++ b/tests/basic.py @@ -1,4 +1,3 @@ - import keras_video import unittest import os diff --git a/tests/opticalflow.py b/tests/opticalflow.py new file mode 100644 index 0000000..8166c84 --- /dev/null +++ b/tests/opticalflow.py @@ -0,0 +1,66 @@ +import keras_video +import keras +import unittest +import os +import sys +import shutil +sys.path.insert(0, './src') + + +class TestOpticalFlow(unittest.TestCase): + + testdir = 'test_vids' + + def setUp(self): + dirname = self.testdir + os.makedirs(dirname) + + def _write_zero(cl, i): + shutil.copy( + 'tests/vidtest.ogv', + os.path.join(self.testdir, '%s_%d.ogv' % (cl, i)) + ) + + for i in range(10): + for cl in ['A', 'B', 'C']: + _write_zero(cl, i) + + def tearDown(self): + shutil.rmtree(self.testdir) + + def test_init(self): + """ Check opticalflow init """ + gen = keras_video.OpticalFlowGenerator( + glob_pattern=os.path.join(self.testdir, '{classname}_*.ogv') + ) + assert len(gen.classes) == 3 + assert gen.files_count == 30 + + def __get_with_method(self, method=keras_video.METHOD_ABS_DIFF): + tr = keras.preprocessing.image.ImageDataGenerator(rotation_range=10) + + gen = keras_video.OpticalFlowGenerator( + method=method, + glob_pattern=os.path.join(self.testdir, '{classname}_*.ogv'), + transformation=tr + ) + + seq, labels = next(gen) + assert seq.shape == (16, 5, 224, 224, 3) + assert labels.shape == (16, 3) + + def test_absdiff(self): + """ Check absdiff """ + self.__get_with_method(keras_video.METHOD_ABS_DIFF) + + def test_absdiffmask(self): + """ Check absdiff masked """ + self.__get_with_method(keras_video.METHOD_DIFF_MASK) + + def test_opticalflow(self): + """ Check opticalflow""" + self.__get_with_method(keras_video.METHOD_OPTICAL_FLOW) + + def test_opticalflowmask(self): + """ Check opticalflow masked """ + self.__get_with_method(keras_video.METHOD_FLOW_MASK) diff --git a/tests/slinding.py b/tests/slinding.py new file mode 100644 index 0000000..ec944e0 --- /dev/null +++ b/tests/slinding.py @@ -0,0 +1,56 @@ +import keras_video +import keras +import unittest +import os +import sys +import shutil +sys.path.insert(0, './src') + + +class TestSlinding(unittest.TestCase): + + testdir = 'test_vids' + + def setUp(self): + dirname = self.testdir + os.makedirs(dirname) + + def _write_zero(cl, i): + shutil.copy( + 'tests/vidtest.ogv', + os.path.join(self.testdir, '%s_%d.ogv' % (cl, i)) + ) + + for i in range(10): + for cl in ['A', 'B', 'C']: + _write_zero(cl, i) + + def tearDown(self): + shutil.rmtree(self.testdir) + + def test_init(self): + """ Check if slinding generator init """ + g = keras_video.SlidingFrameGenerator( + glob_pattern=os.path.join(self.testdir, '{classname}_*.ogv')) + assert 'A' in g.classes + assert 'B' in g.classes + assert 'C' in g.classes + + assert g.files_count == 30 + + # check get item + seq, labels = next(g) + assert seq.shape == (16, 5, 224, 224, 3) + assert labels.shape == (16, 3) + + def test_with_transformation(self): + """ Check if transformation works with slinding frame generator """ + tr = keras.preprocessing.image.ImageDataGenerator(rotation_range=10) + g = keras_video.SlidingFrameGenerator( + transformation=tr, + glob_pattern=os.path.join(self.testdir, '{classname}_*.ogv')) + + # check get item + seq, labels = next(g) + assert seq.shape == (16, 5, 224, 224, 3) + assert labels.shape == (16, 3) diff --git a/tests/split.py b/tests/split.py new file mode 100644 index 0000000..9e03c10 --- /dev/null +++ b/tests/split.py @@ -0,0 +1,55 @@ +import keras_video +import unittest +import os +import sys +import shutil +sys.path.insert(0, './src') + + +class TestSplit(unittest.TestCase): + + testdir = 'test_vids' + + def setUp(self): + dirname = self.testdir + os.makedirs(dirname) + + def _write_zero(cl, i): + shutil.copy( + 'tests/vidtest.ogv', + os.path.join(self.testdir, '%s_%d.ogv' % (cl, i)) + ) + + for i in range(10): + for cl in ['A', 'B', 'C']: + _write_zero(cl, i) + + def tearDown(self): + shutil.rmtree(self.testdir) + + def __split(self, + kind=keras_video.VideoFrameGenerator, + vc=0, + tc=0): + pattern = os.path.join(self.testdir, '{classname}_*.ogv') + gen = kind( + glob_pattern=pattern, + split_test=.2, + split_val=.3) + valid = gen.get_validation_generator() + test = gen.get_test_generator() + + assert valid.files_count == vc + assert test.files_count == tc + + def test_videoframegenerator_split(self): + """ Check spliting VideoFrameGenerator """ + self.__split(keras_video.VideoFrameGenerator, 9, 3) + + def test_slidinggenerator_split(self): + """ Check splitint SlidingFrameGenerator """ + self.__split(keras_video.SlidingFrameGenerator, 9, 3) + + def test_flowgenerator_split(self): + """ Check splitint OpticalFlowGenerator """ + self.__split(keras_video.OpticalFlowGenerator, 9, 3)