【发布时间】:2017-01-05 16:52:38
【问题描述】:
我已经实现了一组定向带通滤波器described in this article。
参见“2.1 预处理”部分的最后一段。
我们选择了 12 个不重叠的过滤器,以分析 12 个不同的方向,相互旋转 15°。
我遇到以下问题,
过滤器组应该生成 12 个过滤后的图像。但是,实际上,我只有 03 个输出,如下图所示,
源代码:
Here is the complete VS2013 solution as a zipped file.
这里是源代码中最相关的部分,
public class KassWitkinFunction
{
/*
* tx = centerX * cos
* ty = centerY * sin
*
* u* = cos . (u + tx) + sin . (v + ty)
* v* = - sin . (u + tx) + cos . (v + ty)
*
*/
//#region MyRegion
public static double tx(int centerX, double theta)
{
double costheta = Math.Cos(theta);
double txx = centerX * costheta;
return txx;
}
public static double ty(int centerY, double theta)
{
double sintheta = Math.Sin(theta);
double tyy = centerY * sintheta;
return tyy;
}
public static double uStar(double u, double v, int centerX, int centerY, double theta)
{
double txx = tx(centerX, theta);
double tyy = ty(centerY, theta);
double sintheta = Math.Sin(theta);
double costheta = Math.Cos(theta);
double cosThetaUTx = costheta * (u + txx);
double sinThetaVTy = sintheta * (v + tyy);
double returns = cosThetaUTx + sinThetaVTy;
return returns;
}
//#endregion
public static double vStar(double u, double v, int centerX, int centerY, double theta)
{
double txx = tx(centerX, theta);
double tyy = ty(centerY, theta);
double sintheta = Math.Sin(theta);
double costheta = Math.Cos(theta);
double sinThetaUTx = (-1) * sintheta * (u + txx);
double cosThetaVTy = costheta * (v + tyy);
double returns = sinThetaUTx + cosThetaVTy;
return returns;
}
public static double ApplyFilterOnOneCoord(double u, double v, double Du, double Dv, int CenterX, int CenterY, double Theta, int N)
{
double uStar = KassWitkinFunction.uStar(u, v, CenterX, CenterY, Theta);
double vStar = KassWitkinFunction.vStar(u, v, CenterX, CenterY, Theta);
double uStarDu = uStar / Du;
double vStarDv = vStar / Dv;
double sqrt = Math.Sqrt(uStarDu + vStarDv);
double _2n = 2 * N;
double pow = Math.Pow(sqrt, _2n);
double div = 1 + 0.414 * pow;
double returns = 1/div;
return returns;
}
}
public class KassWitkinKernel
{
public readonly int N = 4;
public int Width { get; set; }
public int Height { get; set; }
public double[,] Kernel { get; private set; }
public double[,] PaddedKernel { get; private set; }
public double Du { get; set; }
public double Dv { get; set; }
public int CenterX { get; set; }
public int CenterY { get; set; }
public double ThetaInRadian { get; set; }
public void SetKernel(double[,] value)
{
Kernel = value;
Width = Kernel.GetLength(0);
Height = Kernel.GetLength(1);
}
public void Pad(int newWidth, int newHeight)
{
double[,] temp = (double[,])Kernel.Clone();
PaddedKernel = ImagePadder.Pad(temp, newWidth, newHeight);
}
public Bitmap ToBitmap()
{
return ImageDataConverter.ToBitmap(Kernel);
}
public Bitmap ToBitmapPadded()
{
return ImageDataConverter.ToBitmap(PaddedKernel);
}
public Complex[,] ToComplex()
{
return ImageDataConverter.ToComplex(Kernel);
}
public Complex[,] ToComplexPadded()
{
return ImageDataConverter.ToComplex(PaddedKernel);
}
public void Compute()
{
Kernel = new double[Width, Height];
for (int i = 0; i < Width; i++)
{
for (int j = 0; j < Height; j++)
{
Kernel[i, j] = (double)KassWitkinFunction.ApplyFilterOnOneCoord(i, j,
Du,
Dv,
CenterX,
CenterY,
ThetaInRadian,
N);
//Data[i, j] = r.NextDouble();
}
}
string str = string.Empty;
}
}
public class KassWitkinBandpassFilter
{
public Bitmap Apply(Bitmap image, KassWitkinKernel kernel)
{
Complex[,] cImagePadded = ImageDataConverter.ToComplex(image);
Complex[,] cKernelPadded = kernel.ToComplexPadded();
Complex[,] convolved = Convolution.Convolve(cImagePadded, cKernelPadded);
return ImageDataConverter.ToBitmap(convolved);
}
}
public class KassWitkinFilterBank
{
private List<KassWitkinKernel> Kernels;
public int NoOfFilters { get; set; }
public double FilterAngle { get; set; }
public int WidthWithPadding { get; set; }
public int HeightWithPadding { get; set; }
public int KernelDimension { get; set; }
public KassWitkinFilterBank()
{}
public List<Bitmap> Apply(Bitmap bitmap)
{
Kernels = new List<KassWitkinKernel>();
double degrees = FilterAngle;
KassWitkinKernel kernel;
for (int i = 0; i < NoOfFilters; i++)
{
kernel = new KassWitkinKernel();
kernel.Width = KernelDimension;
kernel.Height = KernelDimension;
kernel.CenterX = (kernel.Width) / 2;
kernel.CenterY = (kernel.Height) / 2;
kernel.Du = 2;
kernel.Dv = 2;
kernel.ThetaInRadian = Tools.DegreeToRadian(degrees);
kernel.Compute();
kernel.Pad(WidthWithPadding, HeightWithPadding);
Kernels.Add(kernel);
degrees += degrees;
}
List<Bitmap> list = new List<Bitmap>();
foreach (KassWitkinKernel k in Kernels)
{
Bitmap image = (Bitmap)bitmap.Clone();
Complex[,] cImagePadded = ImageDataConverter.ToComplex(image);
Complex[,] cKernelPadded = k.ToComplexPadded();
Complex[,] convolved = Convolution.Convolve(cImagePadded, cKernelPadded);
Bitmap temp = ImageDataConverter.ToBitmap(convolved);
list.Add(temp);
}
return list;
}
}
【问题讨论】:
-
可能还有其他问题,但对于初学者:1)我不确定 eq。 (1) & (2) 是准确的。按照您的方式实施(这几乎是直接翻译)导致
NaNs 除了解释黑色/缺失图像的前 3 个过滤器输出之外的所有结果。 2)我觉得这些方程旨在指定频域中的内核,而您的Convolution应用空间域中的定义。 3) 较小的点,但在KassWitkinFilterBank.Apply中,您可能应该让degrees += FilterAngle有15 度的步长,而不是为每个过滤器加倍。 -
@SleuthEye, (1) 在评论部分,你可以看到我实际上已经更正了这些方程。
-
@SleuthEye,(2)如果您可以下载我提供了链接的 VS2013 解决方案,您会看到,我已经完成了 FFT 卷积(即我已经在频域中应用了该滤波器)。
-
1) 我注意到您稍微调整了方程式。但它仍然不够,因为它仍然会生成
NaNs。最好是联系论文的作者以获得实际的方程式,否则我会看看我是否能想出一些合理的东西。 2)我检查了你的解决方案,我知道你正在使用 FFT 卷积。我的意思是,提供的方程可能适用于频域中的内核,这意味着您不会计算内核上的 FFT(与在空间域中提供内核时不同)。
标签: c# image-processing filter gabor-filter bandpass-filter