From b1cca53f9dcfbc7166da3aeea23817e6a5545c33 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Sun, 10 Mar 2019 23:18:56 +0000 Subject: [PATCH 1/8] Add size params for preprocessing. --- chainercv/links/model/fpn/faster_rcnn.py | 11 +++++++--- .../links/model/fpn/faster_rcnn_fpn_resnet.py | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/chainercv/links/model/fpn/faster_rcnn.py b/chainercv/links/model/fpn/faster_rcnn.py index 23611b3313..3eeed18767 100644 --- a/chainercv/links/model/fpn/faster_rcnn.py +++ b/chainercv/links/model/fpn/faster_rcnn.py @@ -26,6 +26,9 @@ class FasterRCNN(chainer.Chain): head (Link): A link that has the same interface as :class:`~chainercv.links.model.fpn.Head`. Please refer to the documentation found there. + min_size (int): A preprocessing paramter for :meth:`prepare`. Please + refer to a docstring found for :meth:`prepare`. + max_size (int): A preprocessing paramter for :meth:`prepare`. Parameters: nms_thresh (float): The threshold value @@ -40,17 +43,19 @@ class FasterRCNN(chainer.Chain): """ - _min_size = 800 - _max_size = 1333 _stride = 32 - def __init__(self, extractor, rpn, head): + def __init__(self, extractor, rpn, head, + min_size, max_size): super(FasterRCNN, self).__init__() with self.init_scope(): self.extractor = extractor self.rpn = rpn self.head = head + self._min_size = min_size + self._max_size = max_size + self.use_preset('visualize') def use_preset(self, preset): diff --git a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py index 9757694d92..94d16f5fd4 100644 --- a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py +++ b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py @@ -19,7 +19,8 @@ class FasterRCNNFPNResNet(FasterRCNN): A subclass of this class should have :obj:`_base` and :obj:`_models`. """ - def __init__(self, n_fg_class=None, pretrained_model=None): + def __init__(self, n_fg_class=None, pretrained_model=None, + min_size=800, max_size=1333): param, path = utils.prepare_pretrained_model( {'n_fg_class': n_fg_class}, pretrained_model, self._models) @@ -56,8 +57,8 @@ class FasterRCNNFPNResNet50(FasterRCNNFPNResNet): Feature Pyramid Networks for Object Detection. CVPR 2017 Args: - n_fg_class (int): The number of classes excluding the background. - pretrained_model (string): The weight file to be loaded. + n_fg_class (int): The number of classes excluding the background. + pretrained_model (string): The weight file to be loaded. This can take :obj:`'coco'`, `filepath` or :obj:`None`. The default value is :obj:`None`. @@ -74,6 +75,9 @@ class FasterRCNNFPNResNet50(FasterRCNNFPNResNet): * `filepath`: A path of npz file. In this case, :obj:`n_fg_class` \ must be specified properly. * :obj:`None`: Do not load weights. + min_size (int): A preprocessing paramter for :meth:`prepare`. Please + refer to a docstring found for :meth:`prepare`. + max_size (int): A preprocessing paramter for :meth:`prepare`. """ @@ -99,10 +103,10 @@ class FasterRCNNFPNResNet101(FasterRCNNFPNResNet): Feature Pyramid Networks for Object Detection. CVPR 2017 Args: - n_fg_class (int): The number of classes excluding the background. - pretrained_model (string): The weight file to be loaded. - This can take :obj:`'coco'`, `filepath` or :obj:`None`. - The default value is :obj:`None`. + n_fg_class (int): The number of classes excluding the background. + pretrained_model (string): The weight file to be loaded. + This can take :obj:`'coco'`, `filepath` or :obj:`None`. + The default value is :obj:`None`. * :obj:`'coco'`: Load weights trained on train split of \ MS COCO 2017. \ @@ -117,6 +121,9 @@ class FasterRCNNFPNResNet101(FasterRCNNFPNResNet): * `filepath`: A path of npz file. In this case, :obj:`n_fg_class` \ must be specified properly. * :obj:`None`: Do not load weights. + min_size (int): A preprocessing paramter for :meth:`prepare`. Please + refer to a docstring found for :meth:`prepare`. + max_size (int): A preprocessing paramter for :meth:`prepare`. """ From 451c2166d16831fe26a4021c4183a5dd50424dc1 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Mon, 11 Mar 2019 10:15:27 +0000 Subject: [PATCH 2/8] Update FasterRCNN with default sizes. --- chainercv/links/model/fpn/faster_rcnn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainercv/links/model/fpn/faster_rcnn.py b/chainercv/links/model/fpn/faster_rcnn.py index 3eeed18767..dabfbd1812 100644 --- a/chainercv/links/model/fpn/faster_rcnn.py +++ b/chainercv/links/model/fpn/faster_rcnn.py @@ -46,7 +46,7 @@ class FasterRCNN(chainer.Chain): _stride = 32 def __init__(self, extractor, rpn, head, - min_size, max_size): + min_size=800, max_size=1333): super(FasterRCNN, self).__init__() with self.init_scope(): self.extractor = extractor From ea816f87fc86f2973d14e27870da27b491e8ab78 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 10:14:19 +0000 Subject: [PATCH 3/8] Add size param and fix comments. --- chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py index 94d16f5fd4..b0b9c4ea48 100644 --- a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py +++ b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py @@ -36,6 +36,7 @@ def __init__(self, n_fg_class=None, pretrained_model=None, extractor=extractor, rpn=RPN(extractor.scales), head=Head(param['n_fg_class'] + 1, extractor.scales), + min_size=min_size, max_size=max_size ) if path == 'imagenet': @@ -75,8 +76,8 @@ class FasterRCNNFPNResNet50(FasterRCNNFPNResNet): * `filepath`: A path of npz file. In this case, :obj:`n_fg_class` \ must be specified properly. * :obj:`None`: Do not load weights. - min_size (int): A preprocessing paramter for :meth:`prepare`. Please - refer to a docstring found for :meth:`prepare`. + min_size (int): A preprocessing paramter for :meth:`prepare`. Please \ + refer to :meth:`prepare`. max_size (int): A preprocessing paramter for :meth:`prepare`. """ @@ -121,8 +122,8 @@ class FasterRCNNFPNResNet101(FasterRCNNFPNResNet): * `filepath`: A path of npz file. In this case, :obj:`n_fg_class` \ must be specified properly. * :obj:`None`: Do not load weights. - min_size (int): A preprocessing paramter for :meth:`prepare`. Please - refer to a docstring found for :meth:`prepare`. + min_size (int): A preprocessing paramter for :meth:`prepare`. Please \ + refer to :meth:`prepare`. max_size (int): A preprocessing paramter for :meth:`prepare`. """ From b27316c3a6b3f4ceb0ec9c22f241a493d49cbd05 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 11:14:26 +0000 Subject: [PATCH 4/8] Add tests for min/max size in prepare. --- .../model_tests/fpn_tests/test_faster_rcnn.py | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py index b565062a8d..997b2b5f5b 100644 --- a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py +++ b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py @@ -31,24 +31,35 @@ def __call__(self, x): class DummyFasterRCNN(FasterRCNN): - def __init__(self, n_fg_class): + def __init__(self, n_fg_class, min_size, max_size): extractor = DummyExtractor() super(DummyFasterRCNN, self).__init__( extractor=extractor, rpn=RPN(extractor.scales), head=Head(n_fg_class + 1, extractor.scales), + min_size=min_size, max_size=max_size, ) @testing.parameterize( - {'n_fg_class': 1}, - {'n_fg_class': 5}, - {'n_fg_class': 20}, + {'n_fg_class': 1, 'min_size': 200, 'max_size': 400, + 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, + {'n_fg_class': 1, 'min_size': 800, 'max_size': 133, + 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, + {'n_fg_class': 5, 'min_size': 200, 'max_size': 400, + 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, + {'n_fg_class': 5, 'min_size': 800, 'max_size': 133, + 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, + {'n_fg_class': 20, 'min_size': 200, 'max_size': 400, + 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, + {'n_fg_class': 20, 'min_size': 800, 'max_size': 133, + 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, ) class TestFasterRCNN(unittest.TestCase): def setUp(self): - self.link = DummyFasterRCNN(n_fg_class=self.n_fg_class) + self.link = DummyFasterRCNN(n_fg_class=self.n_fg_class, + min_size=self.min_size, max_size=self.max_size) def test_use_preset(self): self.link.nms_thresh = 0 @@ -117,13 +128,19 @@ def test_predict_gpu(self): self.link.to_gpu() assert_is_detection_link(self.link, self.n_fg_class) - def test_prepare(self): - imgs = [ - np.random.randint(0, 255, size=(3, 480, 640)).astype(np.float32), - np.random.randint(0, 255, size=(3, 320, 320)).astype(np.float32), - ] - x, scales = self.link.prepare(imgs) - self.assertEqual(x.shape, (2, 3, 800, 1088)) + def check_prepare(self): + x = _random_array(np, self.in_shape) + out, scales = self.link.prepare(x) + self.assertIsInstance(out, np.ndarray) + self.assertEqual(out.shape, self.expected_shape) + + def test_prepare_cpu(self): + self.check_prepare() + + @attr.gpu + def test_prepare_gpu(self): + self.link.to_gpu() + self.check_prepare() testing.run_module(__name__, __file__) From 99a0a352f45fafeb013205319ac35b0c49102804 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 13:54:44 +0000 Subject: [PATCH 5/8] Update size tests --- .../links/model/fpn/faster_rcnn_fpn_resnet.py | 4 +- .../model_tests/fpn_tests/test_faster_rcnn.py | 51 +++++++++---------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py index b0b9c4ea48..4b86e0cf7e 100644 --- a/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py +++ b/chainercv/links/model/fpn/faster_rcnn_fpn_resnet.py @@ -60,8 +60,8 @@ class FasterRCNNFPNResNet50(FasterRCNNFPNResNet): Args: n_fg_class (int): The number of classes excluding the background. pretrained_model (string): The weight file to be loaded. - This can take :obj:`'coco'`, `filepath` or :obj:`None`. - The default value is :obj:`None`. + This can take :obj:`'coco'`, `filepath` or :obj:`None`. + The default value is :obj:`None`. * :obj:`'coco'`: Load weights trained on train split of \ MS COCO 2017. \ diff --git a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py index 997b2b5f5b..1ead3866ec 100644 --- a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py +++ b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py @@ -41,20 +41,25 @@ def __init__(self, n_fg_class, min_size, max_size): ) -@testing.parameterize( - {'n_fg_class': 1, 'min_size': 200, 'max_size': 400, - 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, - {'n_fg_class': 1, 'min_size': 800, 'max_size': 133, - 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, - {'n_fg_class': 5, 'min_size': 200, 'max_size': 400, - 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, - {'n_fg_class': 5, 'min_size': 800, 'max_size': 133, - 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, - {'n_fg_class': 20, 'min_size': 200, 'max_size': 400, - 'in_shape': (3, 200, 50), 'expected_shape': (3, 400, 100)}, - {'n_fg_class': 20, 'min_size': 800, 'max_size': 133, - 'in_shape': (3, 480, 640), 'expected_shape': (3, 800, 1088)}, -) +@testing.parameterize(*testing.product_dict( + [ + {'n_fg_class': 1}, + {'n_fg_class': 5}, + {'n_fg_class': 20}, + ], + [ + { + 'in_sizes': [(480, 640), (320, 320)], + 'min_size': 800, 'max_size': 1333, + 'expected_shape': (800, 1088), + }, + { + 'in_sizes': [(200, 50), (400, 100)], + 'min_size': 200, 'max_size': 400, + 'expected_shape': (400, 100), + }, + ], +)) class TestFasterRCNN(unittest.TestCase): def setUp(self): @@ -128,19 +133,13 @@ def test_predict_gpu(self): self.link.to_gpu() assert_is_detection_link(self.link, self.n_fg_class) - def check_prepare(self): - x = _random_array(np, self.in_shape) - out, scales = self.link.prepare(x) + def test_prepare(self): + imgs = [_random_array(np, (3, s[0], s[1])) for s in self.in_sizes] + out, scales = self.link.prepare(imgs) self.assertIsInstance(out, np.ndarray) - self.assertEqual(out.shape, self.expected_shape) - - def test_prepare_cpu(self): - self.check_prepare() - - @attr.gpu - def test_prepare_gpu(self): - self.link.to_gpu() - self.check_prepare() + full_expected_shape = (len(self.in_sizes), + 3, self.expected_shape[0], self.expected_shape[1]) + self.assertEqual(out.shape, full_expected_shape) testing.run_module(__name__, __file__) From f1ad965c005954c9b19c49c5e5741712b070feb5 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 15:58:48 +0000 Subject: [PATCH 6/8] Fix size param to be a whole integer of _stride. --- tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py index 1ead3866ec..8fc4fe3c1e 100644 --- a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py +++ b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py @@ -55,8 +55,8 @@ def __init__(self, n_fg_class, min_size, max_size): }, { 'in_sizes': [(200, 50), (400, 100)], - 'min_size': 200, 'max_size': 400, - 'expected_shape': (400, 100), + 'min_size': 200, 'max_size': 320, + 'expected_shape': (320, 96), }, ], )) From 2f2d262140fb9096d4870a79bddf55f1afd1550f Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 17:31:48 +0000 Subject: [PATCH 7/8] Fix flake8 errors. --- .../model_tests/fpn_tests/test_faster_rcnn.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py index 8fc4fe3c1e..1d245ac0bd 100644 --- a/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py +++ b/tests/links_tests/model_tests/fpn_tests/test_faster_rcnn.py @@ -63,8 +63,9 @@ def __init__(self, n_fg_class, min_size, max_size): class TestFasterRCNN(unittest.TestCase): def setUp(self): - self.link = DummyFasterRCNN(n_fg_class=self.n_fg_class, - min_size=self.min_size, max_size=self.max_size) + self.link = DummyFasterRCNN(n_fg_class=self.n_fg_class, + min_size=self.min_size, + max_size=self.max_size) def test_use_preset(self): self.link.nms_thresh = 0 @@ -137,8 +138,9 @@ def test_prepare(self): imgs = [_random_array(np, (3, s[0], s[1])) for s in self.in_sizes] out, scales = self.link.prepare(imgs) self.assertIsInstance(out, np.ndarray) - full_expected_shape = (len(self.in_sizes), - 3, self.expected_shape[0], self.expected_shape[1]) + full_expected_shape = (len(self.in_sizes), 3, + self.expected_shape[0], + self.expected_shape[1]) self.assertEqual(out.shape, full_expected_shape) From 98e5058cab59cfb9d7850d4712691a10142c3767 Mon Sep 17 00:00:00 2001 From: Daniel Angelov Date: Tue, 12 Mar 2019 17:40:23 +0000 Subject: [PATCH 8/8] Add note about size. --- chainercv/links/model/fpn/faster_rcnn.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chainercv/links/model/fpn/faster_rcnn.py b/chainercv/links/model/fpn/faster_rcnn.py index dabfbd1812..c64a563db2 100644 --- a/chainercv/links/model/fpn/faster_rcnn.py +++ b/chainercv/links/model/fpn/faster_rcnn.py @@ -28,7 +28,9 @@ class FasterRCNN(chainer.Chain): Please refer to the documentation found there. min_size (int): A preprocessing paramter for :meth:`prepare`. Please refer to a docstring found for :meth:`prepare`. - max_size (int): A preprocessing paramter for :meth:`prepare`. + max_size (int): A preprocessing paramter for :meth:`prepare`. Note + that the result of :meth:`prepare` can exceed this size due to + alignment with stride. Parameters: nms_thresh (float): The threshold value