图像灰度级压缩

遥感图像灰度级压缩

在使用灰度共生矩阵计算图像纹理的时候,考虑到计算效率,需要对图像先进行灰度级压缩的操作,比较简单的方法是直接除以前后灰度级的倍数,结果发现这样处理效果不好,原因是影像的直方图分布可能极其不均匀,导致压缩后的图像像素值都集中在最小值周围。针对这种情况可以考虑先进行直方图均衡化,或者先计算累计直方图,然后取2%~98%范围内的灰度值作为有效范围再进行灰度级压缩,下面结合影像介绍一下具体操作过程。

1、图像直方图和累计直方图

直方图表示的是每个灰度级在图像中出现的频数或者概率。
累计直方图表示的是图像组成成分在灰度级的累计概率分布情况,每一个概率值代表小于等于此灰度值的概率。

图像灰度级压缩_第1张图片

左图为直方图曲线,可以看出,这副影像灰度值分布极不均匀,该图像存储数据类型无符号16位整型,灰度值范围0~65535,然而大部分像素灰度值聚集在0-500的范围内。右图为累计直方图曲线,经过计算累计2%处对应的灰度值为90,累计98%处对应的灰度值为400。在进行灰度级压缩时首先判断原始图像的灰度值,如果小于90则设为90,大于400的设为400。

2、灰度压缩

取累计直方图2%和98%处对应的灰度值作为最小值(cumulate2)和最大值(cumulate98),将图像压缩至新的灰度级范围,最小值为 D N n e w m i n DN_{newmin} DNnewmin,最大值为 D N n e w m a x DN_{newmax} DNnewmax

灰度压缩的公式为: D N n e w = D N o − D N o m i n c u m u l a t e 98 − c u m u l a t e 2 ( D N n e w m a x − D N n e w m i n ) DN_{new}=\frac{DN_{o}-DN_{omin}}{cumulate98-cumulate2}\left(DN_{newmax}-DN_{newmin}\right) DNnew=cumulate98cumulate2DNoDNomin(DNnewmaxDNnewmin)

D N n e w DN_{new} DNnew表示压缩后的灰度级, D N o DN_o DNo表示图像原始灰度级,如果 D N o > c u m u l a t e 98 DN_o>cumulate98 DNo>cumulate98, D N o = c u m u l a t e 98 DN_o=cumulate98 DNo=cumulate98,如果 D N o < c u m u l a t e 2 DN_o<cumulate2 DNo<cumulate2, D N o = c u m u l a t e 2 DN_o=cumulate2 DNo=cumulate2

3、关键代码

//统计直方图
void CumulativeHistogram(unsigned short *origindata, int &cutmin, int &cutmax,int height,int width){
	//统计原始图像最大值,最小值
	int array_max = *std::max_element(origindata, origindata + height*width);
	int array_min = *std::min_element(origindata, origindata + height*width);
	
	//原始图像灰度级范围
	int gray_level = array_max - array_min+1;
	int *histogram = new int[gray_level];

	//初始化histogram
	for (int i = 0; i < gray_level; i++)
	{
		histogram[i] = 0;
	}
	
	//直方图统计
	int count = 0;
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			histogram[origindata[count++] - array_min]++;
		}
	}
	
	//累计直方图统计
	float count_percent2 = count*0.02;
	float count_percent98 = count*0.98;
	for (int i = 1; i < gray_level; i++)
	{
		histogram[i] += histogram[i - 1];
		if (histogram[i]>=count_percent2 &&histogram[i-1]<=count_percent2)
		{
			cutmin = i + array_min;
		}

		if (histogram[i]>=count_percent98 && histogram[i-1]<=count_percent98)
		{
			cutmax = i + array_min;
		}
	}

	delete[]histogram;
	histogram = nullptr;

	//std::cout << cutmin << " " << cutmax << std::endl;
}
//灰度级压缩
void ConvertGary(int Width,int Height, unsigned short *array_data,int &cutmin,int &cutmax)
{
	//压缩图像灰度级到64;
	int m_gray_level=64;
	uint8_t *compress_new_data = new uint8_t[Width*Height];

	float compress_level = (float)(cutmax-cutmin) / m_gray_level;
	int data_loc = 0;

	for (size_t i = 0; i < Height; i++)
	{
		for (size_t j = 0; j < Width; j++)
		{

			if (array_data[data_loc]<cutmin)
			{
				array_data[data_loc] = cutmin;
			}

			if (array_data[data_loc]>cutmax)
			{
				array_data[data_loc] = cutmax;
			}

			compress_new_data[data_loc] = (array_data[data_loc] - cutmin) / compress_level;
			data_loc++;
		}
	}
}

4、结果

下图是分别压缩到64级、32级、16级、8级的结果以及对应的直方图曲线。

你可能感兴趣的:(C++,遥感,算法)