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

我的梦境 提交于 2019-12-11 18:46:23

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/24805251/2d-convolution-with-a-with-a-kernel-which-is-not-center-originated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!