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

📄 enhance.cpp

📁 《Visual C++数字图像获取 处理及实践应用》一书的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include "stdafx.h"
#include "cdib.h"
#include "math.h"
#include <direct.h>
#include <complex>
using namespace std;
#include "GlobalApi.h"

/*************************************************************************
 *
 * \函数名称:
 *   HistogramEqualize()
 *
 * \输入参数:
 *   CDib * pDib		- 指向CDib类的指针,含有原始图象信息
 *
 * \返回值:
 *   BOOL			- 成功则返回TRUE,否则返回FALSE
 *
 * \说明:
 *   该函数对指定的图象进行直方图均衡化处理
 *
 *************************************************************************
 */
 BOOL HistogramEqualize(CDib* pDib)
 {
	 // 指向源图像的指针
	unsigned char*	lpSrc;
	
	// 临时变量
	int	nTemp;
	
	// 循环变量
	int i,j;
	
	// 累积直方图,即灰度映射表
	BYTE	byMap[256];
	
	// 直方图
	int	nCount[256];
	
	// 图象的高度和宽度
	CSize sizeImage;
	sizeImage = pDib->GetDimensions();


	// 获得图象数据存储的高度和宽度
	CSize SizeSaveImage;
	SizeSaveImage = pDib->GetDibSaveDim();



	// 重置计数为0
	for (i = 0; i < 256; i ++)
	{
		// 清零
		nCount[i] = 0;
	}
	
	// 计算各个灰度值的计数,即得到直方图
	for (i = 0; i < sizeImage.cy; i ++)
	{
		for (j = 0; j < sizeImage.cx; j ++)
		{
			lpSrc = (unsigned char *)pDib->m_lpImage + SizeSaveImage.cx * i + j;
			
			// 计数加1
			nCount[*(lpSrc)]++;
		}
	}
	
	// 计算累积直方图
	for (i = 0; i < 256; i++)
	{
		// 初始为0
		nTemp = 0;
		
		for (j = 0; j <= i ; j++)
		{
			nTemp += nCount[j];
		}
		
		// 计算对应的新灰度值
		byMap[i] = (BYTE) (nTemp * 255 / sizeImage.cy / sizeImage.cx);
	}
	
	// 每行
	for(i = 0; i < sizeImage.cy; i++)
	{
		// 每列
		for(j = 0; j < sizeImage.cx; j++)
		{
			// 指向DIB第i行,第j个象素的指针
			lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i,j);
			
			// 计算新的灰度值
			*lpSrc = byMap[*lpSrc];
		}
	}
	
	// 返回
	return TRUE;
 }

/*************************************************************************
 *
 * \函数名称:
 *   GraySegLinTrans()
 *
 * \输入参数:
 *   CDib* pDib			- 指向CDib类的指针,含有原始图象信息
 *   int   nX1			- 分段线性灰度变换第一个拐点的X坐标
 *   int   nY1			- 分段线性灰度变换第一个拐点的Y坐标
 *   int   nX2			- 分段线性灰度变换第二个拐点的X坐标
 *   int   nY2			- 分段线性灰度变换第二个拐点的Y坐标
 *
 * \返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * \说明:
 *   该函数用来对图像进行分段线性灰度变换,输入参数中包含了两个拐点的坐标
 *
 *************************************************************************
 */
BOOL GraySegLinTrans(CDib* pDib, int nX1, int nY1, int nX2, int nY2)
{
	
	// 指向源图像的指针
	unsigned char*	lpSrc;
	
	// 循环变量
	int i,j;
	
	// 灰度映射表
	BYTE	byMap[256];
	
	// 图像每行的字节数
	//LONG	lLineBytes;

	// 图象的高度和宽度
	CSize sizeImage;
	sizeImage = pDib->GetDimensions();


	// 获得图象数据存储的高度和宽度
	CSize SizeSaveImage;
	SizeSaveImage = pDib->GetDibSaveDim();

	// 计算图像每行的字节数
	//lLineBytes = WIDTHBYTES(sizeImage.cx * 8);
	
	// 计算灰度映射表
	for (i = 0; i <= nX1; i++)
	{
		// 判断nX1是否大于0(防止分母为0)
		if (nX1 > 0)
		{
			// 线性变换
			byMap[i] = (BYTE) nY1 * i / nX1;
		}
		else
		{
			// 直接赋值为0
			byMap[i] = 0;
		}
	}
	for (; i <= nX2; i++)
	{
		// 判断nX1是否等于nX2(防止分母为0)
		if (nX2 != nX1)
		{
			// 线性变换
			byMap[i] = nY1 + (BYTE) ((nY2 - nY1) * (i - nX1) / (nX2 - nX1));
		}
		else
		{
			// 直接赋值为nY1
			byMap[i] = nY1;
		}
	}
	for (; i < 256; i++)
	{
		// 判断nX2是否等于255(防止分母为0)
		if (nX2 != 255)
		{
			// 线性变换
			byMap[i] = nY2 + (BYTE) ((255 - nY2) * (i - nX2) / (255 - nX2));
		}
		else
		{
			// 直接赋值为255
			byMap[i] = 255;
		}
	}
	
	// 对图象的象素值进行变换
	// 每行
	for(i = 0; i < sizeImage.cy; i++)
	{
		// 每列
		for(j = 0; j < sizeImage.cx; j++)
		{
			// 指向DIB第i行,第j个象素的指针
			lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i,j);
			
			// 计算新的灰度值
			*lpSrc = byMap[*lpSrc];
		}
	}
	
	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * \函数名称:
 *   GeneralTemplate()
 *
 * \输入参数:
 *   CDib * pDib		- 指向CDib类的指针,含有原始图象信息
 *   int nTempWidth		- 模板的宽度
 *   int nTempHeight		- 模板的高度
 *   int nTempCenX		- 模板中心的X坐标(相对于模板)
 *   int nTempCenY		- 模板中心的Y坐标(相对于模板)
 *   double* pdbTemp		- 模板数组的指针
 *   double* dbCoef		- 模板的系数
 *
 * \返回值:
 *   BOOL			- 成功则返回TRUE,否则返回FALSE
 *
 * \说明:
 *   该函数用指定的模板对pDib指向的图象进行模板操作。模板的定义了宽度,高度,
 *    中心坐标和系数,模板的数据存放在pdbTemp中。对图象进行模板操作后,仍
 *    然存放在pDib指向的CDib对象中。需要注意的是,该函数只能处理8位的图象,
 *   否则,指向的数据将出错。
 *
 *************************************************************************
 */
BOOL  GeneralTemplate(CDib* pDib,  int nTempWidth, int nTempHeight, 
					 int nTempCenX, int nTempCenY,
					 double* pdbTemp, double dbCoef)
{
	// 临时存放图像数据的指针
	LPBYTE lpImage;
	
	// 循环变量
	int i,j,k,l;
	
	// 指向源图像的指针
	unsigned char*	lpSrc;
	
	// 指向要复制区域的指针
	unsigned char*	lpDst;

	// 计算结果
	double	dbResult;

	// 图象的高度和宽度
	CSize sizeImage;
	sizeImage = pDib->GetDimensions();


	// 获得图象数据存储的尺寸
	int nSizeImage;
	nSizeImage = pDib->GetSizeImage();

	// 给临时存放数据分配内存
	lpImage = (LPBYTE) new char[nSizeImage];

	// 判断是否内存分配失败
	if (lpImage == NULL)
	{
		// 分配内存失败
		return FALSE;
	}
	
	// 将原始图像的数据拷贝到临时存放内存中
	memcpy(lpImage, pDib->m_lpImage, nSizeImage);

	
	
	// 进行模板操作
	// 行(除去边缘几行)
	for(i = nTempCenY ; i < sizeImage.cy - nTempHeight + nTempCenY + 1; i++)
	{
		// 列(除去边缘几列)
		for(j = nTempCenX; j < sizeImage.cx - nTempWidth + nTempCenX + 1; j++)
		{
			// 指向新DIB第i行,第j个象素的指针
			lpDst = (unsigned char*)lpImage + pDib->GetPixelOffset(i,j);
			
			dbResult = 0;
			
			// 计算
			for (k = 0; k < nTempHeight; k++)
			{
				for (l = 0; l < nTempWidth; l++)
				{
					// 指向DIB第i - nTempCenY + k行,第j - nTempCenX + l个象素的指针
					lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i-nTempCenY+k, j-nTempCenX+l);
					
					// 保存象素值
					dbResult += (* lpSrc) * pdbTemp[k * nTempWidth + l];
				}
			}
			
			// 乘上系数
			dbResult *= dbCoef;
			
			// 取绝对值
			dbResult = (double ) fabs(dbResult);
			
			// 判断是否超过255
			if(dbResult > 255)
			{
				// 直接赋值为255
				* lpDst = 255;
			}
			else
			{
				// 赋值
				* lpDst = (unsigned char) (dbResult + 0.5);
			}
			
		}
	}
	
	// 复制变换后的图像
	memcpy(pDib->m_lpImage, lpImage, nSizeImage);
	
	// 释放内存
	delete[]lpImage;
	
	// 返回
	return TRUE;

}


/*************************************************************************
 *
 * 函数名称:
 *   MedianFilter()
 *
 * \输入参数:
 *   CDib * pDib		- 指向CDib类的指针,含有原始图象信息
 *   int nTempWidth		- 模板的宽度
 *   int nTempHeight		- 模板的高度
 *   int nTempCenX		- 模板中心的X坐标(相对于模板)
 *   int nTempCenY		- 模板中心的Y坐标(相对于模板)
 *
 * \返回值:
 *   BOOL			- 成功则返回TRUE,否则返回FALSE
 *
 * 说明:
 *   该函数对指定的DIB图像进行中值滤波。
 *
 ************************************************************************/

BOOL MedianFilter(CDib* pDib,  int nTempWidth, int nTempHeight, 
					 int nTempCenX, int nTempCenY)
{	
	// 临时存放图像数据的指针
	LPBYTE lpImage;
	
	// 循环变量
	int i,j,k,l;
	
	// 指向源图像的指针
	unsigned char*	lpSrc;
	
	// 指向要复制区域的指针
	unsigned char*	lpDst;

	// 图象的高度和宽度
	CSize sizeImage;
	sizeImage = pDib->GetDimensions();

	// 获得图象数据存储的尺寸
	int nSizeImage;
	nSizeImage = pDib->GetSizeImage();

	// 指向滤波器数组的指针
	unsigned char* pUnchFltValue;

	// 给临时存放数据分配内存
	lpImage = (LPBYTE) new char[nSizeImage];
	// 判断是否内存分配失败
	if (lpImage == NULL)
	{
		// 返回
		return FALSE;
	}
	
	// 将原始图像的数据拷贝到临时存放内存中
	memcpy(lpImage, pDib->m_lpImage, nSizeImage);
	
	// 暂时分配内存,以保存滤波器数组
	pUnchFltValue = new unsigned char[nTempHeight * nTempWidth];
	
	// 判断是否内存分配失败
	if (pUnchFltValue == NULL)
	{
		// 释放已分配内存
		delete[]lpImage;
		
		// 返回
		return FALSE;
	}
	
	// 开始中值滤波
	// 行(除去边缘几行)
	for(i = nTempCenY; i < sizeImage.cy - nTempHeight + nTempCenY + 1; i++)
	{
		// 列(除去边缘几列)
		for(j = nTempCenX; j < sizeImage.cx - nTempWidth + nTempCenX + 1; j++)
		{
			// 指向新DIB第i行,第j个象素的指针
			lpDst = (unsigned char*)lpImage + pDib->GetPixelOffset(i,j);
			//lpDst = (unsigned char*)lpImage + sizeImage.cx * (sizeImage.cy - 1 - i) + j;
			
			// 读取滤波器数组
			for (k = 0; k < nTempHeight; k++)
			{
				for (l = 0; l < nTempWidth; l++)
				{
					// 指向DIB第i - nTempCenY + k行,第j - nTempCenX + l个象素的指针
					lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i-nTempCenY+k, j-nTempCenX+l);
					//lpSrc = (unsigned char*)pDib->m_lpImage + sizeImage.cx * (sizeImage.cy - 1 - i + nTempCenY - k) + j - nTempCenX + l;
					
					// 保存象素值
					pUnchFltValue[k * nTempWidth + l] = *lpSrc;
				}
			}
			
			// 获取中值
			//* lpDst = GetMedianValue(pUnchFltValue, nTempHeight * nTempWidth);
		}
	}
	
	// 复制变换后的图像
	memcpy(pDib->m_lpImage, lpImage, nSizeImage);
	
	// 释放内存
	delete[]lpImage;
	delete[]pUnchFltValue;

	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   GetMedianValue()
 *
 * 参数:
 *   unsigned char * pUnchFltValue	- 指向要获取中值的数组指针
 *   int   iFilterLen			- 数组长度
 *
 * 返回值:
 *   unsigned char			- 返回指定数组的中值。
 *
 * 说明:
 *   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
 *
 ************************************************************************/

unsigned char  GetMedianValue(unsigned char * pUnchFltValue, int iFilterLen)
{
	// 循环变量
	int		i;
	int		j;
	
	// 中间变量
	unsigned char bTemp;
	
	// 用冒泡法对数组进行排序
	for (j = 0; j < iFilterLen - 1; j ++)
	{
		for (i = 0; i < iFilterLen - j - 1; i ++)
		{
			if (pUnchFltValue[i] > pUnchFltValue[i + 1])
			{
				// 互换
				bTemp = pUnchFltValue[i];
				pUnchFltValue[i] = pUnchFltValue[i + 1];
				pUnchFltValue[i + 1] = bTemp;
			}
		}
	}
	
	// 计算中值
	if ((iFilterLen & 1) > 0)
	{
		// 数组有奇数个元素,返回中间一个元素
		bTemp = pUnchFltValue[(iFilterLen + 1) / 2];
	}
	else
	{
		// 数组有偶数个元素,返回中间两个元素平均值
		bTemp = (pUnchFltValue[iFilterLen / 2] + pUnchFltValue[iFilterLen / 2 + 1]) / 2;
	}
	
	// 返回中值
	return bTemp;
}

/*************************************************************************
 *
 * \函数名称:
 *   LinearSharpen()
 *
 * \输入参数:
 *   LPBYTE lpImage		- 指向图象数据得指针
 *   int nWidth			- 图象数据宽度
 *   int nHeight		- 图象数据高度
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   线性锐化图象增强
 *   本函数采用拉普拉斯算子对图象进行线性锐化
 *   在原来图象上加上拉普拉斯算子锐化的信息
 *
 *************************************************************************
 */
void LinearSharpen (LPBYTE lpImage, int nWidth, int nHeight)
{
	// 遍历图象的纵坐标
	int y;

	// 遍历图象的横坐标
	int x;

	double * pdGrad ;
	pdGrad = new double[nWidth*nHeight];

	// 初始化为0
	memset(pdGrad, 0, nWidth*nHeight*sizeof(double)) ;

	// 设置模板系数
	static int nWeight[3][3] ;
	nWeight[0][0] = -1 ;   
	nWeight[0][1] = -1 ;   
	nWeight[0][2] = -1 ;   
	nWeight[1][0] = -1 ;   
	nWeight[1][1] =  8 ;   
	nWeight[1][2] = -1 ;   
	nWeight[2][0] = -1 ;   
	nWeight[2][1] = -1 ;   
	nWeight[2][2] = -1 ;   

	//这个变量用来表示Laplacian算子象素值
	int nTmp[3][3];

	// 临时变量
	double dGrad;

	// 模板循环控制变量
	int yy ;
	int xx ;
	for(y=1; y<nHeight-1 ; y++ )
	 for(x=1 ; x<nWidth-1 ; x++ )
	 {
		 dGrad = 0 ; 
		 // Laplacian算子需要的各点象素值
		 
		 // 模板第一行
		 nTmp[0][0] = lpImage[(y-1)*nWidth + x - 1 ] ; 
		 nTmp[0][1] = lpImage[(y-1)*nWidth + x     ] ; 
		 nTmp[0][2] = lpImage[(y-1)*nWidth + x + 1 ] ; 
		 
		 // 模板第二行
		 nTmp[1][0] = lpImage[y*nWidth + x - 1 ] ; 
		 nTmp[1][1] = lpImage[y*nWidth + x     ] ; 
		 nTmp[1][2] = lpImage[y*nWidth + x + 1 ] ; 
		 
		 // 模板第三行
		 nTmp[2][0] = lpImage[(y+1)*nWidth + x - 1 ] ; 
		 nTmp[2][1] = lpImage[(y+1)*nWidth + x     ] ; 
		 nTmp[2][2] = lpImage[(y+1)*nWidth + x + 1 ] ; 
		 
		 // 计算梯度
		 for(yy=0; yy<3; yy++)
			 for(xx=0; xx<3; xx++)
			 {
				 dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;

⌨️ 快捷键说明

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