您的位置:首页 > 其它

关于傅里叶变换算法中的一个小算法(下标的问题)

2014-08-28 22:03 309 查看
感言:

最近研究傅里叶算法,发现很多书都没有解释明白,都是一笔带过,发了很长时间,终于研究懂了,而且还发现很多书都是抄袭,有一本书出现错误,另一本也出现同样错误,可恶。

注:转载本文:

*************************************************************************

* 函数名称:

* Fourier()

* 参数:

* LPSTR lpDIBBits - 指向源DIB图像指针

* LONG lWidth - 源图像宽度(象素数)

* LONG lHeight - 源图像高度(象素数)

* 返回值:

* BOOL - 成功返回TRUE,否则返回FALSE。

* 说明:

* 该函数用来对图像进行付立叶变换。

************************************************************************/

BOOL CDibImage::Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)

{

unsigned char*lpSrc;
// 指向源图像的指针

double
dTemp;

LONG i;// 循环变量

LONG j;

LONG w;// 进行付立叶变换的宽度(2的整数次方)

LONG h;// 进行付立叶变换的高度(2的整数次方)

int wp;

int hp;

LONG lLineBytes;// 图像每行的字节数

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数

// 赋初值

w = 1;

h = 1;

wp = 0;

hp = 0;

// 计算进行付立叶变换的宽度和高度(2的整数次方)

while(w * 2 <= lWidth)

{

w *= 2;

wp++;

}

while(h * 2 <= lHeight)

{

h *= 2;

hp++;

}

complex<double> *TD = new complex<double>[w * h];

complex<double> *FD = new complex<double>[w * h];

for(i = 0; i < h; i++)// 行

{

for(j = 0; j < w; j++)// 列

{

// 指向DIB第i行,第j个象素的指针

lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;

// 给时域赋值

TD[j + w * i] = complex<double>(*(lpSrc), 0);

}

}

for(i = 0; i < h; i++)

{

// 对y方向进行快速付立叶变换

FFT(&TD[w * i], &FD[w * i], wp);

}

// 保存变换结果(研究了很长时间都没看懂,原来是一个小算法,就是一维数组转换二维数组问题,然后在进行倒置)

for(i = 0; i < h; i++)//行

{

for(j = 0; j < w; j++)//列

{

TD[i + h * j] = FD[j + w * i];//相当于把一维数组FD[j + w * i]转换成二维数组FD[i][j],然后把二维数组

//FD[i][j], 进行转置,变成TD[j][i],然后在把二维数组TD[j][i]变成一维数组TD[j*h+i],

}

}

for(i = 0; i < w; i++)

{

// 对x方向进行快速付立叶变换

FFT(&TD[i * h], &FD[i * h], hp);

}

for(i = 0; i < h; i++)// 行

{

for(j = 0; j < w; j++)// 列

{

// 计算频谱

dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() +

FD[j * h + i].imag() * FD[j * h + i].imag()) / 100;

if (dTemp > 255)

{

dTemp = 255;

}

// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个

// 象素的指针,此处不直接取i和j,是为了将变换后的原点移到中心

// lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight-1-i) + j;

lpSrc = (unsigned char*)lpDIBBits + lLineBytes *

(lHeight - 1 - (i<h/2 ? i+h/2 : i-h/2)) + (j<w/2 ? j+w/2 : j-w/2);

// 更新源图像

* (lpSrc) = (BYTE)(dTemp);

}

}

delete TD;

delete FD;

return TRUE;

}

具体的一维数组转二维数组算法如下:

一维->二维(先看二维转一维,然后逆向思维考虑就行了)

一个n个元素的一维数组,转换为r行c列的二维数组

对于一维数组中任意一个元素的下标i(0 <= i < n)

其对应的二维数组下标为 (i / c, i % c), 显然, 只与列数c有关,而与行数r无关

二维->一维

int[,] a =
newint[r, c];int[] b =new
int[r * c];for(int i =0; i <b.Length; i++)

b[i] = a[i / c, i % c];

一维->二维

codelike this

int[] a = new int
;int[,] b = new int[r, c];for (int i
= 0; i < n; i++)

b[i / c, i % c] = a[i];

also canwrite like this

for (int i = 0; i < r; i++)

{ for (int j = 0; j < c; j++)

{

b[i, j] = a[i * c +j]; //因为 b[i / c, i % c] = a[i];所以逆向思维考虑b[i, j]=b[(i
* c +j)/c][(i * c +j)% c]

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: