|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Tests for Panoptic Quality metric.""" |
|
|
|
from __future__ import absolute_import |
|
from __future__ import division |
|
from __future__ import print_function |
|
|
|
|
|
from absl.testing import absltest |
|
import numpy as np |
|
import six |
|
|
|
from deeplab.evaluation import panoptic_quality |
|
from deeplab.evaluation import test_utils |
|
|
|
|
|
|
|
_CLASS_COLOR_MAP = { |
|
(0, 0, 0): 0, |
|
(0, 0, 255): 1, |
|
(255, 0, 0): 2, |
|
(0, 255, 0): 3, |
|
(255, 0, 255): 4, |
|
(0, 255, 255): 5, |
|
(255, 255, 0): 6, |
|
} |
|
|
|
|
|
class PanopticQualityTest(absltest.TestCase): |
|
|
|
def test_perfect_match(self): |
|
categories = np.zeros([6, 6], np.uint16) |
|
instances = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 2, 2, 1, 1, 1], |
|
[1, 2, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=1, |
|
ignored_label=2, |
|
max_instances_per_category=16, |
|
offset=16) |
|
pq.compare_and_accumulate(categories, instances, categories, instances) |
|
np.testing.assert_array_equal(pq.iou_per_class, [2.0]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [2]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [0]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [0]) |
|
np.testing.assert_array_equal(pq.result_per_category(), [1.0]) |
|
self.assertEqual(pq.result(), 1.0) |
|
|
|
def test_totally_wrong(self): |
|
det_categories = np.array([ |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 1, 0, 0, 1, 0], |
|
[0, 1, 1, 1, 1, 0], |
|
[0, 1, 1, 1, 1, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
], |
|
dtype=np.uint16) |
|
gt_categories = 1 - det_categories |
|
instances = np.zeros([6, 6], np.uint16) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=2, |
|
ignored_label=2, |
|
max_instances_per_category=1, |
|
offset=16) |
|
pq.compare_and_accumulate(gt_categories, instances, det_categories, |
|
instances) |
|
np.testing.assert_array_equal(pq.iou_per_class, [0.0, 0.0]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [0, 0]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [1, 1]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [1, 1]) |
|
np.testing.assert_array_equal(pq.result_per_category(), [0.0, 0.0]) |
|
self.assertEqual(pq.result(), 0.0) |
|
|
|
def test_matches_by_iou(self): |
|
good_det_labels = np.array( |
|
[ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
gt_labels = np.array( |
|
[ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=1, |
|
ignored_label=2, |
|
max_instances_per_category=16, |
|
offset=16) |
|
pq.compare_and_accumulate( |
|
np.zeros_like(gt_labels), gt_labels, np.zeros_like(good_det_labels), |
|
good_det_labels) |
|
|
|
|
|
|
|
np.testing.assert_array_almost_equal(pq.iou_per_class, [28 / 30 + 6 / 8]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [2]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [0]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [0]) |
|
self.assertAlmostEqual(pq.result(), (28 / 30 + 6 / 8) / 2) |
|
|
|
bad_det_labels = np.array( |
|
[ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
|
|
pq.reset() |
|
pq.compare_and_accumulate( |
|
np.zeros_like(gt_labels), gt_labels, np.zeros_like(bad_det_labels), |
|
bad_det_labels) |
|
|
|
|
|
np.testing.assert_array_almost_equal(pq.iou_per_class, [27 / 32]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [1]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [1]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [1]) |
|
self.assertAlmostEqual(pq.result(), (27 / 32) * (1 / 2)) |
|
|
|
def test_wrong_instances(self): |
|
categories = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 2, 2, 1, 2, 2], |
|
[1, 2, 2, 1, 2, 2], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
predicted_instances = np.array([ |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 1, 1], |
|
[0, 0, 0, 0, 1, 1], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
], |
|
dtype=np.uint16) |
|
groundtruth_instances = np.zeros([6, 6], dtype=np.uint16) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=3, |
|
ignored_label=0, |
|
max_instances_per_category=10, |
|
offset=100) |
|
pq.compare_and_accumulate(categories, groundtruth_instances, categories, |
|
predicted_instances) |
|
|
|
np.testing.assert_array_equal(pq.iou_per_class, [0.0, 1.0, 0.0]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [0, 1, 0]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [0, 0, 1]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [0, 0, 2]) |
|
np.testing.assert_array_equal(pq.result_per_category(), [0, 1, 0]) |
|
self.assertAlmostEqual(pq.result(), 0.5) |
|
|
|
def test_instance_order_is_arbitrary(self): |
|
categories = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 2, 2, 1, 2, 2], |
|
[1, 2, 2, 1, 2, 2], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
predicted_instances = np.array([ |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 1, 1], |
|
[0, 0, 0, 0, 1, 1], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
], |
|
dtype=np.uint16) |
|
groundtruth_instances = np.array([ |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 1, 1, 0, 0, 0], |
|
[0, 1, 1, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0], |
|
], |
|
dtype=np.uint16) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=3, |
|
ignored_label=0, |
|
max_instances_per_category=10, |
|
offset=100) |
|
pq.compare_and_accumulate(categories, groundtruth_instances, categories, |
|
predicted_instances) |
|
|
|
np.testing.assert_array_equal(pq.iou_per_class, [0.0, 1.0, 2.0]) |
|
np.testing.assert_array_equal(pq.tp_per_class, [0, 1, 2]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [0, 0, 0]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [0, 0, 0]) |
|
np.testing.assert_array_equal(pq.result_per_category(), [0, 1, 1]) |
|
self.assertAlmostEqual(pq.result(), 1.0) |
|
|
|
def test_matches_expected(self): |
|
pred_classes = test_utils.read_segmentation_with_rgb_color_map( |
|
'team_pred_class.png', _CLASS_COLOR_MAP) |
|
pred_instances = test_utils.read_test_image( |
|
'team_pred_instance.png', mode='L') |
|
|
|
instance_class_map = { |
|
0: 0, |
|
47: 1, |
|
97: 1, |
|
133: 1, |
|
150: 1, |
|
174: 1, |
|
198: 2, |
|
215: 1, |
|
244: 1, |
|
255: 1, |
|
} |
|
gt_instances, gt_classes = test_utils.panoptic_segmentation_with_class_map( |
|
'team_gt_instance.png', instance_class_map) |
|
|
|
pq = panoptic_quality.PanopticQuality( |
|
num_categories=3, |
|
ignored_label=0, |
|
max_instances_per_category=256, |
|
offset=256 * 256) |
|
pq.compare_and_accumulate(gt_classes, gt_instances, pred_classes, |
|
pred_instances) |
|
np.testing.assert_array_almost_equal( |
|
pq.iou_per_class, [2.06104, 5.26827, 0.54069], decimal=4) |
|
np.testing.assert_array_equal(pq.tp_per_class, [1, 7, 1]) |
|
np.testing.assert_array_equal(pq.fn_per_class, [0, 1, 0]) |
|
np.testing.assert_array_equal(pq.fp_per_class, [0, 0, 0]) |
|
np.testing.assert_array_almost_equal(pq.result_per_category(), |
|
[2.061038, 0.702436, 0.54069]) |
|
self.assertAlmostEqual(pq.result(), 0.62156287) |
|
|
|
def test_merge_accumulates_all_across_instances(self): |
|
categories = np.zeros([6, 6], np.uint16) |
|
good_det_labels = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
gt_labels = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 2, 2, 2, 1], |
|
[1, 2, 2, 2, 2, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
|
|
good_pq = panoptic_quality.PanopticQuality( |
|
num_categories=1, |
|
ignored_label=2, |
|
max_instances_per_category=16, |
|
offset=16) |
|
for _ in six.moves.range(2): |
|
good_pq.compare_and_accumulate(categories, gt_labels, categories, |
|
good_det_labels) |
|
|
|
bad_det_labels = np.array([ |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 2, 2, 1], |
|
[1, 1, 1, 1, 1, 1], |
|
], |
|
dtype=np.uint16) |
|
|
|
bad_pq = panoptic_quality.PanopticQuality( |
|
num_categories=1, |
|
ignored_label=2, |
|
max_instances_per_category=16, |
|
offset=16) |
|
for _ in six.moves.range(2): |
|
bad_pq.compare_and_accumulate(categories, gt_labels, categories, |
|
bad_det_labels) |
|
|
|
good_pq.merge(bad_pq) |
|
|
|
np.testing.assert_array_almost_equal( |
|
good_pq.iou_per_class, [2 * (28 / 30 + 6 / 8) + 2 * (27 / 32)]) |
|
np.testing.assert_array_equal(good_pq.tp_per_class, [2 * 2 + 2]) |
|
np.testing.assert_array_equal(good_pq.fn_per_class, [2]) |
|
np.testing.assert_array_equal(good_pq.fp_per_class, [2]) |
|
self.assertAlmostEqual(good_pq.result(), 0.63177083) |
|
|
|
|
|
if __name__ == '__main__': |
|
absltest.main() |
|
|