zl程序教程

您现在的位置是:首页 >  其它

当前栏目

直方图与伽马变换之二

变换 之二 直方图
2023-09-14 09:14:39 时间

图像增强

1.直方图统计与绘制

//直方图统计
vector<int> cal_hist(const Mat&src)
{
	vector<int>histogram(256, 0);

	//计算直方图
	int pixelCount = src.cols*src.rows;
	uchar *imageData = src.data;
	for (int i = 0; i < pixelCount; ++i)
	{
		int gray = imageData[i];
		histogram[gray]++;
	}
	return histogram;
}

opencv绘制直方图

void Draw_HistGram(Mat&src)
{
	vector<int>HistGram;
	Mat histimg;
	HistGram = cal_hist(src);
	
	int length = HistGram.size();
	int max = 0;
	for (int k = 0; k < length; k++)
	{
		//cout << HistGram[k] << endl;
		if (HistGram[k] > max)
			max = HistGram[k];

	}
	cout << "max=" << max << endl;
	int h = length + 100;
	int w = length + 50;
	Mat hist_img = Mat::zeros(h, w, CV_8UC3);
	hist_img = Scalar::all(255);
	int i, j;
	double height;
	for (i = 0; i < length; i++)
	{
		j = i + 20;
		height = (double)HistGram[i] / max * (h - 20);
		rectangle(hist_img, Rect(j, hist_img.rows - height, 1, height), Scalar(158, 158, 58), 1);
	}
	namedWindow("histogram", WINDOW_NORMAL);
	imshow("histogram", hist_img);
}

2.像素统计

//定义灰度特征结构体
struct pixel_statictical
{
	double max=0;
	double min=0;
	double mean=0;
	double ratio_0 = 0;
	double ratio_255 = 0;
};

//灰度统计
void Distribution(const Mat&src,pixel_statictical&pixel)
{
	double cols = src.cols;
	double rows = src.rows;
	float sum = 0;
	double mean = 0;
	double max = 0;
	double min = 300;
	vector<int>hist(256, 0);
	hist = cal_hist(src);
	//cout << hist[0] << " " << hist[255] << endl;
	pixel.ratio_0 = hist[0] / cols / rows;
	pixel.ratio_255 = hist[255] / cols / rows;

	for (int i = 0; i < rows; ++i)
	{
		for (int j = 0; j < cols; ++j)
		{
			double p_ = src.at<uchar>(i, j);
			//cout << pixel/255 << endl;
			sum += p_;
			if (p_ > max)
			{
				max = p_;
			}
			if (p_ < min)
			{
				min = p_;
			}
		}
	}
	pixel.mean = sum / cols / rows;
	pixel.max = max;
	pixel.min = min;
	cout << "max = " << pixel.max << "  min = " << pixel.min << "  mean = " << pixel.mean ;
	cout << "  ratio_0 = " << pixel.ratio_0 << "  ratio_255 = " << pixel.ratio_255 << endl;
}

3.自适应伽马变换

由局部自适应伽马变换更改,讲局部伽马比那换窗口去掉了,采用全局均值

void auto_Gamma_1(Mat &src, Mat &dst,int th)
{
	
	Mat gray,gauss;
	if (src.channels() == 3)
		cvtColor(src, gray, COLOR_BGR2GRAY);
	else
		gray = src.clone();
	int cols = gray.cols;
	
	Mat mask = 255 - gray;
	GaussianBlur(mask, gauss, Size(41, 41), BORDER_DEFAULT);

	double mean = 0;
	for (int k = 0; k < cols*rows; ++k)
	{
		mean += gauss.data[k];
	}
	mean = mean / (cols*rows);
	cout << mean << endl;

	Mat result = gray.clone();
	for (int i = 0; i < rows; ++i)
	{
		for (int j = 0; j < cols; ++j)
		{
			double s = gray.at<uchar>(i, j);
			double b = gauss.at<uchar>(i, j);
			double a = (th - b)/ th;
			double gamma = pow(2, a);
			result.at<uchar>(i,j) = 255.*pow(s / 255., gamma);
		}
	}


	//double mean = 0;
	//for (int k = 0; k < cols*rows; ++k)
	//{
	//	mean += gauss.data[k];
	//}
	//mean = mean / (cols*rows);

	//uchar gray_table[256];
	//for (int i = 0; i < 256; ++i)
	//{
	//	double a = (th - mean) / th;
	//	double gamma = pow(2, a);
	//	gray_table[i] = 255.*pow(static_cast<double>(i) / 255., gamma);

	//}
	//Mat result = gray.clone();
	//for (int k = 0; k < cols*rows; ++k)
	//{
	//	result.data[k] = gray_table[gray.data[k]];
	//}
	dst = result.clone();
}

4.改进伽马变换

void auto_Gamma_2(Mat &src, Mat &dst)  
{
	int rows = src.rows;
	int cols = src.cols;

	double mean = 0;
	for (int k = 0; k < cols*rows; ++k)
	{
		mean += src.data[k];
	}
	mean = mean / (cols*rows);

	uchar gray_table[256];
	double gamma = mean / 128;
	cout << gamma << endl;
	for (int i = 0; i < 256; ++i)
	{
		gray_table[i] = 255.*pow(static_cast<double>(i) / 255., gamma);
	}

	Mat result = Mat(src.size(), CV_8UC1);
	for (int k = 0; k < cols*rows; ++k)
	{
		result.data[k] = gray_table[src.data[k]];
	}
	dst = result.clone();
}