简单

行远必自迩,登高必自卑

直方图规定化(图像处理)

直方图规定化说明

简单说明一下直方图,就是对图像的像素值的个数进行统计,然后分别计算出每一种像素值所占所有像素数量(图像大小)的比例。累计直方图就是将统计起来算好的比例依次累加。举个例子,当像素值为 1 时它所占得比例所对应的累计比例就是它本身。而像素值为 2 时它的累计比例就是像素值为 1 时的比例加上像素值为 2 时的比例。依次类推,像素值为 255 时,所对应的累计比例为 1。

直方图规定化的操作就是计算两张图片的累计直方图,然后进行对应的计算,将一个图片的色系替换给另一个图片。(个人理解,仅供参考)

处理图片介绍

这里我选用了一张小王子的图片作为需要处理的图片,一张不同颜色比例分布的图片。将不同颜色比例的照片的色系替换掉小王子的色系,生成一张新色系的图片。如果感兴趣,还可以尝试其他图片,不同的图片效果不同。

图片显示


图1 原图


图2 不同比例的颜色(规定化图)


图3 原图 + 规定化图 = 处理后结果

源码

///////////////////////////////////////////////////
// 程序名称:图像处理——直方图规定化
// 编译环境:Mictosoft Visual Studio 2013, EasyX_20200315(beta)
// 作    者:luoyh <2864292458@qq.com>
// 学    校:河南理工大学
// 最后修改:2021-11-18
//

#include<graphics.h>
#include<conio.h>
#include<math.h>

// 计算每一种 DN 值在整个像片中所占的比例
void Hist(IMAGE *pimg, double num[][256])
{
	DWORD *p = GetImageBuffer(pimg);
	for (int j = 0; j < 256; j++)
	{
		double sumr = 0.0;
		double sumg = 0.0;
		double sumb = 0.0;
		for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--)
		{
			if (j == GetRValue(p[i]))
			{
				sumr++;
			}
			if (j == GetGValue(p[i]))
			{
				sumg++;
			}
			if (j == GetBValue(p[i]))
			{
				sumb++;
			}
		}
		num[0][j] = sumr / (pimg->getwidth() * pimg->getheight());
		num[1][j] = sumg / (pimg->getwidth() * pimg->getheight());
		num[2][j] = sumb / (pimg->getwidth() * pimg->getheight());
	}
}

// 累计直方图
void HistTOsum(double Hist[][256], double Sum[][256])
{
	for (int j = 0; j < 3; j++)
	{
		double mysum = 0;
		for (int i = 0; i < 256; i++)
		{
			mysum += Hist[j][i];
			Sum[j][i] = mysum;
		}
	}
}

// 通过累计直方图进行计算 DN 值
void HistTOmark(int DN[][256], double numa[][256], double numb[][256])
{
	double mymin;
	for (int rgb = 0; rgb < 3; rgb++)
	{
		for (int i = 0; i < 256; i++)
		{
			int DNnum = 0;
			mymin = 255;
			for (int j = 0; j < 256; j++)
			{
				if (mymin > fabs(numa[rgb][i] - numb[rgb][j]))
				{
					mymin = fabs(numa[rgb][i] - numb[rgb][j]);
					DNnum = j;
				}
			}
			DN[rgb][i] = DNnum;
		}
	}
}

// 将 DN 值进行映射显示
void TurnToShow(IMAGE *pimg, int DN[][256])
{
	DWORD *p = GetImageBuffer(pimg);
	for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--)
	{
		p[i] = RGB(DN[0][GetRValue(p[i])], DN[1][GetGValue(p[i])], DN[2][GetBValue(p[i])]);
	}
}

int main()
{
	int	width = 0;
	int	height = 0;
	IMAGE imgpolt, imgTM;
	loadimage(&imgpolt, _T("prince.jpeg"));		// 加载原图
	width = imgpolt.getwidth();
	height = imgpolt.getheight();
	initgraph(width, height);
	putimage(0, 0, &imgpolt);
	_getch();

	loadimage(&imgTM, _T("color.jpg"));			// 加载规定化图
	double HistPO[3][256];						// 原图像的频率
	double HistTM[3][256];						// TM图像的频率
	double HistPOsum[3][256];					// 原累计直方图
	double HistTMsum[3][256];					// TM累计直方图
	int DNnumber[3][256];						// 储存 DN 值

	Hist(&imgpolt, HistPO);						// 计算原图的直方图
	Hist(&imgTM, HistTM);						// 计算规定化图片的直方图

	HistTOsum(HistPO, HistPOsum);				// 计算原图的累计直方图
	HistTOsum(HistTM, HistTMsum);				// 计算规定化图片的累计直方图

	HistTOmark(DNnumber, HistPOsum, HistTMsum);	// 计算 DN 值
	TurnToShow(&imgpolt, DNnumber);				// 替换 DN 值

	putimage(0, 0, &imgpolt);
	_getch();
	return 0;
}
分享到

添加评论