欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图像处理_直方图规定化

程序员文章站 2022-05-28 14:22:14
...
/***************
直方图规定化本质上是一种拟合过程,因此变换得到的直方图
与标准目标图像的直方图并不会完全一致。然而即使只是相似
的拟合,仍然使得规定化的图像在亮度与对比度上具有类似标
准图像的特性,这正是直方图规定化的目的所在。
由于均衡化变换关系无法保证变换后的灰度渠道0-255上的所有
整数值,因此逆映射就会在0-255的某些整数值上没有定义。
可以令他们去逆映射表中最近上一次的有意义的逆映射值
即g(3) = g(4) =g(2) =0,可以取下一次有意义的逆映射值
double* pdStdHist:标准直方图数组(要求已经归一化的直方图)
****************/
BOOL Histst(BYTE* img, double* pdStdHist,int width,int height)
{
	int i, j;

	BYTE gray;//临时变量,存储当前光标像素的灰度值
	int target;//临时变量,存储当前光标像素的目标值。


	
	double dTemp;      //临时变量,存储累加的直方图数据
	int pdTran[256];   //临时变量,存储标准直方图的均衡化的变换矩阵
	memset(pdTran, -1, sizeof(int)* 256);

	//求标准直方图的均衡化变换矩阵
	for (i = 0; i < 256; i++){
		dTemp = 0;
		for (BYTE k = 0; k < i; k++){
			dTemp += *(pdStdHist + k);             //dTemp += pdStdHist[k]
		}
		*(pdTran + (int)(0.5 + 255 * dTemp)) = i;  //pdTran[(int)(0.5+255*dTemp)] = i
	}
	//去除均衡化变换矩阵中的间断点(插值)
	i = 0, j = 0;
	//找寻下一次的值,用while
	while (i < 255){
		if (*(pdTran + i + 1) != -1){
			i++;
			continue;  //如果是有效值,则跳转到下一次循环
		}
		j = 1;
		//取下一次有意义的值
		while ((*(pdTran + i + j) == -1) && ((i + j) <= 255)){
			*(pdTran + i + j) = *(pdTran + i);
			j++;
		}
	}

	double pdHist[256];//临时变量,存储灰度直方图
	GenHist(img, pdHist, 256.0, width, height);

	for (i = 0; i < height; i++){
		for (j = 0; j < width; j++){
			dTemp = 0;
			gray = img[i * width + j];
			for (BYTE k = 0; k < gray; k++){
				dTemp += *(pdHist + k);
			}
			target = *(pdTran + (int)(255 * dTemp));       //target = pdTran[255*dTemp],直接取图像直方图最近的值

			if (target < 0) target = 0;
			if (target > 255) target = 255;
			//写入目标图像
			img[i*width + j] = target;
		}
	}
	return true;
}