Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

TST: Calculate RMS and diff image in C++#29102

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
QuLogic wants to merge1 commit intomatplotlib:main
base:main
Choose a base branch
Loading
fromQuLogic:cpp-rms
Open
Show file tree
Hide file tree
Changes fromall 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
13 changes: 4 additions & 9 deletionslib/matplotlib/testing/compare.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,7 +19,7 @@
from PIL import Image

import matplotlib as mpl
from matplotlib import cbook
from matplotlib import cbook, _image
from matplotlib.testing.exceptions import ImageComparisonFailure

_log = logging.getLogger(__name__)
Expand DownExpand Up@@ -398,7 +398,7 @@ def compare_images(expected, actual, tol, in_decorator=False):

The two given filenames may point to files which are convertible to
PNG via the `.converter` dictionary. The underlying RMS is calculated
with the `.calculate_rms` function.
in a similar way to the `.calculate_rms` function.

Parameters
----------
Expand DownExpand Up@@ -469,17 +469,12 @@ def compare_images(expected, actual, tol, in_decorator=False):
if np.array_equal(expected_image, actual_image):
return None

# convert to signed integers, so that the images can be subtracted without
# overflow
expected_image = expected_image.astype(np.int16)
actual_image = actual_image.astype(np.int16)

rms = calculate_rms(expected_image, actual_image)
rms, abs_diff = _image.calculate_rms_and_diff(expected_image, actual_image)

if rms <= tol:
return None

save_diff_image(expected, actual, diff_image)
Image.fromarray(abs_diff).save(diff_image, format="png")

results = dict(rms=rms, expected=str(expected),
actual=str(actual), diff=str(diff_image), tol=tol)
Expand Down
75 changes: 75 additions & 0 deletionssrc/_image_wrapper.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

#include <algorithm>

#include "_image_resample.h"
#include "py_converters.h"

Expand DownExpand Up@@ -200,6 +202,76 @@
}


// This is used by matplotlib.testing.compare to calculate RMS and a difference image.
static py::tuple
calculate_rms_and_diff(py::array_t<unsigned char> expected_image,
py::array_t<unsigned char> actual_image)
{
if (expected_image.ndim() != 3) {
auto exceptions = py::module_::import("matplotlib.testing.exceptions");

Check warning on line 211 in src/_image_wrapper.cpp

View check run for this annotation

Codecov/ codecov/patch

src/_image_wrapper.cpp#L211

Added line #L211 was not covered by tests
auto ImageComparisonFailure = exceptions.attr("ImageComparisonFailure");
py::set_error(
ImageComparisonFailure,
"Expected image must be 3-dimensional, but is {ndim}-dimensional"_s.format(
"ndim"_a=expected_image.ndim()));
throw py::error_already_set();
}

if (actual_image.ndim() != 3) {
auto exceptions = py::module_::import("matplotlib.testing.exceptions");

Check warning on line 221 in src/_image_wrapper.cpp

View check run for this annotation

Codecov/ codecov/patch

src/_image_wrapper.cpp#L221

Added line #L221 was not covered by tests
auto ImageComparisonFailure = exceptions.attr("ImageComparisonFailure");
py::set_error(
ImageComparisonFailure,
"Actual image must be 3-dimensional, but is {ndim}-dimensional"_s.format(
"ndim"_a=actual_image.ndim()));
throw py::error_already_set();
}

auto height = expected_image.shape(0);
auto width = expected_image.shape(1);
auto depth = expected_image.shape(2);

if (height != actual_image.shape(0) || width != actual_image.shape(1) ||
depth != actual_image.shape(2)) {
auto exceptions = py::module_::import("matplotlib.testing.exceptions");

Check warning on line 236 in src/_image_wrapper.cpp

View check run for this annotation

Codecov/ codecov/patch

src/_image_wrapper.cpp#L236

Added line #L236 was not covered by tests
auto ImageComparisonFailure = exceptions.attr("ImageComparisonFailure");
py::set_error(
ImageComparisonFailure,
"Image sizes do not match expected size: {expected_image.shape} "_s
"actual size {actual_image.shape}"_s.format(
"expected_image"_a=expected_image, "actual_image"_a=actual_image));
throw py::error_already_set();
}
auto expected = expected_image.unchecked<3>();
auto actual = actual_image.unchecked<3>();

py::ssize_t diff_dims[3] = {height, width, 3};
py::array_t<unsigned char> diff_image(diff_dims);
auto diff = diff_image.mutable_unchecked<3>();

double total = 0.0;
for (auto i = 0; i < height; i++) {
for (auto j = 0; j < width; j++) {
for (auto k = 0; k < depth; k++) {
auto pixel_diff = static_cast<double>(expected(i, j, k)) -
static_cast<double>(actual(i, j, k));

total += pixel_diff*pixel_diff;

if (k != 3) { // Hard-code a fully solid alpha channel by omitting it.
diff(i, j, k) = static_cast<unsigned char>(std::clamp(
abs(pixel_diff) * 10, // Expand differences in luminance domain.
0.0, 255.0));
}
}
}
}
total = total / (width * height * depth);

return py::make_tuple(sqrt(total), diff_image);
}


PYBIND11_MODULE(_image, m, py::mod_gil_not_used())
{
py::enum_<interpolation_e>(m, "_InterpolationType")
Expand DownExpand Up@@ -232,4 +304,7 @@
"norm"_a = false,
"radius"_a = 1,
image_resample__doc__);

m.def("calculate_rms_and_diff", &calculate_rms_and_diff,
"expected_image"_a, "actual_image"_a);
}
Loading

[8]ページ先頭

©2009-2025 Movatter.jp