自动对比度、灰阶调整

自动对比度灰阶调整


1.自动对比度调整

      自动对比度调整,主要作用是把一定范围内的像素值,映射到整个图像灰度范围内。比如对于每个像素都是8Bit的图像而言,整个灰度范围即为[0,255]。实现方式是把一定范围内的像素灰度最小值映射到整个图像所能表示灰度值的最小值,把范围内的最大值灰度映射到整幅图像所能表示灰度值的最大值。如下如所示:

      假设某一幅图像灰度值范围为[Amin,Amax],图像所能表示的最大灰度范围为[aMin,Amax]。为了把一定灰度范围的图像映射到最大灰度范围,首先必须把Amin映射到aMin,然后在乘以系数(aMax-aMin)/(Amax-Amin),最后通过增加aMin,使得一定范围灰度值映射到最大目标灰度范围。因此,自动对比度调整可以用公式表示为:


      Amin不等于Amax。对于每个像素为8Bit的图像而言,aMin=0,aMax=255,因此,上式可以改写为:

    自动色阶调整相关资料暂时还未查阅,待后续添加。

2.代码实现

  主要参考调整图像-自动对比度、自动色阶算法中所描述的算法改写而成。

#define THRESHOLD 0.03
int Auto_Contrast_Gradation(IMAGE_TYPE *bmp_img,double dlowcut ,double dhighcut )
{
	DWORD width,height,dst_index,index;
	WORD  biBitCount;
	T_U8 *bmp_data,R,G,B,*Result_img,BytePerPixel = 3;
	T_U32 line_byte,TmpR,TmpG,TmpB,Sum,PixCount;
	T_U16 i,j,MinBlue,MaxBlue,MinRed,MaxRed,MinGreen,MaxGreen,Max,Min,Y;
	int newX,newY;
	double Tmp;
	double HistRed[256]={0};
    double HistGreen[256]={0};
    double HistBlue[256]={0};
    int bluemap[256]={0};
    int redmap[256]={0};
    int greenmap[256]={0};
	int Map[256] = {0};

	
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;

	FILE *Auto_Contrast_Gradation_fp = fopen("Auto_Contrast_Gradation.bmp","wb");
	
	if(NULL == Auto_Contrast_Gradation_fp)
	{
		printf("Can't open Auto_Contrast_Gradation.bmp\n");
		return -1;
	}
	
	memset(&bf, 0, sizeof(bf));
	memset(&bi, 0, sizeof(bi));

	memcpy(&bf,bmp_img,14);
	memcpy(&bi,&bmp_img[14],40);

	height = bi.biHeight;
	width  = bi.biWidth;
	biBitCount = bi.biBitCount;//每一个像素由24 bits表示,即RGB分量每一个分量用8 bits表示
	line_byte =(width*3+3) & ~0x3;

	fwrite(&bf,sizeof(BITMAPFILEHEADER),1,Auto_Contrast_Gradation_fp);
	fwrite(&bi,sizeof(BITMAPINFOHEADER),1,Auto_Contrast_Gradation_fp);


	bmp_data = bmp_img + BMPHEADSIZE;

	for(i =0;i <  height;i++)
	{
		dst_index = i*line_byte;
		for(j = 0;j < width;j++)
		{
			R = bmp_data[dst_index+2];
			G = bmp_data[dst_index+1];
			B = bmp_data[dst_index];

			HistRed[R]++;
			HistGreen[G]++;
			HistBlue[B]++;

			dst_index += BytePerPixel;

		}
	}

	
	PixCount = height*width;


	//For Blue Channel
	Sum = 0;
	for(Y = 0; Y < 256;Y++)
	{
		Sum += HistBlue[Y];
		if(Sum >= PixCount*dlowcut*THRESHOLD)
		{
				MinBlue = Y;
				break;
		}
	}

	Sum = 0;
	for(Y = 255;Y >=0;Y--)
	{
		Sum +=  HistBlue[Y];
		if(Sum >= PixCount*dhighcut*THRESHOLD)
		{
			MaxBlue = Y;
			break;
		}
	}


	//For Green Channel
	Sum = 0;
	for(Y = 0; Y < 256;Y++)
	{
		Sum += HistGreen[Y];
		if(Sum >= PixCount*dlowcut*THRESHOLD)
		{
			MinGreen = Y;
			break;
		}
	}

	Sum = 0;
	for(Y = 255;Y >=0;Y--)
	{
		Sum +=  HistGreen[Y];
		if(Sum >= PixCount*dhighcut*THRESHOLD)
		{
			MaxGreen = Y;
			break;
		}
	}


	//For Red Channel
	Sum = 0;
	for(Y = 0; Y < 256;Y++)
	{
		Sum += HistRed[Y];
		if(Sum >= PixCount*dlowcut*THRESHOLD)
		{
			MinRed = Y;
			break;
		}
	}

	Sum = 0;
	for(Y = 255;Y >=0;Y--)
	{
		Sum +=  HistRed[Y];
		if(Sum >= PixCount*dhighcut*THRESHOLD)
		{
			MaxRed = Y;
			break;
		}
	}


	for(Y = 0;Y < 256;Y++)
	{
		if(Y <= MinBlue)
			bluemap[Y] = 0;
		else if(Y >=MaxBlue)
			bluemap[Y] = 255;
		else
		{
				Tmp = (double)(Y-MinBlue)/(MaxBlue-MinBlue);
				bluemap[Y] = (int)(Tmp*255);
		}
	}


	for(Y = 0;Y < 256;Y++)
	{
		if(Y <= MinGreen)
			greenmap[Y] = 0;
		else if(Y >=MaxGreen)
			greenmap[Y] = 255;
		else
		{
				Tmp = (double)(Y-MinGreen)/(MaxGreen-MinGreen);
				greenmap[Y] = (int)(Tmp*255);
		}
	}

	

	for(Y = 0;Y < 256;Y++)
	{
		if(Y <= MinRed)
			redmap[Y] = 0;
		else if(Y >=MaxRed)
			redmap[Y] = 255;
		else
		{
				Tmp = (double)(Y-MinRed)/(MaxRed-MinRed);
				redmap[Y] = (int)(Tmp*255);
		}
	}


	//Auto Gradation
	for(i =0;i <  height;i++)
	{
		dst_index = i*line_byte;
		for(j = 0;j < width;j++)
		{
			bmp_data[dst_index] = bluemap[bmp_data[dst_index]];
			bmp_data[dst_index+1] = greenmap[bmp_data[dst_index+1]];
			bmp_data[dst_index+2] = redmap[bmp_data[dst_index+2]];

			dst_index += BytePerPixel;

		}
	}


	//Auto Contrast
	if(MinBlue < MinGreen)
		Min = MinBlue;
	else
		Min = MinGreen;
	if(Min > MinRed)
		Min = MinRed;

	if(MaxBlue > MaxGreen)
		Max = MaxBlue;
	else
		Max = MaxGreen;
	if(Max < MaxRed)
		Max = MaxRed;

	
	for(Y = 0;Y < 256;Y++)
	{
		if(Y <= Min)
			Map[Y] = 0;
		else if(Y >Max)
			Map[Y] = 255;
		else
		{
				Tmp = (double)(Y-Min)/(Max-Min);
				Map[Y] = (int)(Tmp*255);
		}
	}


	for(i =0;i <  height;i++)
	{
		dst_index = i*line_byte;
		for(j = 0;j < width;j++)
		{
			bmp_data[dst_index] = Map[bmp_data[dst_index]];
			bmp_data[dst_index+1] = Map[bmp_data[dst_index+1]];
			bmp_data[dst_index+2] = Map[bmp_data[dst_index+2]];

			dst_index += BytePerPixel;

		}
	}

	fwrite(bmp_data, line_byte*height*sizeof(T_U8), 1, Auto_Contrast_Gradation_fp);
    fclose(Auto_Contrast_Gradation_fp);  
	return 0;
}

3.图像效果


参考资料:

1..http://www.cnblogs.com/Imageshop/archive/2011/11/13/2247614.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值