带有内核的二维卷积,该内核不是中心发起的 [英] 2D convolution with a with a kernel which is not center originated

查看:166
本文介绍了带有内核的二维卷积,该内核不是中心发起的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用高斯内核对图像进行二维卷积,而高斯内核不是由公式给出的中心起源:

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)

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

让我们说内核的中心是(1,1)代替(0,0)。我应该如何更改以下代码以生成内核和卷积?

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. 使用它是空间不变属性。

    为此,只需使用常规卷积滤波器计算图像(使用 conv2 更好地完成imfilter )然后移动结果。

    您应该注意您要使用的边界条件(参见 imfilter 属性)。

  2. 具体计算移位结果。

    您可以按照建议循环执行此操作,或者更轻松地创建非对称内核并仍然使用 imfilter conv2

  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.



示例代码(MATLAB)



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.

享受。

这篇关于带有内核的二维卷积,该内核不是中心发起的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆