1. 程式人生 > 其它 >影象演算法之區域性直方圖均衡化(灰度影象)

影象演算法之區域性直方圖均衡化(灰度影象)

技術標籤:工作隨筆篇VC++(影象處理篇)

1、函式定義

//區域性直方圖均衡化 ksize - 領域大小,kstep - 領域中心步長
struct stPGMImage* LocalEqualHist(struct stPGMImage* image, int ksize = 3, int kstep = 1);

2、函式實現

#include <math.h>
#include <vector>
using namespace std;
struct stPGMImage* LocalEqualHist(struct stPGMImage* image_src, int ksize, int kstep)
{
	struct stPGMImage* result = (struct stPGMImage*)malloc(sizeof(struct stPGMImage));
	result->height = image_src->height;
	result->width = image_src->width;
	result->maxraw = image_src->maxraw;
	result->type = image_src->type;
	result->data = (unsigned char*)malloc(sizeof(unsigned char) * result->width * result->height);
	memcpy(result->data, image_src->data, image_src->height * image_src->width);

	int gray[256] = { 0 };
	double gray_prob[256] = { 0 };
	vector<unsigned char> indexs_hist;

	if (image_src->height < ksize || image_src->width < ksize || kstep <= 0)
		return NULL;

	double* pOutTemp = new double[image_src->height * image_src->width]{};
	int* pDataRef = new int[image_src->height * image_src->width]{};

	for (int yy = ksize / 2; yy < image_src->height - ksize / 2; yy += kstep)
	{
		unsigned char* pIn = (unsigned char*)(image_src->data + yy * image_src->width);
		for (int xx = ksize / 2; xx < image_src->width - ksize / 2; xx += kstep)
		{
			unsigned char vaule = pIn[xx];
			indexs_hist.push_back(vaule);
			for (int y = yy - ksize / 2; y <= yy + ksize / 2; y++)
			{
				pIn = (unsigned char*)(image_src->data + y * image_src->width);
				for (int x = xx - ksize / 2; x <= xx + ksize / 2; x++)
				{
					vaule = pIn[x];
					int size = indexs_hist.size();

					if (vaule == indexs_hist[size - 1] || vaule == indexs_hist[0])
						;
					else if (vaule > indexs_hist[size - 1])
						indexs_hist.push_back(vaule);
					else if (vaule < indexs_hist[0])
						indexs_hist.insert(begin(indexs_hist), vaule);
					else
					{
						for (int i = 1; i < size; i++)
						{
							if (vaule == indexs_hist[i])
								break;
							else if (vaule < indexs_hist[i] && vaule > indexs_hist[i - 1])
							{
								indexs_hist.insert(begin(indexs_hist) + i, vaule);
								break;
							}
						}
					}

					gray[vaule]++;
				}
			}

			for (int i = 0; i < (int)indexs_hist.size(); i++)
			{
				for (int j = 0; j <= i; j++)
					gray_prob[indexs_hist[i]] += (double)(256 - 1) / (ksize * ksize) * gray[indexs_hist[j]];
			}

			for (int y = yy - ksize / 2; y <= yy + ksize / 2; y++)
			{
				pIn = (unsigned char*)(image_src->data + y * image_src->width);
				for (int x = xx - ksize / 2; x <= xx + ksize / 2; x++)
				{
					pOutTemp[y * image_src->width + x] += gray_prob[pIn[x]];
					pDataRef[y * image_src->width + x]++;
				}
			}

 			for (unsigned char& m : indexs_hist)
 			{
				gray[m] = 0;
				gray_prob[m] = 0;
 			}
 
 			indexs_hist.clear();
		}
	}

	for (int y = 0; y < image_src->height; y++)
	{
		unsigned char* pOut = (unsigned char*)(result->data + y * result->width);
		unsigned char* pIn = (unsigned char*)(image_src->data + y * image_src->width);
		for (int x = 0; x < image_src->width; x++)
		{
			if (pDataRef[y * image_src->width + x] != 0)
				pOut[x] = trunc(pOutTemp[y * image_src->width + x] / pDataRef[y * image_src->width + x] + 0.5);
			else
				pOut[x] = pIn[x];
		}
	}

	delete[] pOutTemp;
	delete[] pDataRef;
	return result;
}

3、效果圖