OpenCV C++中floodfill函数的未处理异常

fjnneemd  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(181)

我正在尝试泛色填充一个阈值化的图像。我创建了一个简单的泛色填充函数。该函数从第一张图像中找到白色,然后在另一张空白图像中填充它们的位置。这是一个递归函数,所以一旦它找到一个白点,它不会退出它,直到签署所有的斑点。函数首先检查像素的右侧,然后向下,然后向左,最后向上。

问题是,当我在floodfill函数中包含“up”部分时,它会在imshow函数中抛出异常。但当我删除它时,根本没有异常。我不知道为什么会导致这种情况。
例外情况:

Unhandled exception at 0x00007FF82DCCA2AF (opencv_world343d.dll) in DIP.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000002040E73FE0).

淹没填充功能:

void floodFill(cv::Mat src_8uc1,cv::Mat& index_8uc1,cv::Mat& done_8uc1,int y,int x,int index) {//recursive floodfill function
    
    cv::imshow("INDEX IN FLOODFILL", index_8uc1); //IT THROWS THE EXCEPTION RIGHT HERE!!!
    cv::waitKey(8);

    index_8uc1.at<unsigned char>(y, x) = index;
    
    //right
    if ((y < src_8uc1.rows) && (x+1 < src_8uc1.cols)) {
        if (src_8uc1.at<unsigned char>(y, x + 1) == 255) {
            if (index_8uc1.at<unsigned char>(y, x + 1) == 0) {
                x += 1;
                floodFill(src_8uc1, index_8uc1, done_8uc1, y, x, index);
            }
        }
        
    }

    //down
    if ((y+1 < src_8uc1.rows) && (x < src_8uc1.cols)) {
        if (src_8uc1.at<unsigned char>(y + 1, x) == 255) {
            if (index_8uc1.at<unsigned char>(y + 1, x) == 0) {
                y += 1;
                floodFill(src_8uc1, index_8uc1, done_8uc1, y, x, index);
            }
        }
    }

    //left
    if ((y < src_8uc1.rows) && (x - 1 < src_8uc1.cols)) {
        if (x > 0) {
            if (src_8uc1.at<unsigned char>(y, x - 1) == 255) {
                if (index_8uc1.at<unsigned char>(y, x - 1) == 0) {
                    x -= 1;
                    floodFill(src_8uc1, index_8uc1, done_8uc1, y, x, index);
                }
            }
        }

    }

    //up
    if ((y - 1 < src_8uc1.rows) && (x < src_8uc1.cols)) {
        if (y > 0) {
            if (src_8uc1.at<unsigned char>(y - 1, x) == 255) {
                if (index_8uc1.at<unsigned char>(y - 1, x) == 0) {
                    y -= 1;
                    floodFill(src_8uc1, index_8uc1, done_8uc1, y, x, index);
                }
            }
        }
    }
}

我定义图像的地方:

int main( int argc, char** argv )
{

    // Read image
    cv::Mat src = cv::imread("images2/train.png", cv::IMREAD_GRAYSCALE);
    cv::Mat dst2;

    // Thresholding with threshold value set 127
    threshold(src, dst2, 127, 255, cv::THRESH_BINARY);
    if (dst2.empty()) {
        printf("Unable to read input file (%s, %d).", __FILE__, __LINE__);
    }

    cv::Mat src_8uc1 = src.clone(); //FIRST IMAGE
    cv::Mat index_8uc1 = src.clone();
    index_8uc1 = cv::Mat::zeros(src.rows, src.cols, CV_8UC1); //indexed image (0)
    cv::Mat done_8uc1 =src.clone(); //result

    int index = 40;

    for (int y = 0; y <= src_8uc1.size().height; y++)
        for (int x = 0; x <= src_8uc1.size().width; x++)
        {
            if ((y < src_8uc1.rows) && (x < src_8uc1.cols)) {
                if (dst2.at<uchar>(y, x) == 255) {
                    if (index_8uc1.at<unsigned char>(y, x) == 0) {
                        //done_8uc1.at<uchar>((x, y))= 255;
                        floodFill(dst2, index_8uc1, done_8uc1, y, x, index);
                        index += 1;
                    }
                }
            }
        }


    cv::waitKey(0); // wait until keypressed

}

------------------------------------更新!!!---------------------------------

这不是一个精确的解决方案,但我不得不通过增加调试器设置中的“堆栈保留大小”来绕过错误。

gab6jxml

gab6jxml1#

floodFill是一个递归函数。每次递归调用都会向堆栈添加一个帧。堆栈使用的最大深度取决于图像的大小。当堆栈超过其大小时,您将获得堆栈溢出异常。由于线程内的所有函数调用都共享堆栈,因此很可能在调用imshow时堆栈已经几乎满了。
1.您可以尝试减小图像大小,以验证这确实是问题的原因。
1.您可以尝试迭代实现而不是递归实现,以避免堆栈溢出。
1.为什么你需要在一个递归函数中调用imshow,这个函数被递归地调用了很多次?

相关问题