Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor image::compare #1863

Merged
merged 5 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/F3DStarter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ int F3DStarter::Start(int argc, char** argv)
f3d::image diff;
double error;
const double& threshold = this->Internals->AppOptions.RefThreshold;
if (!img.compare(ref, threshold, error))
if (img.compare(ref) > threshold)
{
if (output.empty())
{
Expand Down
3 changes: 1 addition & 2 deletions examples/libf3d/cpp/render-image/check.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ int main(int argc, char** argv)
f3d::image img1(argv[2]);

// Compare them
double error;
return img0.compare(img1, 0.05, error) ? EXIT_SUCCESS : EXIT_FAILURE;
return img0.compare(img1) <= 0.05 ? EXIT_SUCCESS : EXIT_FAILURE;
}
4 changes: 1 addition & 3 deletions examples/libf3d/python/img-cmp/img-cmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
diff = f3d.Image()
error = 0.0

result = img_0.compare(img_1, 0.05, diff, error)

if result:
if img_0.compare(img_1) <= 0.05:
print("Images are identical")
else:
print("Images are different")
Expand Down
11 changes: 4 additions & 7 deletions library/public/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,23 +135,20 @@ class F3D_EXPORT image
///@}

/**
* Compare current image to a reference using the provided threshold.
* If the comparison fails, ie. error is higher than the threshold,
* this outputs the resulting diff and error and return false,
* return true otherwise.
* Compare current image to a reference.
* The error is minimum between Minkownski and Wasserstein distance
* on a SSIM computation, as specified in VTK.
* Please note, due to possible arithmetic imprecision in the SSIM computation
* using a threshold of zero may return false with identical images.
* a non-zero value can be returned with identical images.
* Depending on the VTK version, another comparison algorithm may be used.
* Threshold should be in range [0, 1[, this returns false otherwise.
* Error value meaning is described below:
* 1e-14: Pixel perfect comparison.
* 0.04: Visually indistinguishable.
* 0.1: Small visible difference.
* 0.5: Comparable images.
* 1.0: Different type, size or number of components
*/
bool compare(const image& reference, double threshold, double& error) const;
double compare(const image& reference) const;

/**
* Save an image to the provided file path, used as is, in the specified format.
Expand Down
43 changes: 10 additions & 33 deletions library/src/image.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -344,39 +344,28 @@ void* image::getContent() const
}

//----------------------------------------------------------------------------
bool image::compare(const image& reference, double threshold, double& error) const
double image::compare(const image& reference) const
{
// Sanity check for threshold
if (threshold < 0 || threshold >= 1)
{
error = 1;
return false;
}

ChannelType type = this->getChannelType();
if (type != reference.getChannelType())
{
error = 1;
return false;
return 1.0;
}

unsigned int count = this->getChannelCount();
if (count != reference.getChannelCount())
{
error = 1;
return false;
return 1.0;
}

if (this->getWidth() != reference.getWidth() || this->getHeight() != reference.getHeight())
{
error = 1;
return false;
return 1.0;
}

if (this->getWidth() == 0 && this->getHeight() == 0)
{
error = 0;
return true;
return 0.0;
}

#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240729)
Expand Down Expand Up @@ -406,39 +395,27 @@ bool image::compare(const image& reference, double threshold, double& error) con
// Thanks to the checks above, this is always true
assert(scalars != nullptr);

double unused;
double error, unused;
vtkImageSSIM::ComputeErrorMetrics(scalars, error, unused);
return error <= threshold;
return error;
#else
threshold *= 1000;

vtkNew<vtkImageDifference> imDiff;
imDiff->SetThreshold(0);
imDiff->SetInputData(this->Internals->Image);
imDiff->SetImageData(reference.Internals->Image);
imDiff->UpdateInformation();
error = imDiff->GetThresholdedError();

if (error <= threshold)
{
imDiff->Update();
error = imDiff->GetThresholdedError();
}

bool ret = error <= threshold;
error /= 1000;
return ret;
double error = imDiff->GetThresholdedError();
return error / 1000.0;
#endif
}

//----------------------------------------------------------------------------
bool image::operator==(const image& reference) const
{
double error;
// XXX: We do not use 0 because even with identical images, rounding error, arithmetic imprecision
// or architecture issue may cause the value to not be 0. See:
// https://develop.openfoam.com/Development/openfoam/-/issues/2958
return this->compare(reference, 1e-14, error);
return this->compare(reference) <= 1e-14;
}

//----------------------------------------------------------------------------
Expand Down
5 changes: 3 additions & 2 deletions library/testing/TestSDKHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ static bool RenderTest(const f3d::image& img, const std::string& baselinePath,
}

f3d::image reference(baseline);
double error;

if (!img.compare(reference, threshold, error))
double error = img.compare(reference);

if (error > threshold)
{
std::cerr << "Current rendering difference with reference image " << baseline << " : " << error
<< " is higher than the threshold of " << threshold << std::endl;
Expand Down
46 changes: 16 additions & 30 deletions library/testing/TestSDKImage.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,8 @@ int TestSDKImage(int argc, char* argv[])
f3d::image baseline(testingDir + "/baselines/TestSDKImage.png");
if (generated != baseline)
{
double error;
generated.compare(baseline, 0, error);

std::cerr << "Generated image is different from the png baseline: " << error << std::endl;
std::cerr << "Generated image is different from the png baseline: "
<< generated.compare(baseline) << std::endl;
return EXIT_FAILURE;
}

Expand All @@ -151,10 +149,8 @@ int TestSDKImage(int argc, char* argv[])
f3d::image baselineTIF(testingDir + "/baselines/TestSDKImage.tif");
if (generated != baselineTIF)
{
double error;
generated.compare(baselineTIF, 0, error);
mwestphal marked this conversation as resolved.
Show resolved Hide resolved

std::cerr << "Generated image is different from the tif baseline: " << error << std::endl;
std::cerr << "Generated image is different from the tif baseline: "
<< generated.compare(baselineTIF) << std::endl;
return EXIT_FAILURE;
}*/

Expand All @@ -171,10 +167,8 @@ int TestSDKImage(int argc, char* argv[])
f3d::image baseline16(testingDir + "/baselines/TestSDKImage16.png");
if (generated16 != baseline16)
{
double error;
generated16.compare(baseline16, 0, error);

std::cerr << "generated short image is different from the baseline: " << error << std::endl;
std::cerr << "generated short image is different from the baseline: "
<< generated16.compare(baseline16) << std::endl;
return EXIT_FAILURE;
}

Expand All @@ -183,10 +177,8 @@ int TestSDKImage(int argc, char* argv[])
f3d::image baseline16TIF(testingDir + "/baselines/TestSDKImage16.tif");
if (generated16 != baseline16TIF)
{
double error;
generated16.compare(baseline16TIF, 0, error);
mwestphal marked this conversation as resolved.
Show resolved Hide resolved

std::cerr << "generated short image is different from the TIF baseline: " << error << std::endl;
std::cerr << "generated short image is different from the TIF baseline: "
<< generated16.compare(baseline16TIF) << std::endl;
return EXIT_FAILURE;
}*/

Expand All @@ -204,10 +196,8 @@ int TestSDKImage(int argc, char* argv[])

if (generated32 != baseline32)
{
double error;
generated32.compare(baseline32, 0, error);

std::cerr << "generated float image is different from the baseline: " << error << std::endl;
std::cerr << "generated float image is different from the baseline: "
<< generated32.compare(baseline32) << std::endl;
return EXIT_FAILURE;
}
#endif // F3D_SSIM_COMPARE
Expand Down Expand Up @@ -300,22 +290,18 @@ int TestSDKImage(int argc, char* argv[])
}

// Test image::compare dedicated code paths
double error;
test("compare images with different channel types",
!generated.compare(generated16, 0, error) && error == 1.);
test("compare images with different channel types", generated.compare(generated16) == 1.);

f3d::image generatedCount(width, height, channels + 1);
test("compare images with different channel count",
!generated.compare(generatedCount, 0, error) && error == 1.);
test("compare images with different channel count", generated.compare(generatedCount) == 1.);

f3d::image generatedSize(width + 1, height, channels);
test("compare images with different size",
!generated.compare(generatedSize, 0, error) && error == 1.);
test("compare images with different size", generated.compare(generatedSize) == 1.);

f3d::image empty(0, 0, 0);
test("compare empty images", empty.compare(empty, 0, error) && error == 0.);
test("compare with negative threshold", !empty.compare(empty, -1, error) && error == 1.);
test("compare with threshold == 1", !empty.compare(empty, 1, error) && error == 1.);
test("compare empty images", empty.compare(empty) == 0.);
test("compare with negative threshold", empty.compare(empty) == 1.);
test("compare with threshold == 1", empty.compare(empty) == 1.);

return test.result();
}
2 changes: 1 addition & 1 deletion python/testing/test_image_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ def test_compare_with_file():

error = 0.0

assert img.compare(f3d.Image(reference), 0.05, error)
assert img.compare(f3d.Image(reference)) <= 0.05
4 changes: 2 additions & 2 deletions python/testing/test_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_scene_memory():

error = 0.0

assert img.compare(f3d.Image(reference), 0.05, error)
assert img.compare(f3d.Image(reference)) < 0.05


def test_scene():
Expand Down Expand Up @@ -54,4 +54,4 @@ def test_scene():

error = 0.0

assert img.compare(f3d.Image(reference), 0.05, error)
assert img.compare(f3d.Image(reference)) < 0.05
Loading