Image ftw_平面图_dft_c2r_2d(宽度、高度、核、核距、FFTW_估计); fftw_执行(dft_规划); fftw销毁计划(dft计划); double*kernelShift=新的双精度[宽度*高度]; circhift(kernelShift,kernelOut,width,height,(width/2),(height/2)); double maxKernel=kernelShift[0]; 对于(int i=0;i
代码没有内存管理,所以您必须清理内存 这是一个经典的反褶积问题。你所谓的卷积矩阵通常被称为“内核”。卷积运算通常用星号“*”表示(不要与乘法混淆!)。使用这个符号Image ftw_平面图_dft_c2r_2d(宽度、高度、核、核距、FFTW_估计); fftw_执行(dft_规划); fftw销毁计划(dft计划); double*kernelShift=新的双精度[宽度*高度]; circhift(kernelShift,kernelOut,width,height,(width/2),(height/2)); double maxKernel=kernelShift[0]; 对于(int i=0;i,image,algorithm,convolution,Image,Algorithm,Convolution,代码没有内存管理,所以您必须清理内存 这是一个经典的反褶积问题。你所谓的卷积矩阵通常被称为“内核”。卷积运算通常用星号“*”表示(不要与乘法混淆!)。使用这个符号 Result=Source*内核 上面使用FFT的答案是正确的,但在存在噪声的情况下,不能真正使用基于FFT的反褶积。正确的方法是使用Richardson-Lucy反褶积(参见) 实现起来非常简单。这个答案还提供了一个示例Matlab实现:谢谢。。它不是精确的内核,但结果对我来说已经足够好了。我正在尝试将代码重写为C。rfft2是F
Result=Source*内核
上面使用FFT的答案是正确的,但在存在噪声的情况下,不能真正使用基于FFT的反褶积。正确的方法是使用Richardson-Lucy反褶积(参见)
实现起来非常简单。这个答案还提供了一个示例Matlab实现:谢谢。。它不是精确的内核,但结果对我来说已经足够好了。我正在尝试将代码重写为C。rfft2是FFT。实际输入和返回实际输出的DFT(也称为DCT)?这行代码是:kernel\u f=blur\u f/orig\u f。。每个元素的/或其矩阵除法(乘以逆)?我相信的输出是复杂的,但它忽略了对实际输入应用一般复FFT得到的对称输出的一半。这不是DCT。无论如何,任何FFT例程都应该这样做。是的,numpy数组上的
/
只进行元素除法(即逆乘法)。我想如果你需要的话,我可以稍后在GSL中提供C代码(但不是现在,我现在还不够清醒。):)C代码会很好。。。我使用fftw和real-to-real-FFT标记为DCT。我试着运行实对实的FFT。元素除法是逆乘法吗?我想,元素方面的意思是res[0][0]=m1[0][0]/m2[0][0]等等(但逆运算并不是那么简单),就像傅里叶空间中的普通卷积需要复数乘法一样。另外,我没有使用FFTW,但我相信你应该使用的计划是。
template<class ty>
void circshift(ty *out, const ty *in, int xdim, int ydim, int xshift, int yshift)
{
for (int i =0; i < xdim; i++)
{
int ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++)
{
int jj = (j + yshift) % ydim;
out[ii * ydim + jj] = in[i * ydim + j];
}
}
}
int width = 256;
int height = 256;
int index = 0;
MyStringAnsi imageName1 = "C://ka4ag.png";
MyStringAnsi imageName2 = "C://KyPu2.png";
double * in1 = new double[width * height];
fftw_complex * out1 = new fftw_complex[width * height];
double * in2 = new double[width * height];
fftw_complex * out2 = new fftw_complex[width * height];
MyUtils::MyImage * im1 = MyUtils::MyImage::Load(imageName1, MyUtils::MyImage::PNG);
MyUtils::MyImage * im2 = MyUtils::MyImage::Load(imageName2, MyUtils::MyImage::PNG);
for (int i = 0; i < width * height; i++)
{
in1[i] = ((im1->Get(i).r / (255.0 * 0.5)) - 1.0);
in2[i] = ((im2->Get(i).r / (255.0 * 0.5)) - 1.0);
}
fftw_plan dft_plan1 = fftw_plan_dft_r2c_2d(width, height, in1, out1, FFTW_ESTIMATE);
fftw_execute(dft_plan1);
fftw_destroy_plan(dft_plan1);
fftw_plan dft_plan2 = fftw_plan_dft_r2c_2d(width, height, in2, out2, FFTW_ESTIMATE);
fftw_execute(dft_plan2);
fftw_destroy_plan(dft_plan2);
fftw_complex * kernel = new fftw_complex[width * height];
for (int i = 0; i < width * height; i++)
{
std::complex<double> c1(out1[i][0], out1[i][1]);
std::complex<double> c2(out2[i][0], out2[i][1]);
std::complex<double> div = c2 / c1;
kernel[i][0] = div.real();
kernel[i][1] = div.imag();
}
double * kernelOut = new double[width * height];
fftw_plan dft_planOut = fftw_plan_dft_c2r_2d(width, height, kernel, kernelOut, FFTW_ESTIMATE);
fftw_execute(dft_planOut);
fftw_destroy_plan(dft_planOut);
double * kernelShift = new double[width * height];
circshift(kernelShift, kernelOut, width, height, (width/2), (height/2));
double maxKernel = kernelShift[0];
for (int i = 0; i < width * height; i++)
{
if (maxKernel < kernelShift[i]) maxKernel = kernelShift[i];
}
for (int i = 0; i < width * height; i++)
{
kernelShift[i] /= maxKernel;
}
uint8 * res = new uint8[width * height];
for (int i = 0; i < width * height; i++)
{
res[i] = static_cast<uint8>((kernelShift[i]+ 1.0) * (255.0 * 0.5));
}
//now in res is similar result as in @Ilmari Karonen, but shifted by +128