From c514e1b49017b91b9565c6ecad1ca156a7bbbffe Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Mon, 31 Jan 2022 12:14:27 -0800 Subject: [PATCH] Small refactor on ImageComparison utils. (#7133) * Small refactor on ImageComparison utils. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> * Add aznumeric cast. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> * Correction on aznumeric cast. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> * Add unit test for new image comparison function. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> --- .../Code/Include/Atom/Utils/ImageComparison.h | 3 +++ .../Utils/Code/Source/ImageComparison.cpp | 19 +++++++++++-------- .../Utils/Code/Tests/ImageComparisonTests.cpp | 10 ++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImageComparison.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImageComparison.h index 4126e9eb4a..58c3a1bd48 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImageComparison.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImageComparison.h @@ -23,6 +23,9 @@ namespace AZ UnsupportedFormat }; + //! Calculates the maximum difference of the rgb channels between two image buffers. + int16_t CalcMaxChannelDifference(AZStd::array_view bufferA, AZStd::array_view bufferB, size_t index); + //! Compares two images and returns the RMS (root mean square) of the difference. //! @param buffer[A|B] the raw buffer of image data //! @param size[A|B] the dimensions of the image in the buffer diff --git a/Gems/Atom/Utils/Code/Source/ImageComparison.cpp b/Gems/Atom/Utils/Code/Source/ImageComparison.cpp index 0bad268ba5..6fcc316791 100644 --- a/Gems/Atom/Utils/Code/Source/ImageComparison.cpp +++ b/Gems/Atom/Utils/Code/Source/ImageComparison.cpp @@ -14,6 +14,16 @@ namespace AZ { namespace Utils { + int16_t CalcMaxChannelDifference(AZStd::array_view bufferA, AZStd::array_view bufferB, size_t index) + { + // We use the max error from a single channel instead of accumulating the error from each channel. + // This normalizes differences so that for example black vs red has the same weight as black vs yellow. + const int16_t diffR = static_cast(abs(aznumeric_cast(bufferA[index]) - aznumeric_cast(bufferB[index]))); + const int16_t diffG = static_cast(abs(aznumeric_cast(bufferA[index + 1]) - aznumeric_cast(bufferB[index + 1]))); + const int16_t diffB = static_cast(abs(aznumeric_cast(bufferA[index + 2]) - aznumeric_cast(bufferB[index + 2]))); + return AZ::GetMax(AZ::GetMax(diffR, diffG), diffB); + } + ImageDiffResultCode CalcImageDiffRms( AZStd::span bufferA, const RHI::Size& sizeA, RHI::Format formatA, AZStd::span bufferB, const RHI::Size& sizeB, RHI::Format formatB, @@ -67,14 +77,7 @@ namespace AZ for (size_t i = 0; i < bufferA.size(); i += BytesPerPixel) { - // We use the max error from a single channel instead of accumulating the error from each channel. - // This normalizes differences so that for example black vs red has the same weight as black vs yellow. - const int16_t diffR = static_cast(abs(aznumeric_cast(bufferA[i]) - aznumeric_cast(bufferB[i]))); - const int16_t diffG = static_cast(abs(aznumeric_cast(bufferA[i + 1]) - aznumeric_cast(bufferB[i + 1]))); - const int16_t diffB = static_cast(abs(aznumeric_cast(bufferA[i + 2]) - aznumeric_cast(bufferB[i + 2]))); - const int16_t maxDiff = AZ::GetMax(AZ::GetMax(diffR, diffG), diffB); - - const float finalDiffNormalized = maxDiff / 255.0f; + const float finalDiffNormalized = aznumeric_cast(CalcMaxChannelDifference(bufferA, bufferB, i)) / 255.0f; const float squared = finalDiffNormalized * finalDiffNormalized; if (diffScore) diff --git a/Gems/Atom/Utils/Code/Tests/ImageComparisonTests.cpp b/Gems/Atom/Utils/Code/Tests/ImageComparisonTests.cpp index 29861e1dbb..2ec71ff848 100644 --- a/Gems/Atom/Utils/Code/Tests/ImageComparisonTests.cpp +++ b/Gems/Atom/Utils/Code/Tests/ImageComparisonTests.cpp @@ -127,6 +127,16 @@ namespace UnitTest EXPECT_EQ(0.0f, diffScore); } + + TEST_F(ImageComparisonTests, CheckMaxChannelDifference) + { + const AZStd::vector imageA = { 255, 255, 255 }; + const AZStd::vector imageB = { 0, 125, 255 }; + const int16_t maxChannelDiff = 255; + const int16_t res = CalcMaxChannelDifference(imageA, imageB, 0); + EXPECT_EQ(res, maxChannelDiff); + } + TEST_F(ImageComparisonTests, CheckThreshold_SmallImagesWithDifferences) { AZ::RHI::Size size{2, 2, 1};