图像处理:直方图规定化

    直方图均衡化能够自动的扩展图像灰度的动态范围从而提高图像的对比度增强视觉效果。但是并非所有的图像都适合直方图均衡化,例如图像中大部分灰度值接近0时,由于接近0的像素多权重大,根据均衡原理使用(L-1)*累计概率会造成暗像素的值急剧上升,最终图像亮度变高出现“冲淡效果”。而直方图规定化是使图像具有指定的概率密度分布,在一些情况下能够获得更好的处理效果。

简单叙述一下具体的步骤:

(1)计算图像直方图并进行直方图均衡化得到变化后的灰度。

(2)利用规定的直方图进行直方图均衡化获得变换函数G的所有值,将G的值存入表中。

(3)对于每个均衡化灰度S,在G值得表中找相应的Z值,使得G的值最接近S值,并存储S到Z的映射。

(4)建立原始图想灰度R到Z的映射,最后根据映射关系重建图像,即可获得均衡化图像。

    代码本来想在网上撸一个,结果感觉都看不懂,还是根据原理自己使用C++写一个吧,关键是使用数据结构Map建立映射表。主要代码封装成下面函数HistogramSpecification(Mat &src, Mat &dst, float zhist[])。

/************************************************
@参数:Mat &src  输入图像
@参数:Mat &dst  输出图像
@参数:float zhist[] 规定化的归一化直方图
************************************************/
void HistogramSpecification(Mat &src, Mat &dst, float zhist[])
{
	src.copyTo(dst);     //src拷贝到dst

	int h = src.rows;    //图像高度
	int w = src.cols;    //图像宽度

	int hist[256] = {0};  //各级像素数目
	int S[256] = { 0 };
	map S2Z;    //S到Z的映射
	map r2z;    //r到Z的映射

	//直方图统计
	for (int i = 0; i < h; i++) {
		uchar* p = src.ptr(i);
		for (int j = 0; j < w; j++){
			int vaule = p[j];
			hist[vaule]++;
		}
	}

	//归一化累加直方图
	float sumhist[256] = { 0 };
	for (int i = 0; i < 256; i++){
		int sum = 0;
		for (int j = 0; j <= i; j++)
			sum += hist[j];
		sumhist[i] = sum*1.0 / (h*w);
	}

	//根据sumhist建立均衡化后灰度级数组S
	for (int i = 0; i < 256; i++)
		S[i] = 255 * sumhist[i] + 0.5;
	
	//根据zsumhist建立均衡化后灰度级数组G
	int G[256] = { 0 };
	float zsumhist[256] = { 0.0 };

	for (int i = 0; i < 256; i++){
		float sum = 0;
		for (int j = 0; j <= i; j++)
			sum += zhist[j];
		zsumhist[i] = sum;
	}

	for (int i = 0; i < 256; i++)
		G[i] = zsumhist[i] * 255 + 0.5;

	//令G(Z)=S 建立S->Z的映射表
	for (int i = 0; i < 256; i++) {
		for (int j = 1; j < 256; j++){
			if (abs(S[i] - G[j - 1]) < abs(S[i] - G[j]))
			{
				S2Z[S[i]] = j - 1; 
				break;
			}
		}
	}
	S2Z[S[255]] = G[255];

	//建立r->z映射,即为原像素到规定化像素的映射
	for (int i = 0; i < 256; i++)
		r2z[i] = S2Z[S[i]];

	//重建图像
	for (int i = 0; i < h; i++) {
		uchar *pdata = dst.ptr(i);
		for (int j = 0; j < w; j++){
			*(pdata + j) = r2z[*(pdata + j)];
		}
	}
}


由于规定化的直方图是根据实际需求而设计的,所以没有统一标准。在这里我的直方图如下:

图像处理:直方图规定化_第1张图片

对比一下均衡化的效果和规定化的效果:

图像处理:直方图规定化_第2张图片

    上图下对比还是比较明显的,均衡化的效果真的不好,规定化的效果稍微强一点(主要是我使用的规定化直方图是瞎整的)。若想要获得更好的效果可以更具实际情况改变规定化直方图。

你可能感兴趣的:(图像处理基础,c++,开发语言,后端)