Skip to content

Inpainting floating point values with Telea's algorithm gives unexpected results. #25404

@MK-3PP

Description

@MK-3PP

System Information

OpenCV version: 4.9.0
Operating System / Platform: Windows 10
Compiler & compiler version: MSVC 19.29.30148

Detailed description

Adapting the unit test from here (thanks, @asmorkalov!) to CV_32F data, inpainting a cv::Mat that has the same float value (128.0) on each known (= not to be inpainted) element does not yield the expected result with Telea's algorithm.
The Navier Stokes method gives the expected result.

Image:

128.00, 128.00, 128.00, 128.00, 128.00,
128.00,      0,      0,      0, 128.00,
128.00,      0,      0,      0, 128.00,
128.00,      0,      0,      0, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00

Mask:

0, 0,   0,   0,   0,
0, 255, 255, 255, 0,
0, 255, 255, 255, 0,
0, 255, 255, 255, 0,
0, 0,   0,   0,   0

Expected/Navier Stokes:

128.00, 128.00, 128.00, 128.00, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00

Telea:

128.00, 128.00, 128.00, 128.00, 128.00,
128.00, 129.50, 128.78, 130.18, 128.00,
128.00, 128.78, 127.55, 128.14, 128.00,
128.00, 130.18, 127.50, 129.55, 128.00,
128.00, 128.00, 128.00, 128.00, 128.00

I could not determine if this is an artifact produced by Telea's algorithm itself or a erroneous implementation in OpenCV.
An indication for an error is the lack of rotational symmetry, which I would expect from a general purpose algorithm.

Steps to reproduce

Since the Issue with top and left borders being not inpainted correctly is not yet fixed, a workaround is added. The calls to inpaint_25389_workaround can be replaced with cv::inpaint once the fix is through.

// Workaround for https://github.com/opencv/opencv/issues/25389
void inpaint_25389_workaround(cv::Mat const& src, cv::Mat const& mask, cv::Mat& dst, double inpaint_radius, int flags) {
    cv::Mat bordered_src, bordered_mask;
    cv::copyMakeBorder(src, bordered_src, 1, 0, 1, 0, cv::BORDER_CONSTANT, 0);
    cv::copyMakeBorder(mask, bordered_mask, 1, 0, 1, 0, cv::BORDER_CONSTANT, 1);
    cv::inpaint(bordered_src, bordered_mask, dst, inpaint_radius, flags);
    dst = dst(cv::Rect(1, 1, dst.cols - 1, dst.rows - 1));
}

TEST(Photo_InpaintSmallBorders32F, regression)
{
    cv::Mat img(5, 5, CV_32F);
    img = 128.f;
    img(cv::Rect(1, 1, 3, 3)) = 0;

    cv::Mat mask(5, 5, CV_8U);
    mask = 0;
    mask(cv::Rect(1, 1, 3, 3)) = 255;

    cv::Mat expected(5, 5, img.type());
    expected = 128.f;

    cv::Mat inpainted, diff;

    inpaint_25389_workaround(img, mask, inpainted, 1, cv::INPAINT_NS);
    cv::absdiff(inpainted, expected, diff);
    ASSERT_EQ(countNonZero(diff), 0);

    inpaint_25389_workaround(img, mask, inpainted, 1, cv::INPAINT_TELEA);
    cv::absdiff(inpainted, expected, diff);
    ASSERT_EQ(countNonZero(diff), 0);
}

Issue submission checklist

  • I report the issue, it's not a question
  • I checked the problem with documentation, FAQ, open issues, forum.opencv.org, Stack Overflow, etc and have not found any solution
  • I updated to the latest OpenCV version and the issue is still there
  • There is reproducer code and related data files (videos, images, onnx, etc)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions