summaryrefslogtreecommitdiff
path: root/silx/math/medianfilter/test/test_medianfilter.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/math/medianfilter/test/test_medianfilter.py')
-rw-r--r--silx/math/medianfilter/test/test_medianfilter.py446
1 files changed, 344 insertions, 102 deletions
diff --git a/silx/math/medianfilter/test/test_medianfilter.py b/silx/math/medianfilter/test/test_medianfilter.py
index 8a26d3a..a4c55b2 100644
--- a/silx/math/medianfilter/test/test_medianfilter.py
+++ b/silx/math/medianfilter/test/test_medianfilter.py
@@ -1,5 +1,5 @@
# coding: utf-8
-# /*##########################################################################
+# ##########################################################################
# Copyright (C) 2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
-# ############################################################################*/
+# ############################################################################
"""Tests of the median filter"""
__authors__ = ["H. Payno"]
@@ -29,8 +29,9 @@ __date__ = "02/05/2017"
import unittest
import numpy
-import os
from silx.math.medianfilter import medfilt2d
+from silx.math.medianfilter.medianfilter import reflect, mirror
+from silx.math.medianfilter.medianfilter import MODES as silx_mf_modes
from silx.test.utils import ParametricTestCase
try:
import scipy
@@ -43,17 +44,23 @@ else:
import logging
_logger = logging.getLogger(__name__)
+RANDOM_FLOAT_MAT = numpy.array([
+ [0.05564293, 0.62717157, 0.75002406, 0.40555336, 0.70278975],
+ [0.76532598, 0.02839148, 0.05272484, 0.65166994, 0.42161216],
+ [0.23067427, 0.74219128, 0.56049024, 0.44406320, 0.28773158],
+ [0.81025249, 0.20303021, 0.68382382, 0.46372299, 0.81281709],
+ [0.94691602, 0.07813661, 0.81651256, 0.84220106, 0.33623165]])
+
+RANDOM_INT_MAT = numpy.array([
+ [0, 5, 2, 6, 1],
+ [2, 3, 1, 7, 1],
+ [9, 8, 6, 7, 8],
+ [5, 6, 8, 2, 4]])
+
class TestMedianFilterNearest(ParametricTestCase):
"""Unit tests for the median filter in nearest mode"""
- random_mat = numpy.array([
- [0.05564293, 0.62717157, 0.75002406, 0.40555336, 0.70278975],
- [0.76532598, 0.02839148, 0.05272484, 0.65166994, 0.42161216],
- [0.23067427, 0.74219128, 0.56049024, 0.44406320, 0.28773158],
- [0.81025249, 0.20303021, 0.68382382, 0.46372299, 0.81281709],
- [0.94691602, 0.07813661, 0.81651256, 0.84220106, 0.33623165]])
-
def testFilter3_100(self):
"""Test median filter on a 10x10 matrix with a 3x3 kernel."""
dataIn = numpy.arange(100, dtype=numpy.int32)
@@ -61,7 +68,8 @@ class TestMedianFilterNearest(ParametricTestCase):
dataOut = medfilt2d(image=dataIn,
kernel_size=(3, 3),
- conditional=False)
+ conditional=False,
+ mode='nearest')
self.assertTrue(dataOut[0, 0] == 1)
self.assertTrue(dataOut[9, 0] == 90)
self.assertTrue(dataOut[9, 9] == 98)
@@ -72,7 +80,7 @@ class TestMedianFilterNearest(ParametricTestCase):
self.assertTrue(dataOut[4, 4] == 44)
def testFilter3_9(self):
- "Test median filter on a 3x3 matrix a 3x3 kernel."
+ "Test median filter on a 3x3 matrix with a 3x3 kernel."
dataIn = numpy.array([0, -1, 1,
12, 6, -2,
100, 4, 12],
@@ -80,7 +88,8 @@ class TestMedianFilterNearest(ParametricTestCase):
dataIn = dataIn.reshape((3, 3))
dataOut = medfilt2d(image=dataIn,
kernel_size=(3, 3),
- conditional=False)
+ conditional=False,
+ mode='nearest')
self.assertTrue(dataOut.shape == dataIn.shape)
self.assertTrue(dataOut[1, 1] == 4)
self.assertTrue(dataOut[0, 0] == 0)
@@ -95,146 +104,379 @@ class TestMedianFilterNearest(ParametricTestCase):
dataOut = medfilt2d(image=dataIn,
kernel_size=(1, 1),
- conditional=False)
+ conditional=False,
+ mode='nearest')
self.assertTrue(numpy.array_equal(dataIn, dataOut))
- def testInputDataIsNotModify(self):
- """Make sure input data is not modify by the median filter"""
- dataIn = numpy.arange(100, dtype=numpy.int32)
- dataIn = dataIn.reshape((10, 10))
- dataInCopy = dataIn.copy()
-
- medfilt2d(image=dataIn,
- kernel_size=(3, 3),
- conditional=False)
- self.assertTrue(numpy.array_equal(dataIn, dataInCopy))
-
- def testThreads(self):
- """Make sure the result doesn't depends on the number of threads used
- """
- dataIn = numpy.random.rand(100, 100)
-
- former = os.environ.get("OMP_NUM_THREADS")
- os.environ["OMP_NUM_THREADS"] = "1"
- dataOut1Thr = medfilt2d(image=dataIn,
- kernel_size=(3, 3),
- conditional=False,
- )
- os.environ["OMP_NUM_THREADS"] = "2"
- dataOut2Thr = medfilt2d(image=dataIn,
- kernel_size=(3, 3),
- conditional=False)
- os.environ["OMP_NUM_THREADS"] = "4"
- dataOut4Thr = medfilt2d(image=dataIn,
- kernel_size=(3, 3),
- conditional=False)
- os.environ["OMP_NUM_THREADS"] = "8"
- dataOut8Thr = medfilt2d(image=dataIn,
- kernel_size=(3, 3),
- conditional=False)
- if former is None:
- os.environ.pop("OMP_NUM_THREADS")
- else:
- os.environ["OMP_NUM_THREADS"] = former
-
- self.assertTrue(numpy.array_equal(dataOut1Thr, dataOut2Thr))
- self.assertTrue(numpy.array_equal(dataOut1Thr, dataOut4Thr))
- self.assertTrue(numpy.array_equal(dataOut1Thr, dataOut8Thr))
-
def testFilter3Conditionnal(self):
- """Test that the conditional filter apply correctly"""
+ """Test that the conditional filter apply correctly in a 10x10 matrix
+ with a 3x3 kernel
+ """
dataIn = numpy.arange(100, dtype=numpy.int32)
dataIn = dataIn.reshape((10, 10))
dataOut = medfilt2d(image=dataIn,
kernel_size=(3, 3),
- conditional=True)
+ conditional=True,
+ mode='nearest')
self.assertTrue(dataOut[0, 0] == 1)
self.assertTrue(dataOut[0, 1] == 1)
self.assertTrue(numpy.array_equal(dataOut[1:8, 1:8], dataIn[1:8, 1:8]))
self.assertTrue(dataOut[9, 9] == 98)
- def testTypes(self):
- """Test that all needed types have their implementation of the median
- filter
- """
- for testType in [numpy.float32, numpy.float64, numpy.int16,
- numpy.uint16, numpy.int32, numpy.int64, numpy.uint64]:
- data = (numpy.random.rand(10, 10) * 65000).astype(testType)
- out = medfilt2d(image=data,
- kernel_size=(3, 3),
- conditional=False)
- self.assertTrue(out.dtype.type is testType)
-
def testFilter3_1D(self):
- """Simple test of a three by three kernel median filter"""
+ """Simple test of a 3x3 median filter on a 1D array"""
dataIn = numpy.arange(100, dtype=numpy.int32)
dataOut = medfilt2d(image=dataIn,
kernel_size=(5),
- conditional=False)
+ conditional=False,
+ mode='nearest')
self.assertTrue(dataOut[0] == 0)
self.assertTrue(dataOut[9] == 9)
self.assertTrue(dataOut[99] == 99)
- @unittest.skipUnless(scipy, "scipy not available")
+
+class TestMedianFilterReflect(ParametricTestCase):
+ """Unit test for the median filter in reflect mode"""
+
+ def testArange9(self):
+ """Test from a 3x3 window to RANDOM_FLOAT_MAT"""
+ img = numpy.arange(9, dtype=numpy.int32)
+ img = img.reshape(3, 3)
+ kernel = (3, 3)
+ res = medfilt2d(image=img,
+ kernel_size=kernel,
+ conditional=False,
+ mode='reflect')
+ self.assertTrue(
+ numpy.array_equal(res.ravel(), [1, 2, 2, 3, 4, 5, 6, 6, 7]))
+
+ def testRandom10(self):
+ """Test a (5, 3) window to a RANDOM_FLOAT_MAT"""
+ kernel = (5, 3)
+
+ thRes = numpy.array([
+ [0.23067427, 0.56049024, 0.56049024, 0.4440632, 0.42161216],
+ [0.23067427, 0.62717157, 0.56049024, 0.56049024, 0.46372299],
+ [0.62717157, 0.62717157, 0.56049024, 0.56049024, 0.4440632],
+ [0.76532598, 0.68382382, 0.56049024, 0.56049024, 0.42161216],
+ [0.81025249, 0.68382382, 0.56049024, 0.68382382, 0.46372299]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=False,
+ mode='reflect')
+
+ self.assertTrue(numpy.array_equal(thRes, res))
+
+ def testApplyReflect1D(self):
+ """Test the reflect function used for the median filter in reflect mode
+ """
+ # test for inside values
+ self.assertTrue(reflect(2, 3) == 2)
+ # test for boundaries values
+ self.assertTrue(reflect(3, 3) == 2)
+ self.assertTrue(reflect(4, 3) == 1)
+ self.assertTrue(reflect(5, 3) == 0)
+ self.assertTrue(reflect(6, 3) == 0)
+ self.assertTrue(reflect(7, 3) == 1)
+ self.assertTrue(reflect(-1, 3) == 0)
+ self.assertTrue(reflect(-2, 3) == 1)
+ self.assertTrue(reflect(-3, 3) == 2)
+ self.assertTrue(reflect(-4, 3) == 2)
+ self.assertTrue(reflect(-5, 3) == 1)
+ self.assertTrue(reflect(-6, 3) == 0)
+ self.assertTrue(reflect(-7, 3) == 0)
+
+ def testRandom10Conditionnal(self):
+ """Test the median filter in reflect mode and with the conditionnal
+ option"""
+ kernel = (3, 1)
+
+ thRes = numpy.array([
+ [0.05564293, 0.62717157, 0.75002406, 0.40555336, 0.70278975],
+ [0.23067427, 0.62717157, 0.56049024, 0.44406320, 0.42161216],
+ [0.76532598, 0.20303021, 0.56049024, 0.46372299, 0.42161216],
+ [0.81025249, 0.20303021, 0.68382382, 0.46372299, 0.33623165],
+ [0.94691602, 0.07813661, 0.81651256, 0.84220106, 0.33623165]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=True,
+ mode='reflect')
+ self.assertTrue(numpy.array_equal(thRes, res))
+
+
+class TestMedianFilterMirror(ParametricTestCase):
+ """Unit test for the median filter in mirror mode
+ """
+
+ def testApplyMirror1D(self):
+ """Test the reflect function used for the median filter in mirror mode
+ """
+ # test for inside values
+ self.assertTrue(mirror(2, 3) == 2)
+ # test for boundaries values
+ self.assertTrue(mirror(4, 4) == 2)
+ self.assertTrue(mirror(5, 4) == 1)
+ self.assertTrue(mirror(6, 4) == 0)
+ self.assertTrue(mirror(7, 4) == 1)
+ self.assertTrue(mirror(8, 4) == 2)
+ self.assertTrue(mirror(-1, 4) == 1)
+ self.assertTrue(mirror(-2, 4) == 2)
+ self.assertTrue(mirror(-3, 4) == 3)
+ self.assertTrue(mirror(-4, 4) == 2)
+ self.assertTrue(mirror(-5, 4) == 1)
+ self.assertTrue(mirror(-6, 4) == 0)
+
+ def testRandom10(self):
+ """Test a (5, 3) window to a random array"""
+ kernel = (3, 5)
+
+ thRes = numpy.array([
+ [0.05272484, 0.40555336, 0.42161216, 0.42161216, 0.42161216],
+ [0.56049024, 0.56049024, 0.4440632, 0.4440632, 0.4440632],
+ [0.56049024, 0.46372299, 0.46372299, 0.46372299, 0.46372299],
+ [0.68382382, 0.56049024, 0.56049024, 0.46372299, 0.56049024],
+ [0.68382382, 0.46372299, 0.68382382, 0.46372299, 0.68382382]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=False,
+ mode='mirror')
+
+ self.assertTrue(numpy.array_equal(thRes, res))
+
+ def testRandom10Conditionnal(self):
+ """Test the median filter in reflect mode and with the conditionnal
+ option"""
+ kernel = (1, 3)
+
+ thRes = numpy.array([
+ [0.62717157, 0.62717157, 0.62717157, 0.70278975, 0.40555336],
+ [0.02839148, 0.05272484, 0.05272484, 0.42161216, 0.65166994],
+ [0.74219128, 0.56049024, 0.56049024, 0.44406320, 0.44406320],
+ [0.20303021, 0.68382382, 0.46372299, 0.68382382, 0.46372299],
+ [0.07813661, 0.81651256, 0.81651256, 0.81651256, 0.84220106]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=True,
+ mode='mirror')
+
+ self.assertTrue(numpy.array_equal(thRes, res))
+
+
+class TestMedianFilterShrink(ParametricTestCase):
+ """Unit test for the median filter in mirror mode
+ """
+
+ def testRandom_3x3(self):
+ """Test the median filter in shrink mode and with the conditionnal
+ option"""
+ kernel = (3, 3)
+
+ thRes = numpy.array([
+ [0.62717157, 0.62717157, 0.62717157, 0.65166994, 0.65166994],
+ [0.62717157, 0.56049024, 0.56049024, 0.44406320, 0.44406320],
+ [0.74219128, 0.56049024, 0.46372299, 0.46372299, 0.46372299],
+ [0.74219128, 0.68382382, 0.56049024, 0.56049024, 0.46372299],
+ [0.81025249, 0.81025249, 0.68382382, 0.81281709, 0.81281709]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=False,
+ mode='shrink')
+
+ self.assertTrue(numpy.array_equal(thRes, res))
+
+ def testBounds(self):
+ """Test the median filter in shrink mode with 3 different kernels
+ which should return the same result due to the large values of kernels
+ used.
+ """
+ kernel1 = (1, 9)
+ kernel2 = (1, 11)
+ kernel3 = (1, 21)
+
+ thRes = numpy.array([[2, 2, 2, 2, 2],
+ [2, 2, 2, 2, 2],
+ [8, 8, 8, 8, 8],
+ [5, 5, 5, 5, 5]])
+
+ resK1 = medfilt2d(image=RANDOM_INT_MAT,
+ kernel_size=kernel1,
+ conditional=False,
+ mode='shrink')
+
+ resK2 = medfilt2d(image=RANDOM_INT_MAT,
+ kernel_size=kernel2,
+ conditional=False,
+ mode='shrink')
+
+ resK3 = medfilt2d(image=RANDOM_INT_MAT,
+ kernel_size=kernel3,
+ conditional=False,
+ mode='shrink')
+
+ self.assertTrue(numpy.array_equal(resK1, thRes))
+ self.assertTrue(numpy.array_equal(resK2, resK1))
+ self.assertTrue(numpy.array_equal(resK3, resK1))
+
+ def testRandom_3x3Conditionnal(self):
+ """Test the median filter in reflect mode and with the conditionnal
+ option"""
+ kernel = (3, 3)
+
+ thRes = numpy.array([
+ [0.05564293, 0.62717157, 0.62717157, 0.40555336, 0.65166994],
+ [0.62717157, 0.56049024, 0.05272484, 0.65166994, 0.42161216],
+ [0.23067427, 0.74219128, 0.56049024, 0.44406320, 0.46372299],
+ [0.81025249, 0.20303021, 0.68382382, 0.46372299, 0.81281709],
+ [0.81025249, 0.81025249, 0.81651256, 0.81281709, 0.81281709]])
+
+ res = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=True,
+ mode='shrink')
+
+ self.assertTrue(numpy.array_equal(res, thRes))
+
+ def testRandomInt(self):
+ """Test 3x3 kernel on RANDOM_INT_MAT
+ """
+ kernel = (3, 3)
+
+ thRes = numpy.array([[3, 2, 5, 2, 6],
+ [5, 3, 6, 6, 7],
+ [6, 6, 6, 6, 7],
+ [8, 8, 7, 7, 7]])
+
+ resK1 = medfilt2d(image=RANDOM_INT_MAT,
+ kernel_size=kernel,
+ conditional=False,
+ mode='shrink')
+
+ self.assertTrue(numpy.array_equal(resK1, thRes))
+
+
+class TestGeneralExecution(ParametricTestCase):
+ """Some general test on median filter application"""
+
+ def testTypes(self):
+ """Test that all needed types have their implementation of the median
+ filter
+ """
+ for mode in silx_mf_modes:
+ for testType in [numpy.float32, numpy.float64, numpy.int16,
+ numpy.uint16, numpy.int32, numpy.int64,
+ numpy.uint64]:
+ with self.subTest(mode=mode, type=testType):
+ data = (numpy.random.rand(10, 10) * 65000).astype(testType)
+ out = medfilt2d(image=data,
+ kernel_size=(3, 3),
+ conditional=False,
+ mode=mode)
+ self.assertTrue(out.dtype.type is testType)
+
+ def testInputDataIsNotModify(self):
+ """Make sure input data is not modify by the median filter"""
+ dataIn = numpy.arange(100, dtype=numpy.int32)
+ dataIn = dataIn.reshape((10, 10))
+ dataInCopy = dataIn.copy()
+
+ for mode in silx_mf_modes:
+ with self.subTest(mode=mode):
+ medfilt2d(image=dataIn,
+ kernel_size=(3, 3),
+ conditional=False,
+ mode=mode)
+ self.assertTrue(numpy.array_equal(dataIn, dataInCopy))
+
+
+def _getScipyAndSilxCommonModes():
+ """return the mode which are comparable between silx and scipy"""
+ modes = silx_mf_modes.copy()
+ del modes['shrink']
+ return modes
+
+
+@unittest.skipUnless(scipy is not None, "scipy not available")
+class TestVsScipy(ParametricTestCase):
+ """Compare scipy.ndimage.median_filter vs silx.math.medianfilter
+ on comparable
+ """
def testWithArange(self):
+ """Test vs scipy with different kernels on arange matrix"""
data = numpy.arange(10000, dtype=numpy.int32)
data = data.reshape(100, 100)
kernels = [(3, 7), (7, 5), (1, 1), (3, 3)]
+ modesToTest = _getScipyAndSilxCommonModes()
for kernel in kernels:
- with self.subTest(kernel=kernel):
- resScipy = scipy.ndimage.median_filter(input=data,
- size=kernel,
- mode='nearest')
- resSilx = medfilt2d(image=data,
- kernel_size=kernel,
- conditional=False)
-
- self.assertTrue(numpy.array_equal(resScipy, resSilx))
+ for mode in modesToTest:
+ with self.subTest(kernel=kernel, mode=mode):
+ resScipy = scipy.ndimage.median_filter(input=data,
+ size=kernel,
+ mode=mode)
+ resSilx = medfilt2d(image=data,
+ kernel_size=kernel,
+ conditional=False,
+ mode=mode)
+
+ self.assertTrue(numpy.array_equal(resScipy, resSilx))
- @unittest.skipUnless(scipy, "scipy not available")
def testRandomMatrice(self):
+ """Test vs scipy with different kernels on RANDOM_FLOAT_MAT"""
kernels = [(3, 7), (7, 5), (1, 1), (3, 3)]
+ modesToTest = _getScipyAndSilxCommonModes()
for kernel in kernels:
- with self.subTest(kernel=kernel):
- resScipy = scipy.ndimage.median_filter(input=self.random_mat,
- size=kernel,
- mode='nearest')
+ for mode in modesToTest:
+ with self.subTest(kernel=kernel, mode=mode):
+ resScipy = scipy.ndimage.median_filter(input=RANDOM_FLOAT_MAT,
+ size=kernel,
+ mode=mode)
- resSilx = medfilt2d(image=self.random_mat,
- kernel_size=kernel,
- conditional=False)
+ resSilx = medfilt2d(image=RANDOM_FLOAT_MAT,
+ kernel_size=kernel,
+ conditional=False,
+ mode=mode)
- self.assertTrue(numpy.array_equal(resScipy, resSilx))
+ self.assertTrue(numpy.array_equal(resScipy, resSilx))
- @unittest.skipUnless(scipy, "scipy not available")
def testAscentOrLena(self):
+ """Test vs scipy with """
if hasattr(scipy.misc, 'ascent'):
img = scipy.misc.ascent()
else:
img = scipy.misc.lena()
kernels = [(3, 1), (3, 5), (5, 9), (9, 3)]
+ modesToTest = _getScipyAndSilxCommonModes()
+
for kernel in kernels:
- with self.subTest(kernel=kernel):
- resScipy = scipy.ndimage.median_filter(input=img,
- size=kernel,
- mode='nearest')
+ for mode in modesToTest:
+ with self.subTest(kernel=kernel, mode=mode):
+ resScipy = scipy.ndimage.median_filter(input=img,
+ size=kernel,
+ mode=mode)
- resSilx = medfilt2d(image=img,
- kernel_size=kernel,
- conditional=False)
+ resSilx = medfilt2d(image=img,
+ kernel_size=kernel,
+ conditional=False,
+ mode=mode)
- self.assertTrue(numpy.array_equal(resScipy, resSilx))
+ self.assertTrue(numpy.array_equal(resScipy, resSilx))
def suite():
test_suite = unittest.TestSuite()
- for test in [TestMedianFilterNearest, ]:
+ for test in [TestGeneralExecution, TestVsScipy,
+ TestMedianFilterNearest, TestMedianFilterReflect,
+ TestMedianFilterMirror, TestMedianFilterShrink]:
test_suite.addTest(
unittest.defaultTestLoader.loadTestsFromTestCase(test))
return test_suite