图像的对数变换和伽马变换是两种常用的图像增强技术,用于改善图像的亮度和对比度。
对数变换,也称为对数压缩,通过将图像中的像素值取对数来改变像素的亮度。对数变换公式如下:
g(x, y) = c * log(1 + f(x, y))
其中,g(x, y) 是变换后的像素值,f(x, y) 是原始像素值,c 是一个常数,用于控制对比度的增益。对数变换可以扩展低亮度区域,压缩高亮度区域,从而提高图像的可视化效果。
伽马变换,也称为幂律变换,通过对图像进行幂次运算来调整像素的亮度。伽马变换公式如下:
g(x, y) = c * [f(x, y)]^γ
其中,g(x, y) 是变换后的像素值,f(x, y) 是原始像素值,c 是一个常数,用于控制对比度的增益,γ 是一个参数,称为伽马值,用于调整亮度的曲线形状。当 γ 大于 1 时,增加了高灰度级之间的对比度;当 γ 小于 1 时,增加了低灰度级之间的对比度。
通过调整对数变换和伽马变换中的参数,可以根据不同图像的特点和需求,实现对图像亮度和对比度的灵活控制。这些变换技术在数字图像处理中被广泛应用于图像增强、显示和校正等领域。
对数变换的曲线:
对数曲线是一个单调递增的函数
对图像的对数变换:
对空域的对数变换,是指对原图的逐像素实现对数变换的映射,可以看到在像素值较暗的地方,曲线斜率较大,在像素值较亮的地方,曲线斜率比较小;因此,对数变换可以扩展低亮度区域,压缩高亮度区域,从而提高图像的可视化效果。
原图:
对数变换图:
可以看到树林阴影部分明显对比度更加清晰了,但是亮区整体变多了。
伽马变换:
图像的伽马变换(Gamma Transformation)是一种常用的非线性灰度变换方法,可以调整图像的对比度。它基于光照强度与人眼感知之间的非线性关系。伽马变换的一般公式如下:
g(x, y) = c * f(x, y)^γ
其中,f(x, y)表示输入图像的像素值,g(x, y)表示输出图像的像素值,c是常数,γ是调节参数。γ决定了变换的形状,较小的γ值会使得图像变亮,较大的γ值会使得图像变暗。
γ=1时,就是图中的恒等变换;γ>1时,扩增暗区的对比度;γ<1时,扩增亮区对比度
γ=1.5:
γ=0.5:
C++代码:
#include<opencv2/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void Spatial_Log_Trans(Mat src ,Mat &des,float lamda)
{
//为des开辟空间
cout << "图像的尺寸为(" << src.rows << "," << src.cols << ")" << endl;
des.create(src.rows,src.cols, CV_8UC1);
//进行空域的对数变换
for (int r=0;r<src.rows;r++)
{
for (int c=0;c<src.cols;c++)
{
//对数计算公式: g(x, y) = c * log(1 + f(x, y))
int gray=saturate_cast<uchar>(int(lamda *log(1 + src.at<uchar>(r, c))));
des.at<uchar>(r, c) = gray;
//cout << gray << endl;
}
}
}
void draw_log_curve()
{
const int width = 800;
const int height = 600;
Mat curve(height, width, CV_8UC3, Scalar(255, 255, 255));
// 定义放大系数
double c = 30;
for (int x = 0; x < width; x++)
{
// 计算对数变换
int y = static_cast<int>(c * std::log(1 + x));
Point pt(x, height - y);
// 绘制曲线点
circle(curve, pt, 1, Scalar(0, 0, 0), FILLED);
}
imshow("Log Transformation Curve", curve);
}
void Gamma_Trans(const Mat src,Mat &des,float alpha,float gama)
{
//为des开辟空间
des.create(src.rows,src.cols,CV_8UC1);
for (int r=0;r<src.rows;r++)
{
for (int c=0;c<src.cols;c++)
{
//gama变换的公式: g(x, y) = c * f(x, y)^γ
int gray = saturate_cast<uchar>(int(alpha * pow(src.at<uchar>(r, c), gama)));
des.at<uchar>(r, c) = gray;
}
}
}
int main(int argc,char *argv)
{
Mat src = imread("dark.jpg"); //读图
cvtColor(src,src,CV_BGR2GRAY);//灰度变换
PrintMs();
Mat slr,Gamma;
Spatial_Log_Trans(src, slr,30);
float r = 1, ga = 0.8;
Gamma_Trans(src,Gamma, r,ga);
PrintMs("myExchange");
namedWindow("src");
imshow("src", src);
namedWindow("空域的对数变换");
imshow("空域的对数变换", slr);
namedWindow("gama变换");
imshow("gama变换",Gamma);
draw_log_curve();
waitKey(0);
return 0;
}