CLAHE代码

为了提高运行速度,把CLAHE的代码进行了修改,方便运行。

CLAHE.h

class CLAHE
{
public:
	CLAHE(void);
	~CLAHE(void);
	int m_nGridX;				 /* CLAHE 宽网格的个数 */
	int m_nGridY;				 /* CLAHE 高网格的个数 */
	unsigned char m_aLUT[256];	/* CLAHE lookup table used for scaling of input image */	   
	int Initial(int nMaxPixel, int nMinPixel, int uiNrBins, int nX, int nY, int nWidth, int nHeight,float fCliplimit);
	int m_nWidth;
	int m_nHeight;
	int m_nCliplimit;
	int m_nHistBins;
	int m_nGridSize_X;
	int m_nGridSize_Y;
	int *m_pMapArray;
	int m_nGridSize;			/* Actual size of contextual regions */
	int ProcessCLAHE(unsigned char* pImage);
	void MakeHistogram(unsigned char* pImage,int* pulHistogram);
	void ClipHistogram(int* pulHistogram);
	void MapHistogram(int* pulHistogram);
	void Interpolate (unsigned char * pImage);
	int m_nMaxPixel;
	int m_nMinPixel;
	void ShiftInterpolate(unsigned char* pImage, int nSizeX, int nSizeY, int* pulMapLU,	int* pulMapRU, int *pulMapLB, int *pulMapRB);
	int LineInterpolate(unsigned char* pImage, int nSizeX, int nSizeY, int* pLU, int* pRU, int* pLB, int* pRB);
};
CLAH.CPP
<pre name="code" class="cpp">const unsigned int uiMAX_REG_X = 16;      /* max. # contextual regions in x-direction */
const unsigned int uiMAX_REG_Y = 16;      /* max. # contextual regions in y-direction */
#define	 uiNR_OF_GREY (256)
#define	 uiNR_OF_GREY (4096)

CLAHE::CLAHE(void)
: m_nGridX(0)
, m_nGridY(0)
, m_nWidth(0)
, m_nHeight(0)
, m_nCliplimit(0)
, m_nHistBins(0)
, m_nGridSize_X(0)
, m_nGridSize_Y(0)
, m_pMapArray(0)
, m_nGridSize(0)
, m_nMaxPixel(0)
, m_nMinPixel(0)
{
}

CLAHE::~CLAHE(void)
{
}

int CLAHE::Initial(int nMaxPixel, int nMinPixel, int uiNrBins, int nX, int nY, int nWidth, int nHeight,
					float fCliplimit)
{
	if (nX > uiMAX_REG_X) return -1;					 /* # of regions x-direction too large */
	if (nY > uiMAX_REG_Y) return -2;					 /* # of regions y-direction too large */
	if (nWidth	% nX) return -3;						 /* x-resolution no multiple of uiNrX */
	if (nHeight % nY) return -4;						 /* y-resolution no multiple of uiNrY */
	if (nMaxPixel >= uiNR_OF_GREY) return -5;					 /* maximum too large */
	if (nMinPixel >= nMaxPixel) return -6;						   /* minimum equal or larger than maximum */
	if (nX < 2 || nY < 2) return -7;			/* at least 4 contextual regions required */
	if (fCliplimit == 1.0) return 0;      /* is OK, immediately returns original image. */
	if (uiNrBins == 0) uiNrBins = 128;      /* default value when not specified */


	/* Make lookup table for mapping of greyvalues */
	int i;
	const unsigned char BinSize = (unsigned char)(1 + (nMaxPixel-nMinPixel)/uiNrBins);

	for (i=nMinPixel; i<=nMaxPixel; i++) 
		m_aLUT[i] = (i-nMinPixel) / BinSize;

	m_nMinPixel = nMinPixel;
	m_nMaxPixel = nMaxPixel;
	m_nGridX = nX;
	m_nGridY = nY;
	m_nWidth = nWidth;
	m_nHeight = nHeight;
	m_nHistBins = uiNrBins;
	m_nGridSize_X = m_nWidth / m_nGridX;
	m_nGridSize_Y = m_nHeight / m_nGridY;
	m_nGridSize = m_nGridSize_X * m_nGridSize_Y;
	if(fCliplimit > 0.0) {          /* Calculate actual cliplimit     */
		m_nCliplimit = fCliplimit * m_nGridSize / uiNrBins;
		m_nCliplimit = (m_nCliplimit < 1) ? 1: m_nCliplimit;
	}
	m_pMapArray=(int *)malloc(sizeof(int)*m_nGridX*m_nGridY*m_nHistBins);
	if (m_pMapArray == 0) return -8;      /* Not enough memory! (try reducing uiNrBins) */
	return 1;
}

int CLAHE::ProcessCLAHE(unsigned char* pImage)
{
	int		x,y;
	unsigned char* pImPointer;	
	int			   *pulHist;
	int				uiSubX, uiSubY;		
	int				uiXL, uiXR, uiYU, uiYB;						/* auxiliary variables interpolation routine */					
	int			* pulLU, *pulLB, *pulRU, *pulRB;			/* auxiliary pointers interpolation */


	/* Calculate greylevel mappings for each contextual region */
	for (y=0,pImPointer=pImage; y<m_nGridY; y++)
	{
		for (x=0; x<m_nGridX; x++,pImPointer+=m_nGridSize_X)
		{
			pulHist = &m_pMapArray[m_nHistBins * (y * m_nGridX + x)];
			MakeHistogram(pImPointer,pulHist);
			ClipHistogram(pulHist);
			MapHistogram(pulHist);
		}
		pImPointer += (m_nGridSize_Y-1) * m_nWidth;          /* skip lines, set pointer */
	}

	/* Interpolate greylevel mappings to get CLAHE image */
	Interpolate (pImage);
	
	return 0;  
}

void CLAHE::MakeHistogram(unsigned char* pImage,int* pulHistogram)
{
	unsigned char* pImagePointer;
	int			   i;
		
	memset(pulHistogram, 0, sizeof(int) * m_nHistBins);			/* clear histogram */

	for (i=0; i<m_nGridSize_Y; i++)
	{
		pImagePointer = &pImage[m_nGridSize_X];
		while (pImage < pImagePointer) 
			pulHistogram[m_aLUT[*pImage++]]++;
		pImagePointer += m_nWidth;
		pImage = &pImagePointer[-m_nGridSize_X];
	}
}
/* This function performs clipping of the histogram and redistribution of bins.
 * The histogram is clipped and the number of excess pixels is counted. Afterwards
 * the excess pixels are equally redistributed across the whole histogram (providing
 * the bin count is smaller than the cliplimit).
 */
void CLAHE::ClipHistogram(int* pulHistogram)
{
	int*	pulBinPointer, *pulEndPointer, *pulHisto;
	int		ulNrExcess, ulUpper, ulBinIncr, ulStepSize, i;
	int		lBinExcess;

	ulNrExcess = 0; 
	pulBinPointer = pulHistogram;
	for (i = 0; i < m_nHistBins; i++) 
	{ 
		/* calculate total number of excess pixels */
		lBinExcess = pulBinPointer[i] - m_nCliplimit;
		if (lBinExcess > 0) 
			ulNrExcess += lBinExcess;      /* excess in current bin */
	}

	/* Second part: clip histogram and redistribute excess pixels in each bin */
	ulBinIncr = ulNrExcess / m_nHistBins;          /* average binincrement */
	ulUpper =  m_nCliplimit - ulBinIncr;				  /* Bins larger than ulUpper set to cliplimit */

	for (i=0; i<m_nHistBins; i++)
	{
		if (pulHistogram[i] > m_nCliplimit) 
			pulHistogram[i] = m_nCliplimit;			/* clip bin */
		else
		{
			if (pulHistogram[i] > ulUpper)
			{        /* high bin count */
				ulNrExcess -= (pulHistogram[i] - ulUpper);
				pulHistogram[i]= m_nCliplimit;
			}
			else 
			{  /* low bin count */
				ulNrExcess -= ulBinIncr; 
				pulHistogram[i] += ulBinIncr;
		 }
		}
	}

	while (ulNrExcess) 
	{   
		/* Redistribute remaining excess  */
		pulEndPointer = &pulHistogram[m_nHistBins];
		pulHisto = pulHistogram;

		while (ulNrExcess && (pulHisto<pulEndPointer))
		{
			ulStepSize = m_nHistBins / ulNrExcess;
			if (ulStepSize < 1) ulStepSize = 1;          /* stepsize at least 1 */
			for (pulBinPointer=pulHisto; pulBinPointer<pulEndPointer&&ulNrExcess; pulBinPointer += ulStepSize)
			{
				if (*pulBinPointer < m_nCliplimit) 
				{
					(*pulBinPointer)++;   
					ulNrExcess--;      /* reduce excess */
				}
			}
			pulHisto++;          /* restart redistributing on other bin location */
		}
	}
}

/* This function calculates the equalized lookup table (mapping) by
 * cumulating the input histogram. Note: lookup table is rescaled in range [Min..Max].
 */
void CLAHE::MapHistogram(int* pulHistogram)
{
	int			i;  
	long		ulSum = 0;
	const float fScale = ((float)(m_nMaxPixel - m_nMinPixel)) / m_nGridSize;
	const long	ulMin = (long)m_nMinPixel;

	for (i=0; i<m_nHistBins; i++)
	{
		ulSum += pulHistogram[i]; 
		pulHistogram[i]	= (long)(ulMin+ulSum*fScale);
		if (pulHistogram[i] > m_nMaxPixel)
			pulHistogram[i] = m_nMaxPixel;
	}
}
/* pImage      - pointer to input/output image
 * This function calculates the new greylevel assignments of pixels within a submatrix
 * of the image with size uiXSize and uiYSize. This is done by a bilinear interpolation
 * between four different mappings in order to eliminate boundary artifacts.
 * It uses a division; since division is often an expensive operation, I added code to
 * perform a logical shift instead when feasible.
 */
void CLAHE:: Interpolate (unsigned char * pImage)
{
	int		      x,y;
	int		      uiSubY,uiSubX,uiYU,uiYB,uiXL,uiXR;
	int			 *pulLU,*pulRU,*pulLB,*pulRB;
	unsigned char	*pImPointer;

	//x,y都为0
	pImPointer = pImage;
	uiSubY = m_nGridSize_Y>>1; 
	uiSubX = m_nGridSize_X>>1;
	pulLU = &m_pMapArray[0];
	pulRU = &m_pMapArray[0];
	pulLB = &m_pMapArray[0];
	pulRB = &m_pMapArray[0];
	LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
	pImPointer += uiSubX;              /* set pointer on next matrix */

	//y为0
	uiYU = 0;
	uiYB = 0;
	for (x=1; x<m_nGridX; x++)
	{
		uiSubX = m_nGridSize_X; 
		uiXL = x - 1;
		uiXR = uiXL + 1;

		pulLU = &m_pMapArray[m_nHistBins * uiXL];
		pulRU = &m_pMapArray[m_nHistBins * uiXR];
		pulLB = &m_pMapArray[m_nHistBins * uiXL];
		pulRB = &m_pMapArray[m_nHistBins * uiXR];
		LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
		pImPointer += uiSubX;              /* set pointer on next matrix */

	}

	//y为0,x为m_nGridX
	uiSubX = m_nGridSize_X>>1; 
	uiXL = m_nGridX - 1;
	uiXR = uiXL;

	pulLU = &m_pMapArray[m_nHistBins * uiXL];
	pulRU = &m_pMapArray[m_nHistBins * uiXR];
	pulLB = &m_pMapArray[m_nHistBins * uiXL];
	pulRB = &m_pMapArray[m_nHistBins * uiXR];
	LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
	pImPointer += uiSubX;              /* set pointer on next matrix */
	pImPointer += (uiSubY - 1) * m_nWidth;

	for (y=1; y<m_nGridY; y++)
	{
		uiSubY = m_nGridSize_Y; 
		uiYU = y - 1;
		uiYB = uiYU + 1;

		//x为0
		uiSubX = m_nGridSize_X >> 1;
		pulLU = &m_pMapArray[m_nHistBins * uiYU * m_nGridX];
		pulRU = &m_pMapArray[m_nHistBins * uiYU * m_nGridX];
		pulLB = &m_pMapArray[m_nHistBins * uiYB * m_nGridX];
		pulRB = &m_pMapArray[m_nHistBins * uiYB * m_nGridX];
		LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
		pImPointer += uiSubX;              /* set pointer on next matrix */

		for (x=1; x<m_nGridX; x++)
		{
			uiSubX = m_nGridSize_X; 
			uiXL = x - 1;
			uiXR = uiXL + 1;
			pulLU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX + uiXL)];
			pulRU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX  + uiXR)];
			pulLB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXL)];
			pulRB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXR)];
			LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
			pImPointer += uiSubX;              /* set pointer on next matrix */

		}

		uiSubX = m_nGridSize_X >> 1; 
		uiXL = x - 1;
		uiXR = uiXL;
		pulLU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX + uiXL)];
		pulRU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX  + uiXR)];
		pulLB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXL)];
		pulRB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXR)];
		LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
		pImPointer += uiSubX;              /* set pointer on next matrix */
		pImPointer += (uiSubY - 1) * m_nWidth;
		
	}

	//y为m_nGridY
	uiSubY = m_nGridSize_Y >> 1;   
	uiYU = m_nGridY-1;   
	uiYB = uiYU;

	//x为0
	uiSubX = m_nGridSize_X >> 1;
	pulLU = &m_pMapArray[m_nHistBins * uiYU * m_nGridX];
	pulRU = &m_pMapArray[m_nHistBins * uiYU * m_nGridX];
	pulLB = &m_pMapArray[m_nHistBins * uiYB * m_nGridX];
	pulRB = &m_pMapArray[m_nHistBins * uiYB * m_nGridX];
	LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
	pImPointer += uiSubX;              /* set pointer on next matrix */

	for (x=1; x<m_nGridX; x++)
	{
		uiSubX = m_nGridSize_X; 
		uiXL = x - 1;
		uiXR = uiXL + 1;
		pulLU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX + uiXL)];
		pulRU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX  + uiXR)];
		pulLB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXL)];
		pulRB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXR)];
		LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
		pImPointer += uiSubX;              /* set pointer on next matrix */

	}

	uiSubX = m_nGridSize_X >> 1; 
	uiXL = x - 1;
	uiXR = uiXL;
	pulLU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX + uiXL)];
	pulRU = &m_pMapArray[m_nHistBins * (uiYU * m_nGridX  + uiXR)];
	pulLB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXL)];
	pulRB = &m_pMapArray[m_nHistBins * (uiYB * m_nGridX  + uiXR)];
	LineInterpolate(pImPointer,uiSubX,uiSubY,pulLU,pulRU,pulLB,pulRB);
	pImPointer += uiSubX;              /* set pointer on next matrix */
	pImPointer += (uiSubY - 1) * m_nWidth;

		
}

void CLAHE::ShiftInterpolate(unsigned char* pImage, int nSizeX, int nSizeY, int* pulMapLU,int* pulMapRU, int *pulMapLB, int *pulMapRB)
{
	const int	  uiIncr = m_nWidth-nSizeX;							/* Pointer increment after processing row */
	unsigned char GreyValue; 
	int			  uiNum = nSizeX*nSizeY;	
	int			  x, y, nInvX, nInvY, uiShift = 0;
	while (uiNum >>= 1) uiShift++; /* Calculate 2log of uiNum */
	for (y=0,nInvY=nSizeY; y<nSizeY; y++,nInvY--,pImage+=uiIncr) 
	{
		for (x=0, nInvX=nSizeX; x<nSizeX; x++,nInvX--) 
		{
			GreyValue = m_aLUT[*pImage];      /* get histogram bin value */
			*pImage++ = (unsigned char)((nInvY*(nInvX*pulMapLU[GreyValue] + x*pulMapRU[GreyValue])
				+ y*(nInvX*pulMapLB[GreyValue] + x*pulMapRB[GreyValue])) >> uiShift);
		}
	}
}


int CLAHE::LineInterpolate(unsigned char* pImage, int nSizeX, int nSizeY, int* pulMapLU,int* pulMapRU, int* pulMapLB, int* pulMapRB)
{
	const int	  uiIncr = m_nWidth-nSizeX;							/* Pointer increment after processing row */
	unsigned char GreyValue; 
	int			  uiNum = nSizeX*nSizeY;	
	int			  x, y, nInvX, nInvY, uiShift = 0;
	for (y=0, nInvY=nSizeY; y<nSizeY; y++, nInvY--,pImage+=uiIncr)
	{
		for (x=0,nInvX=nSizeX; x<nSizeX; x++, nInvX--) 
		{
			GreyValue = m_aLUT[*pImage];           /* get histogram bin value */
			*pImage++ = (unsigned char) (( nInvY*(nInvX*pulMapLU[GreyValue] + x*pulMapRU[GreyValue])
				+ y * (nInvX*pulMapLB[GreyValue] + x*pulMapRB[GreyValue])) / uiNum);
		}
	}
	return 0;
}


 
 

你可能感兴趣的:(C++,图像增强,对比度受限直方图增强)