图像增强-伽马校正

【简介】伽马校正

伽马校正,英文全称为gamma correction。又称伽马变换(gamma transfer)、伽马非线性变化(gamma nonlinearity)、伽马编码(gamma encoding),或者也可以单纯得称作伽马(gamma)。这是一种用来对图像信号做非线性运算的算子,从结果上来说这是用于调节图像灰度值明暗范围的一种运算。

【原理】校正原理

最简单的伽马校正运算是由一个幂函数的公式所定义的,公式如下 公式.gif

伽马可视化图表.png

其中,c为一个常数系数,控制整条伽马曲线的倾斜程度,一般默认为1。幂函数的幂规定大于0,有一个关键的分界点1。在【0,1】区间伽马曲线呈上凸形态,在【1,无穷】区间呈下凸形态。从伽马曲线图可以看出:

  • 在【0,1】区间,gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分,与此对应的变化是图像的暗部细节会得到提升。

  • 在【1,无穷】,gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分,这样处理和的结果是图像的对比度得到明显提升。

【实验】如何使用伽马校正?

为图像进行伽马编码的目的是用来对人类视觉的特性进行补偿,从而根据人类对光线或者黑白的感知,最大化地利用表示黑白的数据位或带宽。在通常的照明(既不是漆黑一片,也不是令人目眩的明亮)的情况下,人类的视觉大体有伽马或者是幂函数的性质。如果不将图像进行伽马编码,那么数据位或者带宽的利用就会分布不均匀——会有过多的数据位或者带宽用来表示人类根本无法察觉到的差异,而用于表示人类非常敏感的视觉感知范围的数据位或者带宽又会不足。图像的伽马编码并不是必须的(甚至有的时候会适得其反),浮点数格式的颜色值已经提供了一部分对数曲线的线性估计。

  • 在逆光图片下或者想提升暗部细节,可使用伽马校正,并且设置伽马值小于1.
  • 想提高图片的对比度,使得目标与背景之间分明,可以使用伽马校正,并且设置伽马值大于1.

**注意:**伽马值一般设置不要超过【0.7,1.4】,超过此范围图像丢失原有细节就较为严重了。

street-view.jpg

原图

gamma_1_4.jpg

gamma=1.4

backlighting.jpg

原图

gamma_0_7.jpg

gamma=0.7

【代码】

以下代码是基于opencv实现的伽马校正过程

  • 头文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#pragma once
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gamma correction | 伽马校正
// this is gamma correction.h 

#include<opencv2/opencv.hpp>

namespace imageproccess
{
	// gamma correction 
	void GammaCorrection(cv::Mat& dst_image, const cv::Mat& src_image, const int& constant = 1, const float& gamma = 1);


}//namespace imageproccess
  • 源文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gamma correction | 伽马校正
// this is gamma correction.cpp

#include"gamma_correction.h"
#include<cmath>

void imageproccess::GammaCorrection(cv::Mat& dst_image, const cv::Mat& src_image, const int& constant, const float& gamma)
{
	// step1:check the input parameter : 检查输入参数
	assert(constant > 0);
	assert(gamma > 0);
	assert(src_image.size == dst_image.size);

	// step2: traverse every pixel and execute gamma correction: 遍历每个像素点并且执行伽马矫正
	for (size_t i = 0; i < src_image.rows; i++)
	{
		for (size_t j = 0; j < src_image.cols; j++)
		{
			for (size_t k = 0; k < 3; k++)
			{
				// dst = c * src ^ r ( r > 0)
				auto result = constant * std::pow((float)src_image.at<cv::Vec3b>(i, j)[k]/255.0, gamma) * 255;

				// prevent grayscale value from overflowing: 防止灰度值溢出
				dst_image.at<cv::Vec3b>(i, j)[k] = cv::saturate_cast<uchar>(result);
			}
		}
	}
}
  • main文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// image proccess algorithm  | 图像处理算法
// this is main.cpp

#include"gamma_correction.h"

int main()
{
	//cv::Mat src_image = cv::imread("backlighting.jpg");
	cv::Mat src_image2 = cv::imread("street-view.jpg");

	//cv::Mat gamma_0_7 = src_image.clone();
	cv::Mat gamma_1_4 = src_image2.clone();

	//imageproccess::GammaCorrection(gamma_0_7, src_image, 1, 0.7);
	imageproccess::GammaCorrection(gamma_1_4, src_image2, 1, 1.4);

	//cv::imwrite("gamma_0_7.jpg", gamma_0_7);
	cv::imwrite("gamma_1_4.jpg", gamma_1_4);

	//cv::imshow("gamma=0.7", gamma_0_7);
	cv::imshow("gamma=1.4", gamma_1_4);


	cv::waitKey(0);
	return 0;
}

本文由芒果浩明发布,转载请注明来源。 本文链接:https://blog.mangoeffect.net/opencv/gamma-correction.html

https://mango-blog-1255355814.cos.ap-guangzhou.myqcloud.com//gamma-correct-6.jpg


微信公众号