0

I want to do 2D convolution of an image with a Gaussian kernel which is not centre originated given by equation:

h(x-x', y-y') = exp(-((x-x')^2+(y-y'))/2*sigma)

Lets say the centre of kernel is (1,1) instead of (0,0). How should I change my following code for generation of kernel and for the convolution?

int krowhalf=krow/2, kcolhalf=kcol/2;
int sigma=1

// sum is for normalization
float sum = 0.0;

 // generate  kernel
for (int x = -krowhalf; x <= krowhalf; x++)
{
  for(int y = -kcolhalf; y <= kcolhalf; y++)
  {
    r = sqrtl((x-1)*(x-1) + (y-1)*(y-1));
    gKernel[x + krowhalf][y + kcolhalf] = exp(-(r*r)/(2*sigma));
    sum += gKernel[x + krowhalf][y + kcolhalf];
  }
}

//normalize the Kernel
for(int i = 0; i < krow; ++i)
  for(int j = 0; j < kcol; ++j)
    gKernel[i][j] /= sum;

float **convolve2D(float** in, float** out, int h, int v, float **kernel, int kCols, int kRows)
{
  int kCenterX = kCols / 2;
  int kCenterY = kRows / 2;
  int i,j,m,mm,n,nn,ii,jj;

  for(i=0; i < h; ++i)          // rows
  {
    for(j=0; j < v; ++j)        // columns
    {
      for(m=0; m < kRows; ++m)     // kernel rows
      {
        mm = kRows - 1 - m;      // row index of flipped kernel
        for(n=0; n < kCols; ++n) // kernel columns
        {
          nn = kCols - 1 - n;  // column index of flipped kernel

          //index of input signal, used for checking boundary
          ii = i + (m - kCenterY);
          jj = j + (n - kCenterX);

          // ignore input samples which are out of bound
          if( ii >= 0 && ii < h && jj >= 0 && jj < v )
            //out[i][j] += in[ii][jj] * (kernel[mm+nn*29]);
            out[i][j] += in[ii][jj] * (kernel[mm][nn]);
        }
      }
    }
  }
}
syockit
  • 5,747
  • 1
  • 24
  • 33
user3840066
  • 33
  • 1
  • 9
  • 1
    The good thing with convolution is is translation invariance. http://en.wikipedia.org/wiki/Convolution : translating the kernel by (x,y), translating the function by (x,y) or translating the result by (x,y) should give the same result. The only trouble is the boundary of the image. What about adding an extra layer, as wide as the kernel, with zero values ; translating the image ; using the convolution as usual and taking the interresting sub-image ? – francis Jul 17 '14 at 17:10
  • hello, thank you for your response. So you think i do not need to shift the origin? yes i will consider your idea of zero padding – user3840066 Jul 17 '14 at 19:51
  • Usually sigma is used as standard deviation instead of variance. Are you intentionally writing it as just `sigma` and not `sigma*sigma`? – syockit Oct 28 '15 at 04:33

1 Answers1

0

Since you're using the convolution operator you have 2 choices:

  1. Using it Spatial Invariant property.
    To so so, just calculate the image using regular convolution filter (Better done using either conv2 or imfilter) and then shift the result.
    You should mind the boundary condition you'd to employ (See imfilter properties).
  2. Calculate the shifted result specifically.
    You can do this by loops as you suggested or more easily create non symmetric kernel and still use imfilter or conv2.

Sample Code (MATLAB)

clear();

mInputImage = imread('3.png');
mInputImage = double(mInputImage) / 255;

mConvolutionKernel = zeros(3, 3);
mConvolutionKernel(2, 2) = 1;

mOutputImage01 = conv2(mConvolutionKernel, mInputImage);

mConvolutionKernelShifted   = [mConvolutionKernel, zeros(3, 150)];
mOutputImage02              = conv2(mConvolutionKernelShifted, mInputImage);

figure();
imshow(mOutputImage01);

figure();
imshow(mOutputImage02);

The tricky part is to know to "Crop" the second image in the same axis as the first.
Then you'll have a shifted image.
You can use any Kernel and any function which applies convolution.

Enjoy.

Royi
  • 4,640
  • 6
  • 46
  • 64
  • hi thank you for your reply. I do not currently have access to matlab so i am doing it in c . Do u think if I create a non symmetric kernel and then do the convolution as I am doing above , will it make a differece ? – user3840066 Jul 18 '14 at 07:53