Skip to content

xphoto inpaint crush #965

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

Closed
saedrna opened this issue Jan 22, 2017 · 7 comments · Fixed by #1128
Closed

xphoto inpaint crush #965

saedrna opened this issue Jan 22, 2017 · 7 comments · Fixed by #1128

Comments

@saedrna
Copy link
Contributor

saedrna commented Jan 22, 2017

System information (version)
  • OpenCV => 3.2
  • Operating System / Platform => Mac OS(installed with homebrew) and Windows(installed with cmake)
  • Compiler => clang(mac os) and msvc 2015 (windows)
Detailed description

Sometimes the xphoto::inpaint function will crash with exception Exception: EXC_BAD_ACCESS (code=1, address=0x11ef10ffc) . But not for all the images.

Steps to reproduce

I have upload a project with images below. And here is the code.

#include <iostream>
#include <string>
#include <vector>

#include <opencv2/core.hpp>
#include <opencv2/xphoto.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void inpaint_rgb() {
    string path_mask = "mask1.png";
    string path_gt = "1.png";
    string path_img = path_gt;
    string path_inpaint = "result-1.png";

    Mat gt = cv::imread(path_gt, cv::IMREAD_GRAYSCALE);
    Mat mask = cv::imread(path_mask, cv::IMREAD_GRAYSCALE);
    Mat img = cv::imread(path_img, cv::IMREAD_COLOR);

    img.setTo(cv::Scalar(0,0,0), mask == 255);
    Mat inpainted;
    mask = 255 - mask;
    cv::xphoto::inpaint(img, mask, inpainted, 0);
    cv::imwrite(path_inpaint, inpainted);
}

int main() {
    inpaint_rgb();
    return 0;
}

inpaint.zip

@savuor savuor self-assigned this Jan 23, 2017
@savuor
Copy link
Contributor

savuor commented Jan 23, 2017

@saedrna this code produces an error very rarely, usually it works with no problem.
Also I failed to reproduce this on Linux.
Will keep trying to catch a problem.

@saedrna
Copy link
Contributor Author

saedrna commented Jan 24, 2017

Yes, really weird. Because previously, when I debug this code, I came into exceptions and the code stop in somewhere in annf.hpp, in Visual Studio 2015. But today, (when I want to show you where is the code) the program runs fine.

Also on Mac, not all the images will produce the exception, when using a inpaint benchmark dataset.

I will keep you informed when I manage to locate an error.

Below is the location of error in XCode, because I do not know how to build opencv_contrib on Mac OS, only something about KDTree is shown here.
1

@saedrna
Copy link
Contributor Author

saedrna commented Jan 24, 2017

I have successfully build the debug version of opencv_contrib and here is more debug information.

The problem is located in the following function, and the value x itself is bad allocated. Although this is on Mac, I remember the problem is the same for Windows VS 2015.

class KDTreeComparator
    {
        const KDTree <Tp, cn> *main; // main class
        int dimIdx; // dimension to compare

    public:
        bool operator () (const int &x, const int &y) const
        {
            cv::Vec <Tp, cn> u = main->data[main->idx[x]];
            cv::Vec <Tp, cn> v = main->data[main->idx[y]];

            return  u[dimIdx] < v[dimIdx];
        }

        KDTreeComparator(const KDTree <Tp, cn> *_main, int _dimIdx)
            : main(_main), dimIdx(_dimIdx) {}
    };

2

This functor is used in the nth_element function, idx seems to a growing sequence and here is something not consistent. (left = 0, right = 153601). Because I do not quite understand the algorithm, I can not go any further. Hope this will help.

  std::nth_element(/**/
            idx.begin() +  _left,
            idx.begin() +    nth,
            idx.begin() + _right, comp
                         /**/);

3

@saedrna
Copy link
Contributor Author

saedrna commented Feb 10, 2017

Here is an dataset that will cause problem.

The problem is another space, where whs is 12 channel but kdtree requires 24, and crash in the constructor.
image

image

The code is below. And the dataset is attached.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>

#include <opencv2/core.hpp>
#include <opencv2/xphoto.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main() {

    string path_mask = "mask.tif";
    string path_image = "img.tif";

    Mat img = cv::imread(path_image, cv::IMREAD_UNCHANGED);
    Mat mask = cv::imread(path_mask, cv::IMREAD_UNCHANGED);

    Mat inpainted;
    xphoto::inpaint(img, mask, inpainted, 0);

    cv::imshow("inpaint", inpainted);
    cv::waitKey();

    return 0;
}

inpaint.zip

@savuor
Copy link
Contributor

savuor commented Apr 16, 2017

@saedrna I confirm the bug, it is reproduced, now investigating it

@kznsq
Copy link

kznsq commented Oct 13, 2018

Some issues were found in the inpaint code:

  1. I've found an issue with the using std::nth_element in the file "xphoto/src/annf.hpp".
    It seems like an inconsistency of sorting data because of using dependent data in main->idx while it is sorting.
    The issue can be fixed with making a copy of sorting data:
line 168:
std::vector<int> _idx(idx.begin(), idx.end());
        std::nth_element(/**/
            _idx.begin() +  _left,
            _idx.begin() +    nth,
            _idx.begin() + _right, comp
                         /**/);
        idx = _idx;
  1. Also there is a potential crash in the code if nTransform is greagter than amount.size():
line 283:
    std::partial_sort( amount.begin(), amount.begin() + nTransform,
        amount.end(), std::greater< std::pair<double, int> >() );

My fix:

line 283:
    int num = std::min((int)amount.size(), (int)nTransform);
    std::partial_sort( amount.begin(), amount.begin() + num,
        amount.end(), std::greater< std::pair<float, int> >() );

    transforms.resize(num);
    for (int i = 0; i < num; ++i)
    {
        int idx = amount[i].second;
        transforms[i] = cv::Point2i( shiftM[idx].x, shiftM[idx].y );
    }

@alalek
Copy link
Member

alalek commented Oct 13, 2018

@kznsq Feel free to prepare Pull Request (bugfix patches should go into 3.4 branch first)

shah-scalpel added a commit to shah-scalpel/opencv_contrib that referenced this issue Sep 19, 2021
xphoto inpaint shiftmap kdtree crush fix

opencv#965 (comment)
@shah-scalpel shah-scalpel mentioned this issue Sep 19, 2021
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants