限制对比度自适应直方图均衡(CLAHE算法)

       限制对比度自适应直方图均衡(CLAHE算法),本算法与普通的自适应直方图均衡不同地方在于对比度限幅,即下面的直方图修剪过程,修剪后的直方图均衡图像时,图像对比度会更自然。这个算法还是挺需要编程技巧的,写程序水平也都是随着解决问题难度而无形中提高的。本程序主要改写自下面的C代码,经过二次加工后感觉可读性高了一些。很多时候摘录的代码一定要经过二次加工,这样才能和项目中的代码保持风格一致,以及逻辑调用一致。 但是原算法处理完后有些偏色,所以在处理完后我额外增加了图层滤色混合操作,可以很好的降低偏色,使增强后的图片看着更自然、舒服。

主要参考资料:
       算法主要分以下三部:
       1.图像分块,以块为单位,先计算直方图,然后修剪直方图,最后均衡;
                                                                       
// 修剪直方图
void ClipHistogram(int* pHistogram, int clipThreshold)
{
	int binExcess = 0, totalExcess = 0, avgBinIncr = 0, upperLimit = 0;
	// 累积超出阈值部分
	for (int i = 0; i < 256; i++) 
	{
		binExcess = pHistogram[i] - clipThreshold;
		if (binExcess > 0)
		{
			totalExcess += binExcess;
		}
	}

	avgBinIncr = totalExcess / 256;
	upperLimit = clipThreshold - avgBinIncr;

	// 修剪直方图并重新分配数值
	for (int i = 0; i < 256; i++) 
	{
		if (pHistogram[i] > clipThreshold)
		{
			pHistogram[i] = clipThreshold;
		}
		else 
		{
			if (pHistogram[i] > upperLimit) 
			{
				totalExcess -= (clipThreshold - pHistogram[i]);
				pHistogram[i] = clipThreshold;
			}
			else 
			{
				totalExcess -= avgBinIncr;
				pHistogram[i] += avgBinIncr;
			}
		}
	}

	// 剩余部分再次分配
	int *pCurBin = pHistogram;
	int *pStartBin = pHistogram;
	int *pEndBin = pHistogram + 255;
	while (totalExcess > 0 && pStartBin < pEndBin)
	{
		int stepSize = 256 / totalExcess;
		if (stepSize < 1)
		{
			stepSize = 1;
		}

		for (pCurBin = pStartBin; pCurBin < pEndBin && totalExcess > 0; pCurBin += stepSize)
		{
			if (*pCurBin < clipThreshold)
			{
				(*pCurBin)++;
				totalExcess--;
			}
		}
		pStartBin++;
	}
}
       2.块间线性插值,这里需要遍历、操作各个图像块,处理起来复杂一些;
                                                             
// 线性插值
void BlocksBilinearInter(uchar *pBlockData, int width, int blockWidth, int blockHeight, int *histogramLU, int *histogramRU, int *histogramLB, int *histogramRB)
{
	int p_offet = (width - blockWidth)*4;
	int blockSize = blockWidth * blockHeight;
	int x_wgt = 0, y_wgt = 0, xinv_wgt = 0, yinv_wgt = 0;

	for (y_wgt = 0, yinv_wgt = blockHeight; y_wgt < blockHeight; y_wgt++, yinv_wgt--, pBlockData += p_offet)
	{
		for (x_wgt = 0, xinv_wgt = blockWidth; x_wgt < blockWidth; x_wgt++, xinv_wgt--, pBlockData += 4) 
		{
			pBlockData[AXJ_BLUE]  = (uchar)((yinv_wgt*(xinv_wgt*histogramLU[pBlockData[AXJ_BLUE]] + x_wgt*histogramRU[pBlockData[AXJ_BLUE]]) + y_wgt*(xinv_wgt*histogramLB[pBlockData[AXJ_BLUE]] + x_wgt*histogramRB[pBlockData[AXJ_BLUE]])) / blockSize);
			pBlockData[AXJ_GREEN] = (uchar)((yinv_wgt*(xinv_wgt*histogramLU[pBlockData[AXJ_GREEN]] + x_wgt*histogramRU[pBlockData[AXJ_GREEN]]) + y_wgt*(xinv_wgt*histogramLB[pBlockData[AXJ_GREEN]] + x_wgt*histogramRB[pBlockData[AXJ_GREEN]])) / blockSize);
			pBlockData[AXJ_RED]   = (uchar)((yinv_wgt*(xinv_wgt*histogramLU[pBlockData[AXJ_RED]] + x_wgt*histogramRU[pBlockData[AXJ_RED]]) + y_wgt*(xinv_wgt*histogramLB[pBlockData[AXJ_RED]] + x_wgt*histogramRB[pBlockData[AXJ_RED]])) / blockSize);
		}
	}
}
       3.与原图做图层滤色混合操作: f(a, b) = 1 - (1 - a)*(1 - b)
       下面是一些增强效果图:
   

   

   

   



  • 8
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值