【问题标题】:Convolution function gives segmentation error while getting pixel value of relative image coordinates卷积函数在获取相对图像坐标的像素值时会产生分割误差
【发布时间】:2020-11-11 23:35:52
【问题描述】:

我正在尝试用 C 语言编写一个卷积函数,用于我的计算机视觉研究。 在这个函数中,卷积图像中的每个像素都是原始图像和过滤器内核的乘积之和,如this imagethis gif

在下面的代码中,像素值是 floatget_pixel() 函数获取给定索引处的像素值。 set_pixel() 函数将值设置为给定的索引。

image convolve(image im, image filter) {
    // imx, imy, imc: indexes of image pixels
    // fix, fiy: indexes of filter pixels
    // rx, ry: relative indexes of pixels
    
    image convolved_img = make_image(im.w, im.h, im.c); // image with same dimensions
    float value = 0;                                    // pixel value
    int oxo = floor(filter.w / 2);                      // half of the kernel width
    int xox = floor(filter.h / 2);                      // half of the kernel height

    // Convolution Loop
    for(int imc = 0; imc < im.c; imc++) {               // for every channel
        for(int imx = 0; imx < im.w; imx++) {
            for(int imy = 0; imy < im.h; imy++) {       // for every pixel
                value = 0;
                for(int fix = 0; fix < filter.w; fix++) {
                    for(int fiy = 0; fiy < filter.h; fiy++) {
                        int rx = imx - oxo + fix;
                        int ry = imy - xox + fiy;
                        value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);
                    }
                }
                set_pixel(convolved_img, imx, imy, imc, value);
            }
        }
    }
    return convolved_img;
}

我收到分段错误(核心转储)错误。调试后我意识到它的原因是:

value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);

当我给出rxry 的固定值时,程序成功执行。在循环内部,我打印了imx, imy, fix, fiy, rx, ry 的值,一切正常,直到图像的一部分处理完毕;在不确定的循环时间之后,程序会无缘无故地崩溃。

我确定它不能与索引边界相关,因为我截断了 get_pixel() 函数内的索引,在该函数下方我从一长串浮点数中获取存储值。

float get_pixel(image im, int x, int y, int c) {
    if(x > im.w) {x = im.w;}
    else if(y > im.h) {y = im.h;}
    else if(c > im.c) {c = im.c;}
    else if(x < 0) {x = 0;}
    else if(y < 0) {y = 0;}
    else if(c < 0) {c = 0;}

    int index = (c * (im.h * im.w)) + (y * im.w) + x;
    return im.data[index];
}

以下是我将此操作视为伪代码的想法:

create convolved_image with same dimensions
for every pixel (imx, imy) in image {
    float value = 0;
    for every pixel (fix, fiy) in filter {
        // calculate relative pixel coordinates
        int rx = imx - (filter / 2) + fix;
        int ry = imy - (filter / 2) + fiy;
        value += filter(fix, fiy) * image(rx, ry);
    }
    set pixel of convolved_image to value
}

我错过了什么吗?我的方法有什么问题?或者有没有更好的方法来进行这种操作?

【问题讨论】:

  • 你用过调试器吗?它会立即准确地告诉您哪行代码触发了段错误。当程序崩溃时,您是否真的检查过index 的值? What is a debugger and how can it help me diagnose problems?。如果您仍需要帮助,请提供minimal verifiable example
  • "因为我截断了索引" 不,你没有。 1.{y = im.h;} 已经偏离 1。2.所有参数都可以超出范围。您最多只能修复其中的 1 个。您必须删除 else 关键字并检查所有条件。
  • 与您的段错误无关,但您的方法会导致多次拍摄边缘像素。而不是跳过图像外部的像素,而是取而代之的是边缘像素。不确定这是否是您想要的。

标签: c image-processing computer-vision convolution


【解决方案1】:

这显然是越界访问:

                for(int fix = 0; fix < filter.w; fix++) {
                    for(int fiy = 0; fiy < filter.h; fiy++) {
                        int rx = imx - oxo + fix;
                        int ry = imy - xox + fiy;
                        value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);
                    }
                }

imx 上升到 im.xfix 上升到 2*oxo 你显然比 im.x 大。 imy 也一样。

您尝试限制范围但不正确:

float get_pixel(image im, int x, int y, int c) {
    if(x > im.w) {x = im.w;}
    else if(y > im.h) {y = im.h;}
    else if(c > im.c) {c = im.c;}
    else if(x < 0) {x = 0;}
    else if(y < 0) {y = 0;}
    else if(c < 0) {c = 0;}

    int index = (c * (im.h * im.w)) + (y * im.w) + x;
    return im.data[index];
}

您忘记了所有参数都可能是错误的。你先停下来。 你也限制为 size+1 这也是错误的。

像这样改变:

float get_pixel(image im, int x, int y, int c) {
    if(x >= im.w) {x = im.w-1;}
    else if(x < 0) {x = 0;}

    if(y >= im.h) {y = im.h-1;}
    else if(y < 0) {y = 0;}

    if(c >= im.c) {c = im.c-1;}
    else if(c < 0) {c = 0;}

    int index = (c * (im.h * im.w)) + (y * im.w) + x;
    return im.data[index];
}

【讨论】:

  • 谢谢。这是一个菜鸟错误 :) 它知道 :)
猜你喜欢
  • 1970-01-01
  • 2019-09-18
  • 2016-02-09
  • 2014-02-26
  • 1970-01-01
  • 2020-01-14
  • 2022-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多