我编写了以下代码来开发同态过滤器。
我认为(虽然我不确定)彩色图像被很好地过滤了。
如果是灰度图像,
为什么内核总是绿色?
同样,滤镜被认为可以锐化图像。但是,它没有这样做。
可能出了什么问题?
。
。
源代码:
Here is the Github repository.
public class HomomorphicFilter
{
public HomoMorphicKernel Kernel = null;
public bool IsPadded { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public double RH { get; set; }
public double RL { get; set; }
public double Sigma { get; set; }
public double Slope { get; set; }
public int PaddedWidth { get; set; }
public int PaddedHeight { get; set; }
public Bitmap KernelBitmap
{
get
{
if (IsPadded)
{
return Kernel.PaddedKernelBitmap;
}
else
{
return Kernel.KernelBitmap;
}
}
}
#region private methods
private int[,] Apply8bit(int[,] imageData2d)
{
Complex[,] imageData2dShiftFftCplx = FourierShifter.ShiftFft(FourierTransform.ForwardFFT(ImageDataConverter.ToComplex(imageData2d)));
Complex[,] fftShiftedFiltered = null;
if (IsPadded)
{
fftShiftedFiltered = Tools.Multiply(Kernel.PaddedKernel, imageData2dShiftFftCplx);
}
else
{
fftShiftedFiltered = Tools.Multiply(Kernel.Kernel, imageData2dShiftFftCplx);
}
return ImageDataConverter.ToInteger(FourierTransform.InverseFFT(FourierShifter.RemoveFFTShift(fftShiftedFiltered)));
}
private int[, ,] Apply3d(int[, ,] image3d)
{
int[, ,] filteredImage3d = new int[image3d.GetLength(0), image3d.GetLength(1), image3d.GetLength(2)];
int widtH = image3d.GetLength(1);
int heighT = image3d.GetLength(2);
int[,] imageData2d = new int[widtH, heighT];
for (int dimension = 0; dimension < 3; dimension++)
{
for (int i = 0; i <= widtH - 1; i++)
{
for (int j = 0; j <= heighT - 1; j++)
{
imageData2d[i, j] = image3d[dimension, i, j];
}
}
int[,] filteredImage2d = Apply8bit(imageData2d);
for (int i = 0; i <= widtH - 1; i++)
{
for (int j = 0; j <= heighT - 1; j++)
{
filteredImage3d[dimension, i, j] = filteredImage2d[i, j];
}
}
}
return filteredImage3d;
}
#endregion
public void Compute()
{
if (IsPadded)
{
if (Width >= PaddedWidth || Height >= PaddedHeight)
{
throw new Exception("PaddedWidth or PaddedHeight must be greater than Width or Height.");
}
}
Kernel = new HomoMorphicKernel();
Kernel.Width = Width;
Kernel.Height = Height;
Kernel.RH = RH;
Kernel.RL = RL;
Kernel.Sigma = Sigma;
Kernel.Slope = Slope;
Kernel.PaddedWidth = PaddedWidth;
Kernel.PaddedHeight = PaddedHeight;
Kernel.Compute();
}
public Bitmap Apply8bit(Bitmap image)
{
int[,] image2d = ImageDataConverter.ToInteger(image);
int[,] filtered = Apply8bit(image2d);
return ImageDataConverter.ToBitmap(filtered);
}
public Bitmap Apply32bitColor(Bitmap image)
{
int[, ,] image3d = ImageDataConverter.ToInteger3d_32bit(image);
int[, ,] filtered = Apply3d(image3d);
return ImageDataConverter.ToBitmap3d_32bit(filtered);
}
}
最佳答案
为什么内核总是绿色?
仅仅是因为执行从ImageDataConverter.ToBitmap32bitColor
调用的整数值内核HomoMorphicKernel.GetKernelBitmap
的转换函数显式地仅分配给RGBA单词的绿色和alpha分量:
for (int i = 0; i < bitmapData.Height; i++)
{
for (int j = 0; j < bitmapData.Width; j++)
{
address[0] = 0; //<=== No red
address[1] = (byte)image[j, i]; //<=== This is the green component
address[2] = 0; //<=== No blue
address[3] = 255;
//4 bytes per pixel
address += 4;
}//end for j
//4 bytes per pixel
address += (bitmapData.Stride - (bitmapData.Width * 4));
}//end for i
如果您想将内核显示为灰度强度,则可以使用8位灰度图像来执行此操作,或者将相同的值分配给红色,绿色和蓝色分量:
address[0] = (byte)image[j, i];
address[1] = (byte)image[j, i];
address[2] = (byte)image[j, i];
address[3] = 255;
同样,滤镜被认为可以锐化图像。但是,它没有这样做。可能出了什么问题?
那是更有趣的问题。简而言之,您在
Gaussian.GaussianKernelHPF
中从低通进行高通高斯内核转换是不正确的。您必须更正总体思路,才能计算类似1-f(x)
的函数,其中f(x)
是低通内核,但这适用于频域内核响应。在空间域中,常数项成为冲量。考虑到一些缩放比例因素(为了在频域中获得单一脉冲并给出FFT定义,您需要在空间域中脉冲的幅度为Width*Height
),您应该得到以下信息:double K = 1 / D1;
double S = Width * Height / (Math.PI * Math.PI * D2 * D2);
for (int i = -halfOfWidth; i < halfOfWidth; i++)
{
for (int j = -halfOfHeight; j < halfOfHeight; j++)
{
int x = halfOfWidth + i;
int y = halfOfHeight + j;
if (i == 0 && j == 0)
{
GaussianKernel[x, y] = Width * Height + (K / D1 - Kernel[x, y]) * S;
}
else
{
GaussianKernel[x, y] = -Kernel[x, y] * S;
}
}
}
请注意,您还需要对内核进行移位,以使高斯内核的峰值位于像素位置
(0,0)
,以避免获得循环移位的结果图像://Swap halves so the peak is at pixel (0,0)
double[,] shifted = new double[Width, Height];
for (int j = 0; j < halfOfHeight; j++)
{
for (int i = 0; i < halfOfWidth; i++)
{
int x = i + halfOfWidth;
int y = j + halfOfHeight;
shifted[x, y] = GaussianKernel[i, j];
shifted[i, j] = GaussianKernel[x, y];
shifted[x, j] = GaussianKernel[i, y];
shifted[i, y] = GaussianKernel[x, j];
}
}
return shifted;
有关此修复程序的实现,请参见this pull-request,其中还包括一些其他调整(例如,我已将
Sigma
修改为不太积极的值4,进行了一些重新缩放,以对数比例显示内核等)。可随意将参数调整为适合您要求的任何值。有了这个,您应该得到如下所示的内容:
我认为(虽然我不确定)彩色图像被很好地过滤了。
情况并非如此。对于锐化滤镜,我认为颜色不会受到太大影响(指建筑物上天空的绿色,黄色和红色反射)。好消息是,与上述相同的修复程序也可以解决以下问题: