基于C++实现灰度图像的小波变换

本文介绍了如何在CDib类中使用Haar和Daubechies 5(db5)小波变换进行1D和2D图像处理,包括行级变换、系数调整和像素值映射,重点展示了两种小波类型的实现细节与图像增强操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先放下代码 回头补一下解释

头文件

const double haar_h[2] = {sqrt(2)/2 , sqrt(2)/2 };
const double haar_g[2] = { -sqrt(2) / 2 , sqrt(2) / 2 };
const double db5_h[10] = { 0.1601023980, 0.6038292698, 0.7243085284, 0.1384281459, \
	-0.2422948871, -0.0322448696, 0.0775714938, -0.0062414902, -0.0125807520, 0.0033357253 };
const double db5_g[10] = { 0.0033357253, 0.0125807520, -0.0062414902, -0.0775714938,\
	-0.0322448696, 0.2422948871, 0.1384281459, -0.7243085284, 0.6038292698, -0.1601023980 };
enum wavelets { haar, db5 };	//小波类型

cpp文件

void CDib::transpose()
{
	unsigned char* temp = new BYTE[m_nHeight*m_nWidthBytes];
	for (int lineX = 0; lineX < m_nHeight; lineX++)
	{
		for (int lineY = 0; lineY < m_nWidth; lineY++)
		{
			temp[lineY * m_nHeight + lineX] = m_pDibBits[lineX * m_nWidth + lineY];
		}
	}
	memcpy(m_pDibBits, temp, m_nHeight*m_nWidthBytes);
	delete temp;
}

void CDib::waveletTransform1D(wavelets selectedWavelet, int level, bool first_trans)
{
	//按行进行小波变换
	int hLen = 0;
	const double* h = NULL;
	const double* g = NULL;
	double *result = new double[m_nHeight / level * m_nWidthBytes / level];

	switch (selectedWavelet)
	{
	case haar:
		hLen = 2;
		h = haar_h;
		g = haar_g;
		break;
	case db5:
		hLen = 10;
		h = db5_h;
		g = db5_g;
		break;
	}

	unsigned char* temp = new unsigned char[m_nWidthBytes + hLen];

	for (int i = 0; i < m_nHeight / level; i++)
	{
		for (int j = 0; j < m_nWidthBytes / level; j++)
			temp[j] = m_pDibBits[i * m_nWidthBytes + j];

		// 末尾补最后一个
		memset(temp + m_nWidthBytes/level, m_pDibBits[i * m_nWidthBytes + m_nWidthBytes / level - 1], hLen);
		//memset(temp + m_nWidthBytes, 0, hLen);
		for (int j = 0; j < m_nWidthBytes / level; j += 2)
		{
			double c = 0;
			double d = 0;
			for (int t = 0; t < hLen; t++)
			{
				c += temp[j + t] * h[t];
				d += temp[j + t] * g[t];
			}
			result[i * m_nWidthBytes / level + j / 2] = c;
			result[i * m_nWidthBytes / level + j / 2 + m_nWidthBytes / 2 / level] = d;
		}
	}

	if (first_trans)
	{
		double max = 0;
		double min = 0;
		int beginXs[2] = { 0, m_nWidthBytes / level / 2 };
		int beginX;
		// find the max
		for (int i = 0; i < 4; i++)
		{
			beginX = beginXs[i % 2];
			for (int x = beginX; x < beginX + m_nWidthBytes / level / 2; x++)
			{
				for (int y = 0; y < m_nHeight / level; y++)
				{
					if (result[y * m_nWidthBytes / level + x] > max) max = result[y * m_nWidthBytes / level + x];
					if (result[y * m_nWidthBytes / level + x] < min) min = result[y * m_nWidthBytes / level + x];
				}
			}
			for (int x = beginX; x < beginX + m_nWidthBytes / level / 2; x++)
			{
				for (int y = 0; y < m_nHeight / level; y++)
				{
					m_pDibBits[y * m_nWidthBytes + x] = (result[y * m_nWidthBytes / level + x] - min) / (max - min) * 255;
				}
			}
		}
	}
	else
	{
		double max = 0;
		double min = 0;
		int beginXs[2] = { 0, m_nWidthBytes / level / 2 };
		int beginYs[2] = { 0 , m_nHeight / level / 2 };
		int beginX, beginY;
		// find the max
		for (int i = 0; i < 4; i++)
		{
			beginX = beginXs[i % 2];
			beginY = beginYs[i / 2];
			for (int x = beginX; x < beginX + m_nWidthBytes / level / 2; x++)
			{
				for (int y = beginY; y < beginY + m_nHeight / level / 2; y++)
				{
					if (result[y * m_nWidthBytes / level + x] > max) max = result[y * m_nWidthBytes / level + x];
					if (result[y * m_nWidthBytes / level + x] < min) min = result[y * m_nWidthBytes / level + x];
				}
			}
			for (int x = beginX; x < beginX + m_nWidthBytes / level / 2; x++)
			{
				for (int y = beginY; y < beginY + m_nHeight / level / 2; y++)
				{
					m_pDibBits[y * m_nWidthBytes + x] = (result[y * m_nWidthBytes / level + x] - min) / (max - min) * 255;
				}
			}
		}
	}

	delete[]result;
	delete[]temp;
}

void CDib::waveletTransform2D(wavelets selectedWavelet, int level)
{
	if (level == 2)
		waveletTransform2D(selectedWavelet, 1);
	waveletTransform1D(selectedWavelet, level , true);
	transpose();
	waveletTransform1D(selectedWavelet, level , false);
	transpose();
	double max = 0;
	double min = 0;
	int beginXs[2] = { 0, m_nWidthBytes / level / 2 };
	int beginYs[2] = { 0 , m_nHeight / level / 2 };
	int beginX, beginY;
	// 调亮点
	for (int i = 0; i < 4; i++)
	{
		beginX = beginXs[i % 2];
		beginY = beginYs[i / 2];
		for (int x = beginX; x < beginX + m_nWidthBytes / level / 2; x++)
		{
			for (int y = beginY; y < beginY + m_nHeight / level / 2; y++)
			{
				switch (selectedWavelet)
				{
				case haar:
					switch (i)
					{
					case 0: break;
					case 1: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.1); break;
					case 2: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.2); break;
					case 3: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.35); break;
					};
					break;
				case db5:
					switch (i)
					{
					case 0: break;
					case 1: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.25); break;
					case 2: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.45); break;
					case 3: m_pDibBits[y * m_nWidthBytes + x] = pow(m_pDibBits[y * m_nWidthBytes + x], 1.45); break;
					};
					break;
				}
				
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值