简体   繁体   中英

2D convolution with a with a kernel which is not center originated

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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