热线电话:0755-23712116
邮箱:contact@shuangyi-tech.com
地址:深圳市宝安区沙井街道后亭茅洲山工业园工业大厦全至科技创新园科创大厦2层2A
前面几篇文章介绍的是图像的空间域滤波,其对像素的处理都是基于像素的某一邻域进行的。本文介绍的图像的灰度变换则不同,其对像素的计算仅仅依赖于当前像素和灰度变换函数。
灰度变换也被称为图像的点运算(只针对图像的某一像素点)是所有图像处理技术中最简单的技术,其变换形式如下:
其中,T是灰度变换函数;r是变换前的灰度;s是变换后的像素。
图像灰度变换的有以下作用:
• 改善图像的质量,使图像能够显示更多的细节,提高图像的对比度(对比度拉伸)
• 有选择的突出图像感兴趣的特征或者抑制图像中不需要的特征
• 可以有效的改变图像的直方图分布,使像素的分布更为均匀
灰度变换函数描述了输入灰度值和输出灰度值之间变换关系,一旦灰度变换函数确定下来了,那么其输出的灰度值也就确定了。可见灰度变换函数的性质就决定了灰度变换所能达到的效果。用于图像灰度变换的函数主要有以下三种:
• 线性函数 (图像反转)
• 对数函数:对数和反对数变换
• 幂律函数:n次幂和n次开方变换
上图给出了几种常见灰度变换函数的曲线图,根据这几种常见函数的曲线形状,可以知道这几种变换的所能达到的效果。例如,对数变换和幂律变换都能实现图像灰度级的扩展/压缩,另外对数变换还有一个重要的性质,它能压缩图像灰度值变换较大的图像的动态范围(例如,傅立叶变换的频谱显示)。令r为变换前的灰度,s为变换后的灰度,则线性变换的函数:
其中,a为直线的斜率,b为在y轴的截距。选择不同的a,b值会有不同的效果:
•
•
•
•
•
•
在进行图像增强时,上述的线性变换函数用的较多的就是图像反转了,根据上面的参数,图像反转的变换函数为:
图像反转的实现是比较简单的,在OpenCV中有对Mat的运算符重载,可以直接Mat r = 255 - img
或者~img
来实现。
对数变换的通用公式是:
其中,c是一个常数,,假设
这使用的对数函数的底为10。由于灰度变换是灰度值之间的一对一的映射,而灰度值区间通常为[0,255],所以在进行灰度变换时,通常使用查表法。也就是,现将每个灰度值的映射后的结果计算出来,在变换时,通过查表得到变换后的灰度值。执行上面结果得到的结果如下:
伽马变换的公式为:
其中c和为正常数。
伽马变换的效果与对数变换有点类似,当
当
伽马变换主要用于图像的校正,对灰度值过高(图像过亮)或者过低(图像过暗)的图像进行修正,增加图像的对比度,从而改善图像的显示效果。
基于OpenCV的实现:
float pixels[256];
for (int i = 0; i < 256; i++)
pixels[i] = i * i *i;
Mat imageLog(image.size(), CV_32FC3);
for (int i = 0; i<image.rows; i++)
{
for (int j = 0; j<image.cols; j++)
{
imageLog.at
这里选择的参数为c = 1,
当选择参数为c = 1,
根据以上的结果,结合伽马变换的函数曲线图,做如下总结:
•
•
灰度变换属于点对点的一一变换,在实现的时候,可以利用查表法。也就是实现将[0,255]区间的各个灰度值的变换后的值计算出来,在变换的时候直接根据灰度值进行查表得到变换后的结果。其实现如下:
/////////////////////////////////////////////////////////////////////
//
// 灰度线性变换函数
// 参数:
// src,输入原图像
// dst,输出图像,类型为CV_32F,大小及通道数与原图像相同
// mapping,灰度映射表,可以根据不同的变换函数,提前计算好图像的灰度映射表
//
////////////////////////////////////////////////////////////////////
void gray_trans(const Mat& src, Mat& dst,float* mapping)
{
int channels = src.channels();
if (channels == 1)
{
dst = Mat(src.size(), CV_32FC1);
for (int i = 0; i < src.rows; i++)
{
float* p1 = dst.ptr<float>(i);
const uchar* p2 = src.ptr(i);
for (int j = 0; j < src.cols; j++)
p1[j] = mapping[p2[j]];
}
}
else if (channels == 3)
{
dst = Mat(src.size(), CV_32FC3);
for (int i = 0; i < src.rows; i++)
{
float* p1 = dst.ptr<float>(i);
const uchar* p2 = src.ptr(i);
for (int j = 0; j < src.cols * 3; j+=3)
{
p1[j] = mapping[p2[j]];
p1[j+1] = mapping[p2[j+1]];
p1[j+2] = mapping[p2[j+2]];
}
}
}
}
其调用也比较简单,根据具体的灰度变换函数,填充灰度映射表即可,以伽马变换为例:
float pixels[256];
for (int i = 0; i < 256; i++)
pixels[i] = powf(i, 1.5);
Mat imageLog;
gray_trans(image, imageLog, pixels);
本文主要对图像的几种常见的灰度变换进行了总结。
• 图像反转,是图像线性变换的一种,可以得到图像负片,能够有效的增强图像的暗色区域中的白色或者灰色细节
• 对数变换,扩展图像中的低灰度区域,压缩图像中的高灰度区域,能够增强图像中的暗色区域的细节;反对数变换与此相反。对数变换还有个重要作用是,能够压缩图像灰度值的动态范围,在傅立叶变换中能够显示更多的变换后的频谱细节。
• 伽马变换,主要用于图像的校正,根据参数
文章转自Brook_icv https://www.cnblogs.com/wangguchangqing/p/6983680.html