1. 程式人生 > >影象處理 離散haar小波變換

影象處理 離散haar小波變換

程式設計環境:windows下結合opencv庫

//離散Haar小波變換
/*
dst深度為IPL_DEPTH_32F
nLayer為變換尺度
*/
void HaarWavelet(IplImage* src, IplImage* dst, int nLayer);
//離散Haar小波變換
/*
dst深度為IPL_DEPTH_32F
nLayer為變換尺度
*/
void HaarWavelet(IplImage* src, IplImage* dst, int nLayer)
{
	if (!dst)
	{
		return;
	}
	if (((dst->width >> nLayer) << nLayer != dst->width) 
		|| ((dst->height >> nLayer) << nLayer != dst->height)
		|| (dst->depth != IPL_DEPTH_32F)
		|| (src->nChannels != 1)
		|| (dst->nChannels != 1)
		|| (nLayer <= 0))
	{
		return;
	}

	int x, y;
	int nWidth = dst->width;
	int nHeight = dst->height;
	int nHalfWidth = nWidth / 2;
	int nHalfHeight = nHeight / 2;
	//影象資料的起始地址
	float* *pfData = (float**)(malloc(sizeof(float*) * nHeight));
	//儲存計算過程中用到的行列資料
	float* pfRow = (float*)(malloc(sizeof(float) * nWidth));
	float* pfColumn = (float*)(malloc(sizeof(float) * nHeight));
	CvMat tmp;
	//預先填充dst
	cvZero(dst);
	cvGetSubRect(dst, &tmp, cvRect(0, 0, src->width, src->height));
	cvScale(src, &tmp, 1.0, 0);
	//儲存影象資料每行的起始地址
	for (y = 0; y < nHeight; y++)
	{
		pfData[y] = (float*)(dst->imageData + y * dst->widthStep);
	}

	while (nLayer > 0)
	{
		//行變換
		for (y = 0; y < nHeight; y++)
		{
			for (x = 0; x < nHalfWidth; x++)
			{
				pfRow[x] = (pfData[y][2 * x] + pfData[y][2 * x + 1]) / 2.0;
				pfRow[x + nHalfWidth] = (pfData[y][2 * x] - pfData[y][2 * x + 1]) / 2.0;
			}
			for (x = 0; x < nWidth; x++)
			{
				pfData[y][x] = pfRow[x];
			}
		}
		//列變換
		for (x = 0; x < nWidth; x++)
		{
	
			for (y = 0; y < nHalfHeight; y++)
			{
				pfColumn[y] = (pfData[2 * y][x] + pfData[2 * y + 1][x]) / 2;
				pfColumn[y + nHalfHeight] = (pfData[2 * y][x] - pfData[2 * y + 1][x]) / 2;
			}
			for (y = 0; y < nHeight; y++)
			{
				pfData[y][x] = pfColumn[y];
			}
		}
		//一層變換後尺度的縮小
		nLayer--;
		nWidth = nHalfWidth;
		nHeight = nHalfHeight;
		nHalfWidth = nHalfWidth / 2;
		nHalfHeight = nHalfHeight / 2;
	}

	//結果縮放以便與顯示
	double min,max;
	cvMinMaxLoc(dst, &min, &max, NULL, NULL, NULL);
    cvScale(dst, dst, 1.0/(max-min), 1.0*(-min)/(max-min));
}