Mercurial > hg > orthanc
changeset 3504:18566f9e1831
unit testing new functions in ImageProcessing
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 27 Aug 2019 14:26:04 +0200 |
parents | 46cf170ba121 |
children | b2d4dd16dae8 |
files | Core/Images/ImageProcessing.cpp UnitTestsSources/ImageProcessingTests.cpp |
diffstat | 2 files changed, 311 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/Images/ImageProcessing.cpp Tue Aug 27 12:10:13 2019 +0200 +++ b/Core/Images/ImageProcessing.cpp Tue Aug 27 14:26:04 2019 +0200 @@ -1907,7 +1907,7 @@ { for (unsigned int k = 0; k < vertical.size(); k++) { - if (y < verticalAnchor) + if (y + k < verticalAnchor) { rows[k] = reinterpret_cast<const float*>(tmp.GetConstRow(0)); // Use top border }
--- a/UnitTestsSources/ImageProcessingTests.cpp Tue Aug 27 12:10:13 2019 +0200 +++ b/UnitTestsSources/ImageProcessingTests.cpp Tue Aug 27 14:26:04 2019 +0200 @@ -278,6 +278,7 @@ { PixelTraits<PixelFormat_Grayscale8>::PixelType p; ImageTraits<PixelFormat_Grayscale8>::GetPixel(p, image, x, y); + if (p != value) printf("%d %d\n", p, value); return p == value; } @@ -304,9 +305,11 @@ { PixelTraits<PixelFormat_RGB24>::PixelType p; ImageTraits<PixelFormat_RGB24>::GetPixel(p, image, x, y); - return (p.red_ == red && - p.green_ == green && - p.blue_ == blue); + bool ok = (p.red_ == red && + p.green_ == green && + p.blue_ == blue); + if (!ok) printf("%d,%d,%d %d,%d,%d\n", p.red_, p.green_, p.blue_, red, green, blue); + return ok; } @@ -467,3 +470,307 @@ ImageProcessing::Resize(target, source); } } + + +TEST(ImageProcessing, Convolution) +{ + std::vector<float> k1(5, 1); + std::vector<float> k2(1, 1); + + { + Image image(PixelFormat_Grayscale8, 1, 1, false); + SetGrayscale8Pixel(image, 0, 0, 100); + ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); + ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); + ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); + ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); + } + + { + Image image(PixelFormat_RGB24, 1, 1, false); + SetRGB24Pixel(image, 0, 0, 10, 20, 30); + ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); + ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); + ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); + ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); + } + + { + Image dirac(PixelFormat_Grayscale8, 9, 1, false); + ImageProcessing::Set(dirac, 0); + SetGrayscale8Pixel(dirac, 4, 0, 100); + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 100)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 100)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0)); + } + } + + { + Image dirac(PixelFormat_Grayscale8, 1, 9, false); + ImageProcessing::Set(dirac, 0); + SetGrayscale8Pixel(dirac, 0, 4, 100); + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 20)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 100)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 100)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0)); + } + } + + { + Image dirac(PixelFormat_RGB24, 9, 1, false); + ImageProcessing::Set(dirac, 0); + SetRGB24Pixel(dirac, 4, 0, 100, 120, 140); + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 100, 120, 140)); + ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 100, 120, 140)); + ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0)); + } + } + + { + Image dirac(PixelFormat_RGB24, 1, 9, false); + ImageProcessing::Set(dirac, 0); + SetRGB24Pixel(dirac, 0, 4, 100, 120, 140); + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 20, 24, 28)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 100, 120, 140)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0)); + } + + { + std::auto_ptr<ImageAccessor> image(Image::Clone(dirac)); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 100, 120, 140)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0)); + } + } +} + + +TEST(ImageProcessing, SmoothGaussian5x5) +{ + /** + Test the point spread function, as can be seen in Octave: + g1 = [ 1 4 6 4 1 ]; + g1 /= sum(g1); + g2 = conv2(g1, g1'); + floor(conv2(diag([ 0 0 100 0 0 ]), g2, 'same')) % red/green channels + floor(conv2(diag([ 0 0 200 0 0 ]), g2, 'same')) % blue channel + **/ + + { + Image image(PixelFormat_Grayscale8, 5, 5, false); + ImageProcessing::Set(image, 0); + SetGrayscale8Pixel(image, 2, 2, 100); + ImageProcessing::SmoothGaussian5x5(image); + + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 2)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 0, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 1, 6)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 1, 9)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 1, 6)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 1, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 2, 2)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 2, 9)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 2, 14)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 2, 9)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 2, 2)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 3, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 3, 6)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 3, 9)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 3, 6)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 3, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 4, 0)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 4, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 4, 2)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 4, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 4, 0)); + } + + { + Image image(PixelFormat_RGB24, 5, 5, false); + ImageProcessing::Set(image, 0); + SetRGB24Pixel(image, 2, 2, 100, 100, 200); + ImageProcessing::SmoothGaussian5x5(image); + + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 0, 2, 2, 4)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 0, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 0, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 6, 6, 12)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 1, 9, 9, 18)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 1, 6, 6, 12)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 1, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 2, 2, 2, 4)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 2, 9, 9, 18)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 2, 14, 14, 28)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 2, 9, 9, 18)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 2, 2, 2, 4)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 3, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 3, 6, 6, 12)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 3, 9, 9, 18)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 3, 6, 6, 12)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 3, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 4, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 4, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 4, 2, 2, 4)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 4, 1, 1, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 4, 0, 0, 0)); + } +}