灰階變換是空間域圖像處理技術中最基礎的技術,常用的轉換有圖像反轉、對數變換和伽馬(幂律)變換。
圖像反轉
圖像反轉的原理很簡單,就是颠倒黑白的運算,處理後的效果看起來像是原圖的底片,對于一個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;
}
原圖是一張有點過曝的圖像,高灰階部分的細節不清楚,通過伽馬變換擴充高灰階部分,增強對比度: