灰度变换是空间域图像处理技术中最基础的技术,常用的转换有图像反转、对数变换和伽马(幂律)变换。
图像反转
图像反转的原理很简单,就是颠倒黑白的运算,处理后的效果看起来像是原图的底片,对于一个8bit的灰度图像,变换公式为:
s=255-1-r;
opencv实现:
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main(int argc,char *argv[])
{
Mat image=imread(argv[1],0);
Mat imageDst=~image; //图像反转
imshow("Source Image",image);
imshow("Reversal Image",imageDst);
waitKey();
return 0;
}
Opencv重载了“~”操作符,~image就可以返回image的反转图像。下图可以看到,黑的部分变白,白的部分变黑了。
对数变换
对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。变换方法:
对数变换对图像低灰度部分细节增强的功能过可以从对数图上直观理解:
x轴的0.4大约对应了y轴的0.8,即原图上0~0.4的低灰度部分经过对数运算后扩展到0~0.8的部分,而整个0.4~1的高灰度部分被投影到只有0.8~1的区间,这样就达到了扩展和增强低灰度部分,压缩高灰度部分的值的功能。
从上图还可以看到,对于不同的底数,底数越大,对低灰度部分的扩展就越强,对高灰度部分的压缩也就越强。
Opencv实现:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
using namespace cv;
int main(int argc,char *argv[])
{
Mat image=imread(argv[1]);
Mat imageLog(image.size(),CV_32FC3);
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
imageLog.at<Vec3f>(i,j)[0]=log(1+image.at<Vec3b>(i,j)[0]);
imageLog.at<Vec3f>(i,j)[1]=log(1+image.at<Vec3b>(i,j)[1]);
imageLog.at<Vec3f>(i,j)[2]=log(1+image.at<Vec3b>(i,j)[2]);
}
}
//归一化到0~255
normalize(imageLog,imageLog,0,255,CV_MINMAX);
//转换成8bit图像显示
convertScaleAbs(imageLog,imageLog);
imshow("Soure",image);
imshow("after",imageLog);
waitKey();
return 0;
}
低灰度部分扩展效果:
从右图可以看到,低灰度部分如楼房、天空、树叶部分的像素值得到了扩展,可以看到更多的细节。所以对数变换对照度不均图像中低灰度部分的细节增强很实用。
伽马变换
伽马变换主要用于图像的校正,将灰度过高或者灰度过低的图片进行修正,增强对比度。变换公式就是对原图像上每一个像素值做乘积运算:
伽马变换对图像的修正作用其实就是通过增强低灰度或高灰度的细节实现的,从伽马曲线可以直观理解:
γ值以1为分界,值越小,对图像低灰度部分的扩展作用就越强,值越大,对图像高灰度部分的扩展作用就越强,通过不同的γ值,就可以达到增强低灰度或高灰度部分细节的作用。
Opencv实现:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
using namespace cv;
int main(int argc,char *argv[])
{
Mat image=imread(argv[1]);
Mat imageGamma(image.size(),CV_32FC3);
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
imageGamma.at<Vec3f>(i,j)[0]=(image.at<Vec3b>(i,j)[0])*(image.at<Vec3b>(i,j)[0])*(image.at<Vec3b>(i,j)[0]);
imageGamma.at<Vec3f>(i,j)[1]=(image.at<Vec3b>(i,j)[1])*(image.at<Vec3b>(i,j)[1])*(image.at<Vec3b>(i,j)[1]);
imageGamma.at<Vec3f>(i,j)[2]=(image.at<Vec3b>(i,j)[2])*(image.at<Vec3b>(i,j)[2])*(image.at<Vec3b>(i,j)[2]);
}
}
//归一化到0~255
normalize(imageGamma,imageGamma,0,255,CV_MINMAX);
//转换成8bit图像显示
convertScaleAbs(imageGamma,imageGamma);
imshow("Soure",image);
imshow("Gamma Trans",imageGamma);
waitKey();
return 0;
}
原图是一张有点过曝的图像,高灰度部分的细节不清楚,通过伽马变换扩展高灰度部分,增强对比度:
伽马变换效果: