大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
自动伽马校正(Auto Gamma Correction)算法
微信公众号:幼儿园的学霸
目录
理论
在对图像进行处理过程中,查找到一篇对图像进行自动gamma校正的论文,论文名称及链接见参考文献1.
文章的核心描述如下:
Average of brightness is simple element that can be computed in the least amount of time. Basic approach in this article present a technique to estimate appropriate gamma based on average brightness. …, We suppose a gamma which changes average of brightness to 1/2, …
其大概意思是:假定一副合理的图像其所有像素(归一化后)的均值应该在0.5左右,那么自动伽马校正的伽马值就要使得目标图像向这个目标前进。
假设X
是图像的平均值,那么自动伽马校正所需要的伽马值应该基于下列公式进行计算:
根据论文描述:
This paper proposes a method which estimates a power that transport average amount of brightness to center of histogram.
即通过自动gamma校正后图像的灰度直方图将向中心进行偏移。
代码实现
按照上述公式,可以很快实现该算法。代码如下。
1.在实现过程中,采用了查找表的思想,以加快图像处理速度。
2.针对多通道图像,对各通道的gamma再次进行求均值,作为gamma校正的gamma值,以避免多通道图像的偏色现象。该修改在原论中并不存在。
//
// Created by liheng on 11/22/20.
//
#include <iostream>
#include <chrono>
#include <opencv2/opencv.hpp>
//自动Gamma校正算法
//Input Param:src--输入图像,3 channels or 1channels
//Output Param:dst--归一化后的图像,type as src
//Return: null
void AutoGammaCorrection(const cv::Mat &src, cv::Mat &dst)
{
const int channels = src.channels();
const int type = src.type();
assert( type==CV_8UC1 || type==CV_8UC3 );
//======计算gamma值========//
auto mean = cv::mean(src);//求均值
mean[0] = std::log10(0.5) / std::log10(mean[0]/255);//gamma = -0.3/log10(X)
if( 3==channels )
{
mean[1] = std::log10(0.5) / std::log10(mean[1]/255);//gamma = -0.3/log10(X)
mean[2] = std::log10(0.5) / std::log10(mean[2]/255);//gamma = -0.3/log10(X)
//多通道图像,对求得的gamm再次平均,避免偏色现象
auto mean3 = (mean[0]+mean[1]+mean[2])/3;
mean[0]=mean[1]=mean[2] = mean3;
}
//=======计算gamma查找表,减少计算量=======//
//查找表,数组的下标对应图片里面的灰度值
//lut(0,10)=(50,60,70)表示通道1灰度值为10的像素其对应的值为50;
// 通道2灰度值为10的像素其对应的值为60;
// 通道3灰度值为10的像素其对应的值为70
cv::Mat lut(1,256,src.type());
if( 1==channels )
{
for(int i=0; i<256;++i)//灰度等级[0,255]
{
//将灰度值归一化0-1之间
float Y = i*1.0f/255;// or Y=i*0.00392;
//求该灰度值gamma校正后的值
Y = std::pow(Y,mean[0]);
lut.at<unsigned char>(0,i) = cv::saturate_cast<unsigned char>(Y*255);
}
}
else if(3==channels)
{
for(int i=0; i<256;++i)//灰度等级[0,255]
{
//将灰度值归一化0-1之间
float Y = i*1.0f/255;// or Y=i*0.00392;
//求该灰度值gamma校正后的值
auto B = cv::saturate_cast<unsigned char>(std::pow(Y,mean[0])*255);
auto G = cv::saturate_cast<unsigned char>(std::pow(Y,mean[1])*255);
auto R = cv::saturate_cast<unsigned char>(std::pow(Y,mean[2])*255);
lut.at<cv::Vec3b>(0,i) = cv::Vec3b(B,G,R);
}
}
//=========利用查找表进行校正==========//
cv::LUT(src,lut,dst);
}
int main()
{
std::string image_path = "../autogamma.png";
cv::Mat src = cv::imread(image_path,cv::IMREAD_COLOR);
cv::imshow("src",src);
cv::Mat dst1,dst2;
AutoGammaCorrection(src,dst1);
src.convertTo(src,CV_32FC3,1.0/255);
cv::pow(src,0.7,dst2);
cv::normalize(dst2,dst2,0,255,cv::NORM_MINMAX);
cv::convertScaleAbs(dst2,dst2);
cv::imshow("dst1",dst1);
cv::imshow("dst2",dst2);
cv::waitKey(0);
}
效果如下:
类别 | 图像 | 直方图 |
---|---|---|
原图 | ||
自动gamma校正 | ||
手动gamma校正 |
可以看到,
1.自动gamma校正通过自动计算gamma值来调整图像,比手工设定gamma值要明显方便很多。
2.经过自动gamma校正后的图像,其直方图的中心相对原图向中心进行了平移。
参考资料
1.自动伽马校正原英文论文 Automatic gamma correction based on average of
brightness
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190046.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...