简体   繁体   English

用C实现2D卷积

[英]Implementation of 2D Convolution in C

This is the function I have written for 2D Convolution in C: 这是我为C中的2D卷积编写的函数:

typedef struct PGMImage{
    int w;
    int h;
    int* data;
}GrayImage;

GrayImage Convolution2D(GrayImage image,GrayImage kernel){
    int aH,aW,bW,bH,r,c,x,y,xx,yy,X,Y;
    int temp = 0;
    GrayImage conv;
    CreateGrayImage(&conv,image.w,image.h);
    aH = image.h;
    aW = image.w;
    bH = kernel.h;
    bW = kernel.w;
    if(aW < bW || aH < bH){
        fprintf(stderr,"Image cannot have smaller dimensions than the blur kernel");
    }

    for(r = aH-1;r >= 0;r--){
        for(c = aW-1;c >= 0;c--){
            temp = 0;
            for(y = bH-1;y >= 0;y--){
                yy = bH - y -1;
                for(x = bW-1;x >= 0;x--){
                    xx = bW - x - 1;
                    X = c + (x - (bW/2));
                    Y = r + (y - (bH/2));
                    if(X >= 0 && X < aW && Y >= 0 && Y < aH){
                        temp += ((kernel.data[(yy*bW)+xx])*(image.data[(Y*aW)+X]));
                    }
                }
            }
            conv.data[(r*aW)+c] = temp;
        }
    }
    return conv;
}

I reproduced this function in Matlab and found that it overestimates the values for certain pixels as compared to the regular 2D Convolution function in Matlab (conv2D). 我在Matlab中重现了此函数,发现与Matlab中的常规2D卷积函数(conv2D)相比,它高估了某些像素的值。 I can't figure out where I am going wrong with the logic. 我无法弄清楚逻辑哪里出了问题。 Please help. 请帮忙。

EDIT: Here's the stock image I am using (512*512): https://drive.google.com/file/d/0B3qeTSY-DQRvdWxCZWw5RExiSjQ/view?usp=sharing 编辑:这是我正在使用的库存图片(512 * 512): https : //drive.google.com/file/d/0B3qeTSY-DQRvdWxCZWw5RExiSjQ/view?usp=sharing

Here's the kernel (3*3): https://drive.google.com/file/d/0B3qeTSY-DQRvdlQzamcyVmtLVW8/view?usp=sharing 这是内核(3 * 3): https : //drive.google.com/file/d/0B3qeTSY-DQRvdlQzamcyVmtLVW8/view?usp=sharing

On using the above function I get 使用上面的功能我得到

46465 46456 46564
45891 46137 46158
45781 46149 46030

But Matlab's conv2 gives me 但是Matlab的conv2给了我

46596 46618 46627
46073 46400 46149
45951 46226 46153

for the same pixels (rows:239-241,col:316:318) 对于相同的像素(行:239-241,col:316:318)

This is the Matlab code I am using to compare the values: 这是我用来比较值的Matlab代码:

pgm_img = imread('path\to\lena512.pgm');
kernel = imread('path\to\test_kernel.pgm');
sz_img = size(pgm_img);
sz_ker = size(kernel);
conv = conv2(double(pgm_img),double(kernel),'same');
pgm_img = padarray(pgm_img,floor(0.5*sz_ker),'both');
convolve = zeros(sz_img);
for i=floor(0.5*sz_ker(1))+1:floor(0.5*sz_ker(1))+sz_img(1)
    for j=floor(0.5*sz_ker(2))+1:floor(0.5*sz_ker(2))+sz_img(2)
        startX = j - floor(sz_ker(2)/2);
        startY = i - floor(sz_ker(1)/2);
        endX = j + floor(sz_ker(2)/2);
        endY = i + floor(sz_ker(1)/2);
        block = pgm_img(startY:endY,startX:endX);
        prod = double(block).*double(kernel);
        convolve(i-floor(0.5*sz_ker(1)),j-floor(0.5*sz_ker(2))) = sum(sum(prod));
    end
end
disp(conv(239:241,316:318));
disp(convolve(239:241,316:318));

One obvious difference is that your c code uses ints, while the matlab code uses doubles. 一个明显的区别是您的c代码使用ints,而matlab代码使用double。 Change your c code to use doubles, and see if the results are still different. 更改c代码以使用double,然后查看结果是否仍然不同。

I created Image Convolution library for simple cases of an image which is a simple 2D Float Array. 我为简单的2D浮点数组图像创建了图像卷积库。

The function supports arbitrary kernels and verified against MATLAB's implementation. 该函数支持任意内核,并已针对MATLAB的实现进行了验证。

So all needed on your side is calling it with your generated Kernel. 因此,您需要做的就是使用生成的内核调用它。

You can use its generated DLL inside MATLAB and see it yields same results as MATLAB's Image Convolution functions. 您可以在MATLAB中使用它生成的DLL,并看到它产生与MATLAB的图像卷积函数相同的结果。

Image Convolution - GitHub . 图像卷积-GitHub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM