【发布时间】:2016-08-01 23:59:47
【问题描述】:
我想在频域中将 Lena 与自身进行卷积。 Here is an excerpt from a book. 建议卷积的输出应该如何:
我编写了以下应用程序来实现两个图像在频域中的卷积。我遵循的步骤如下:
- 将 Lena 转换为复数矩阵。
- 应用 FFT 获得复矩阵。
- 将两个复数矩阵逐个元素相乘(如果这是卷积的定义)。
- 将 IFFT 应用于乘法结果。
输出似乎不像预期的那样:
这里有两个问题:
- 输出仅包含黑色背景,其中心只有一个点。
- 执行卷积后原始图像失真。
。
注意。 FFT 和 I-FFT 与相同的库完美配合。
注 2。 There is a thread in SO 似乎在讨论同一主题。
。
源代码:
public static class Convolution
{
public static Complex[,] Convolve(Complex[,]image, Complex[,]mask)
{
Complex[,] convolve = null;
int imageWidth = image.GetLength(0);
int imageHeight = image.GetLength(1);
int maskWidth = mask.GetLength(0);
int maskeHeight = mask.GetLength(1);
if (imageWidth == maskWidth && imageHeight == maskeHeight)
{
FourierTransform ftForImage = new FourierTransform(image); ftForImage.ForwardFFT();
FourierTransform ftForMask = new FourierTransform(mask); ftForMask.ForwardFFT();
Complex[,] fftImage = ftForImage.FourierTransformedImageComplex;
Complex[,] fftKernel = ftForMask.FourierTransformedImageComplex;
Complex[,] fftConvolved = new Complex[imageWidth, imageHeight];
for (int i = 0; i < imageWidth; i++)
{
for (int j = 0; j < imageHeight; j++)
{
fftConvolved[i, j] = fftImage[i, j] * fftKernel[i, j];
}
}
FourierTransform ftForConv = new FourierTransform();
ftForConv.InverseFFT(fftConvolved);
convolve = ftForConv.GrayscaleImageComplex;
//convolve = fftConvolved;
}
else
{
throw new Exception("padding needed");
}
return convolve;
}
}
private void convolveButton_Click(object sender, EventArgs e)
{
Bitmap lena = inputImagePictureBox.Image as Bitmap;
Bitmap paddedMask = paddedMaskPictureBox.Image as Bitmap;
Complex[,] cLena = ImageDataConverter.ToComplex(lena);
Complex[,] cPaddedMask = ImageDataConverter.ToComplex(paddedMask);
Complex[,] cConvolved = Convolution.Convolve(cLena, cPaddedMask);
Bitmap convolved = ImageDataConverter.ToBitmap(cConvolved);
convolvedImagePictureBox.Image = convolved;
}
【问题讨论】:
-
我在您的代码中看到您需要掩码和图像具有相同的大小,这意味着一个被“填充”到另一个的长度。但是当您谈论通过 FFT 进行快速卷积时,“填充”意味着对输入图像进行“零填充”,这样当您执行
ifft( fft(a) * fft(b) )时,您会得到线性卷积而不是循环卷积——这就是 answer you link to 的要点。跨度> -
C#
Complex类型是否知道如何进行复数乘法,即(a + j*b) * (c + j*d) = (a*c - b*d) + j*(a*d + b*c)? -
即使您在 2D FFT 之前根本没有对两个图像进行零填充,您的结果(黑色背景,白色圆点)也非常错误。如果您将图像与其自身的扭曲版本进行卷积,您仍然会期望(可能扭曲的)指数衰减自相关,就像教科书所暗示的那样。
标签: c# image-processing fft convolution ifft