⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grayproc.cpp

📁 电子书《数字图像处理学》Visual C++实现 郎锐编写 所附源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	int ns_r[256];
	int ns_g[256];
	int ns_b[256];
	
	// 灰度分布概率
	float ps_r[256];
	float ps_g[256];
	float ps_b[256];

	// 中间临时变量
	float temp_r[256];
	float temp_g[256];
	float temp_b[256];

	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);

	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);
	
	// 对灰度密度分布进行统计	
	GetIntensity(hDIB, ns_r, ns_g, ns_b);

	// 对灰度分布概率进行统计
	GetIntensity(hDIB, ps_r, ps_g, ps_b);
	
	// 计算原始累计直方图
	for (i = 0; i < 256; i++)
	{
		if (i == 0)
		{
			temp_r[0] = ps_r[0];
			temp_g[0] = ps_g[0];
			temp_b[0] = ps_b[0];
		}
		else
		{
			temp_r[i] = temp_r[i-1] + ps_r[i];
			temp_g[i] = temp_g[i-1] + ps_g[i];
			temp_b[i] = temp_b[i-1] + ps_b[i];
		}
		ps_r[i] = temp_r[i];
		ps_g[i] = temp_g[i];
		ps_b[i] = temp_b[i];
	}
	
	// 计算规定累计直方图
	for (i = 0; i < bNum; i++)
	{
		if (i == 0)
		{
			temp_r[0] = fpPu[0];
		}
		else
		{
			temp_r[i] = temp_r[i-1] + fpPu[i];
		}
		fpPu[i] = temp_r[i];
	}
	
	// 确定映射对应关系
	for (i = 0; i < 256; i++)
	{
		// 最接近的规定直方图灰度级
		int m_r = 0;
		int m_g = 0;
		int m_b = 0;
		
		// 最小差值
		float min_value_r = 1.0f;
		float min_value_g = 1.0f;
		float min_value_b = 1.0f;

		// 对规定直方图各灰度进行枚举
		for (j = 0; j < bNum; j++)
		{
			// 当前差值
			float now_value = 0.0f;
			
			// 对R分量计算差值
			if (ps_r[i] - fpPu[j] >= 0.0f)
				now_value = ps_r[i] - fpPu[j];
			else
				now_value = fpPu[j] - ps_r[i];

			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_r)
			{
				// 最接近的灰度级
				m_r = j;

				// 暂存最小差值
				min_value_r = now_value;
			}

			// 对G分量计算差值
			if (ps_g[i] - fpPu[j] >= 0.0f)
				now_value = ps_g[i] - fpPu[j];
			else
				now_value = fpPu[j] - ps_g[i];

			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_g)
			{
				// 最接近的灰度级
				m_g = j;
			
				// 暂存最小差值
				min_value_g = now_value;
			}
				
			// 对B分量计算差值
			if (ps_b[i] - fpPu[j] >= 0.0f)
				now_value = ps_b[i] - fpPu[j];
			else
				now_value = fpPu[j] - ps_b[i];
			
			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_b)
			{
				// 最接近的灰度级
				m_b = j;
			
				// 暂存最小差值
				min_value_b = now_value;
			}
		}

		// 建立灰度映射表
		ns_r[i] = npNu[m_r];
		ns_g[i] = npNu[m_g];
		ns_b[i] = npNu[m_b];
	}

	// 对各像素进行处理
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lLineBytes; j ++)
		{
			// 对像素各颜色分量进行单映射规则的直方图规定化映射处理
			unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_r[R];
			j++;
			unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_g[G];
			j++;
			unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_b[B];
		}
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 恢复光标
	EndWaitCursor();
}


/*************************************************************************
 *
 * 函数名称:
 *   PointGML()
 *
 * 参数:
 *   HDIB hDIB          - 待处理的DIB
 *	 BYTE bNum			- 规定直方图灰度级数
 *	 int* npNu			- 规定直方图灰度映射关系
 *	 float* fpPu		- 规定直方图各灰度的分布概率
 *
 * 返回值:
 *   void				- 无返回值
 *
 * 说明:
 *   该函数对图像进行组映射规则直方图规定化变换
 *
 ************************************************************************/

void CGrayProc::PointGML(HDIB hDIB, BYTE bNum, int *npNu, float *fpPu)
{
	// 循环变量
	LONG i;
	LONG j;
	LONG k;

	// 灰度分布密度
	int ns_r[256];
	int ns_g[256];
	int ns_b[256];
	
	// 灰度分布概率
	float ps_r[256];
	float ps_g[256];
	float ps_b[256];

	// 中间临时变量
	float temp_r[256];
	float temp_g[256];
	float temp_b[256];

	// 灰度映射区间的起始灰度
	int A1_r = 0;
	int A1_g = 0;
	int A1_b = 0;
	
	// 灰度映射区间的终止灰度
	int A2_r = 0;
	int A2_g = 0;
	int A2_b = 0;

	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 对灰度密度分布进行统计	
	GetIntensity(hDIB, ns_r, ns_g, ns_b);

	// 对灰度分布概率进行统计
	GetIntensity(hDIB, ps_r, ps_g, ps_b);
	
	// 计算原始累计直方图
	for (i = 0; i < 256; i++)
	{
		if (i == 0)
		{
			temp_r[0] = ps_r[0];
			temp_g[0] = ps_g[0];
			temp_b[0] = ps_b[0];
		}
		else
		{
			temp_r[i] = temp_r[i-1] + ps_r[i];
			temp_g[i] = temp_g[i-1] + ps_g[i];
			temp_b[i] = temp_b[i-1] + ps_b[i];
		}
		ps_r[i] = temp_r[i];
		ps_g[i] = temp_g[i];
		ps_b[i] = temp_b[i];
	}
	
	// 计算规定累计直方图
	for(i = 0; i < bNum; i++)
	{
		if(i == 0)
		{
			temp_r[0] = fpPu[0];
		}
		else
		{
			temp_r[i] = temp_r[i-1] + fpPu[i];
		}
		fpPu[i] = temp_r[i];
	}

	// 确定映射对应关系
	for (i = 0; i < bNum; i++)
	{
		// 最小差值
		float min_value_r = 1.0f;
		float min_value_g = 1.0f;
		float min_value_b = 1.0f;

		// 对原始直方图分布进行枚举检索
		for (j = 0; j < 256; j++)
		{
			// 当前差值
			float now_value = 0.0f;
			
			// 对R分量计算差值
			if (ps_r[j] - fpPu[i] >= 0.0f)
				now_value = ps_r[j] - fpPu[i];
			else
				now_value = fpPu[i] - ps_r[j];
			
			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_r)
			{
				// 最接近的灰度级
				A2_r=j;

				// 暂存最小差值
				min_value_r = now_value;
			}

			// 对G分量计算差值
			if (ps_g[j] - fpPu[i] >= 0.0f)
				now_value = ps_g[j] - fpPu[i];
			else
				now_value = fpPu[i] - ps_g[j];
			
			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_g)
			{
				// 最接近的灰度级
				A2_g = j;

				// 暂存最小差值
				min_value_g = now_value;
			}
				
			// 对B分量计算差值
			if (ps_b[j] - fpPu[i] >= 0.0f)
				now_value = ps_b[j] - fpPu[i];
			else
				now_value = fpPu[i] - ps_b[j];
			
			// 寻找最接近的规定直方图灰度级
			if (now_value < min_value_b)
			{
				// 最接近的灰度级
				A2_b = j;
				
				// 暂存最小差值
				min_value_b = now_value;
			}
		}
			
		// 将[A1_r,A2_r]区间的原始灰度k通过建立映射表ns_r[]映射到灰度nu[i]
		for (k = A1_r; k <= A2_r; k++)
			ns_r[k] = npNu[i];
	
		// 移动区间其始位置
		A1_r = A2_r + 1;
			
		// 将[A1_g,A2_g]区间的原始灰度k通过建立映射表ns_g[]映射到灰度nu[i]
		for (k = A1_g; k <= A2_g; k++)
			ns_g[k] = npNu[i];
		
		// 移动区间其始位置
		A1_g = A2_g + 1;
		
		// 将[A1_b,A2_b]区间的原始灰度k通过建立映射表ns_b[]映射到灰度nu[i]
		for (k = A1_b; k <= A2_b; k++)
			ns_b[k] = npNu[i];
		
		// 移动区间其始位置
		A1_b = A2_b + 1;
	}

	// 对各像素进行处理
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lLineBytes; j ++)
		{
			// 对像素各颜色分量进行单映射规则的直方图规定化映射处理
			unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_r[R];
			j++;
			unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_g[G];
			j++;
			unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = ns_b[B];
		}
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 恢复光标
	EndWaitCursor();
}


/*************************************************************************
 *
 * 函数名称:
 *   DynamicCompress()
 *
 * 参数:
 *   HDIB hDIB          - 待处理的DIB
 *	 float fC			- 尺度比例常数
 *
 * 返回值:
 *   void				- 无返回值
 *
 * 说明:
 *   该函数对图像进行灰度动态范围压缩处理
 *
 ************************************************************************/

void CGrayProc::DynamicCompress(HDIB hDIB, int nC)
{
	// 循环变量
	LONG i;
	LONG j;

	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 对各像素进行灰度转换
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lLineBytes; j ++)
		{
			// 对像素各颜色分量进行灰度动态范围压缩
			unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			R = (unsigned char)(nC * log(1 + R));
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = R;
			j++;

			unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			G = (unsigned char)(nC * log(1 + G));
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = G;
			j++;

			unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			B = (unsigned char)(nC * log(1 + B));
			*((unsigned char *)lpDIBBits + lLineBytes * i + j) = B;
		}
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 恢复光标
	EndWaitCursor();
}


/*************************************************************************
 *
 * 函数名称:
 *   CutWave()
 *
 * 参数:
 *   HDIB hDIB          - 待处理的DIB
 *
 * 返回值:
 *   void				- 无返回值
 *
 * 说明:
 *   该函数将对图象进行灰度削波处理
 *
 ************************************************************************/

void CGrayProc::CutWave(HDIB hDIB)
{
	// 循环变量
	LONG i;
	LONG j;
	
	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 对各像素进行灰度转换
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lLineBytes; j ++)
		{
			// 获取各颜色分量
			unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			j++;
			unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i + j);
			j++;
			unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i + j);

			// 计算灰度值
			unsigned char Y = (9798 * R + 19235 * G + 3735 * B) / 32768;

			if (Y < 30)
			{
				R = G = B = 0;
			}

			if (Y >= 30 && Y < 200)
			{
				R = R * 256 / 200;
				G = G * 256 / 200;
				B = B * 256 / 200;
				
				// 超限保护
				if (R > 255)	R = 255;
				if (R < 0)		R = 0;
				if (G > 255)	G = 255;
				if (G < 0)		G = 0;
				if (B > 255)	B = 255;
				if (B < 0)		B = 0;
			}

			if (Y >= 200)
			{
				R = G = B = 255;
			}

			// 回写灰度值
			*((unsigned char *)lpDIBBits + lLineBytes * i + j - 2) = B;
			*((unsigned char *)lpDIBBits + lLineBytes * i + j - 1) = G;
			*((unsigned char *)lpDIBBits + lLineBytes * i + j ) = R;
		}
	}

	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 恢复光标
	EndWaitCursor();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -