特徵變換(2)沃爾什-哈達瑪變換
阿新 • • 發佈:2019-01-30
筆記->印象筆記(沃爾什變換篇)
MATLAB 原始碼:
clear all; I=zeros(2.^8); I(2.^7-2.^4+1:2.^7+2.^4,2.^7-2.^4+1:2.^7+2.^4)=ones(2*2.^4); %讀入資料 subplot(1,2,1); colormap(gray(128));imagesc(I); title('顯示原始影象'); [m,n]=size(I); for k=1:n wht(:,k)=hadamard(m)*I(:,k)/m; %對每一列作walah-Hadamard變換 end for j=1:m %對進行列的walah-Hadamard變換後的係數進行walah-Hadamard變換 wh(:,j)=hadamard(n)*wht(j,:)'/n; end wh=wh'; subplot(1,2,2);colormap(gray(128));imagesc(wh); title('walah-Hadamard變換系數');
/************************************************************************* * * 函式名稱: * WALSH() * * 引數: * double * dpf - 指向時域值的指標 * double * dpF - 指向頻域值的指標 * r -2的冪數 * * 返回值: * 無。 * * 說明: * 該函式用來實現一維快速沃爾什-哈達瑪變換。 * *********************************************************************** */ VOID WINAPI WALSH(double *dpf, double *dpF, int r) { // 沃爾什-哈達瑪變換點數 LONG lNum; // 快速沃爾什變換點數 lNum = 1 << r; // 迴圈變數 int i,j,k; // 中間變數 int nTemp,m; double *X1,*X2,*X; // 分配運算所需的陣列 X1 = new double[lNum]; X2 = new double[lNum]; // 將時域點寫入陣列X1 memcpy(X1, dpf, sizeof(double) * lNum); for(k = 0; k < r; k++) { for(j = 0; j < 1<<k; j++) { // 按照蝶形運算圖進行運算 nTemp = 1 << (r-k); for(i = 0; i < nTemp / 2; i++) { m = j * nTemp; X2[i + m] = X1[i + m] + X1[i + m + nTemp / 2]; X2[i + m + nTemp / 2] = X1[i + m] - X1[i + m + nTemp / 2]; } } // 互換 X = X2; X2 = X1; X1 = X; } // 對係數做調整 for(j = 0; j < lNum; j++) { m = 0; for(i = 0; i < r; i++) { if (j & (1<<i)) { m += 1 << (r-i-1); } } dpF[j] = X1[m] / lNum; } // 釋放記憶體 delete X1; delete X2; }
/************************************************************************* * * 函式名稱: * IWALSH() * * 引數: * double * dpF - 指向頻域值的指標 * double * dpf - 指向時域值的指標 * n -2的冪數 * * 返回值: * 無。 * * 說明: * 該函式用來實現一維快速沃爾什-哈達瑪反變換。 * *********************************************************************** */ VOID WINAPI IWALSH(double *dpF, double *dpf, int n) { // 變換點數 LONG lNum; // 迴圈變數 int i; // 計算變換點數 lNum = 1 << n; // 用快速沃爾什-哈達瑪變換進行反變換 WALSH(dpF, dpf, n); // 對係數進行調整 for(i = 0; i < lNum; i++) { dpf[i] *= lNum; } }
/*************************************************************************
*
* 函式名稱:
* DIBWalsh()
*
* 引數:
* CDib *pDib - 指向CDib類的指標
*
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
*
* 說明:
* 該函式用來對影象進行二維快速沃爾什-哈達瑪變換。
*
***********************************************************************
*/
BOOL WINAPI DIBWalsh(CDib * pDib)
{
// 指向源影象的指標
unsigned char *lpSrc;
//圖象的寬度和高度
LONG lWidth;
LONG lHeight;
// 迴圈變數
LONG i;
LONG j;
// 實際進行付立葉變換的寬度和高度
LONG lW = 1;
LONG lH = 1;
int wp = 0;
int hp = 0;
// 中間變數
double dTemp;
//得到圖象的寬度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到實際的圖象儲存大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 影象每行的位元組數
LONG lLineBytes;
// 計算影象每行的位元組數
lLineBytes = SizeRealDim.cx;
//影象資料的指標
LPBYTE lpDIBBits = pDib->m_lpImage;
// 保證離散餘弦變換的寬度和高度為2的整數次方
while(lW * 2 <= lWidth)
{
lW = lW * 2;
wp++;
}
while(lH * 2 <= lHeight)
{
lH = lH * 2;
hp++;
}
// 分配記憶體
double *dpf = new double[lW * lH];
double *dpF = new double[lW * lH];
// 時域賦值
for(i = 0; i < lH; i++)
{
// 列
for(j = 0; j < lW; j++)
{
// 指向DIBi行j列象素的指標
lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 將象素值賦值給時域陣列
dpf[j + i * lW] = *(lpSrc);
}
}
for(i = 0; i < lH; i++)
// 對y方向進行沃爾什-哈達瑪變換
WALSH(dpf + lW * i, dpF + lW * i, wp);
// 儲存計算結果
for(i = 0; i < lH; i++)
{
for(j = 0; j < lW; j++)
{
dpf[j * lH + i] = dpF[j + lW * i];
}
}
for(j = 0; j < lW; j++)
// 對x方向進行沃爾什-哈達瑪變換
WALSH(dpf + j * lH, dpF + j * lH, hp);
// 行
for(i = 0; i < lH; i++)
{
// 列
for(j = 0; j < lW; j++)
{
// 計算頻譜
dTemp = fabs(dpF[j * lH + i] * 1000);
if (dTemp > 255)
{
// 超過255直接設定為255
dTemp = 255;
}
// 指向DIBi行j列象素的指標
lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 更新源影象
* (lpSrc) = (BYTE)(dTemp);
}
}
//釋放記憶體
delete dpf;
delete dpF;
// 返回
return TRUE;
}