OpenCV C++ 的洪水填充函数中出现 Stackoverflow 异常
我正在尝试填充阈值图像。我创建了一个简单的洪水填充函数。该函数从第一张图像中找到白点,然后将其位置填充到另一张空白图像中。这是一个递归函数,因此一旦找到白点,它就不会退出,直到对所有白点进行签名。函数首先检查像素的右侧,然后是下侧,然后是左侧,最后是上侧。
问题是当我将“up”部分包含到洪水填充函数中时,它会在 imshow 函数中引发异常。但当我删除它时,完全没有例外。我不知道为什么会导致这种情况。
例外:
Unhandled exception at 0x00007FF82DCCA2AF (opencv_world343d.dll) in DIP.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000002040E73FE0).
Floodfill 函数:
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
}
--------------------------------更新!! !-----------------------------------------
这不是一个精确的解决方案,但我必须通过增加“来绕过错误调试器设置中的“堆栈保留大小”。请参阅此处
I'm trying to floodfill a thresholded image. I created a simple floodfill function. The function, finds the white spots from first image and then flodfills their location in another blank image. It's a recursive function so once it finds a white spot, it do not exit it until sign all the spots. Function firstly checks the right of the pixel, then down side, then left and finally up side.
Problem is when I include the "up" section to the floodfill function, it throws an exception at imshow function. But when I deleted it, there is no exception at all. I have no idea why it causes this.
Exception:
Unhandled exception at 0x00007FF82DCCA2AF (opencv_world343d.dll) in DIP.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000002040E73FE0).
Floodfill function:
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);
}
}
}
}
}
And where I defined the images:
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
}
--------------------------------UPDATE!!!-----------------------------
It's not a exact solution but I had to bypass the error by increasing the "Stack reserve size" in the debugger settings. See here
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
floodFill
是一个递归函数。每次递归调用都会向堆栈添加一个帧。堆栈使用的最大深度取决于图像的大小。当堆栈超出其大小时,您将收到堆栈溢出异常。由于线程内的所有函数调用共享堆栈,因此很可能在调用 imshow 时堆栈已经几乎满了。您可以尝试减小图像大小,以验证这确实是问题的原因。
您可以尝试迭代实现而不是递归,以避免堆栈溢出。
为什么您需要从递归调用相当多时间的递归函数中调用 imshow ?
floodFill
is a recursive function. Each recursive call adds a frame to the stack. The maximum depth of the stack usage depends on the size of the image. When the stack exceeds it's size you'll get a stack overflow exception. Since all functions calls within a thread share the stack, it could very well be that by the time imshow is called the stack is already almost full.You can try to reduce the image size, to verify that this is indeed the cause of the problem.
You can try an iterative implementation instead of recursive to avoid stack overflow.
Why do you need to call imshow from within a recursive function that is called recursivly quite a lot of time anyway ?