卷积函数在获取相对图像坐标的像素值时给出分割误差

Convolution function gives segmentation error while getting pixel value of relative image coordinates

我正在尝试用 C 编写一个 卷积函数 用于我的计算机视觉研究。 在此函数中,卷积图像中的每个像素都是 原始图像和滤波器内核的乘积 的总和,如 this image and this 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
}

我错过了什么吗?我的方法有什么问题?或者有更好的操作方法吗?

这显然是越界访问:

                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];
}