引言
傳統的圖像增強方法主要分為兩方面:空間域和頻域。
空間域中增強方法:
- 直方圖均衡化,對比度以及gama增強等(顏色的增強)
- 均值濾波,高斯濾波(模糊)
- 局部標准差實現對比度增強(銳化)
頻域中增強方法如:
- 小波變換,在圖像的某個變換域內,對圖像的變換系數進行運算,然后通過逆變換獲得圖像增強效果。
一般來說,對於實際項目中,可能用其中一種或幾種方法來進行圖像增強效果一般會很差,我們更多的是對這些算法進行融合,來達到我們想要的效果。
1. 基於直方圖均衡化的圖像增強
直方圖均衡化是通過調整圖像的灰階分布,使得在0~255灰階上的分布更加均衡,提高了圖像的對比度,達到改善圖像主觀視覺效果的目的。對比度較低的圖像適合使用直方圖均衡化方法來增強圖像細節。
彩色圖像的直方圖均衡化實現:
Mat image = imread("D:/opencv練習圖片/均衡化.png"); imshow("原圖像", image); Mat imageRGB[3]; split(image, imageRGB); for (int i = 0; i < 3; i++) { equalizeHist(imageRGB[i], imageRGB[i]); } merge(imageRGB, 3, image); imshow("直方圖均衡化圖像增強效果", image); waitKey(); return 0;
2. 基於拉普拉斯算子的圖像增強
使用中心為5的8鄰域拉普拉斯算子與圖像卷積可以達到銳化增強圖像的目的,拉普拉斯算子如下圖所示:
拉普拉斯算子可以增強局部的圖像對比度:
3. 基於對數Log變換的圖像增強
對數變換可以將圖像的低灰度值部分擴展,顯示出低灰度部分更多的細節,將其高灰度值部分壓縮,減少高灰度值部分的細節,從而達到強調圖像低灰度部分的目的。變換方法:
對數變換對圖像低灰度部分細節增強的功能過可以從對數圖上直觀理解:
上0~0.4的低灰度部分經過對數運算后擴展到0~0.8的部分,而整個0.4~1的高灰度部分被投影到只有0.8~1的區間,這樣就達到了擴展和增強低灰度部分,壓縮高灰度部分的值的功能。
從上圖還可以看到,對於不同的底數,底數越大,對低灰度部分的擴展就越強,對高灰度部分的壓縮也就越強。
int main(int argc, char** argv) { Mat src; src = imread("D:/opencv練習圖片/對數變換.jpg"); imshow("Image", src); Mat srcLog(src.size(), CV_32FC3); for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { //對數變換公式s = clog(1 + r) srcLog.at<Vec3f>(i, j)[0] = log(1 + src.at<Vec3b>(i, j)[0]); srcLog.at<Vec3f>(i, j)[1] = log(1 + src.at<Vec3b>(i, j)[1]); srcLog.at<Vec3f>(i, j)[2] = log(1 + src.at<Vec3b>(i, j)[2]); } } //歸一化到0~255 normalize(srcLog, srcLog, 0, 255, NORM_MINMAX); //轉換成8bit圖像顯示 convertScaleAbs(srcLog, srcLog); imshow("對數變換", srcLog); waitKey(0); return 0; }
這使用的對數函數的底為10。由於灰度變換是灰度值之間的一對一的映射,而灰度值區間通常為[0,255],所以在進行灰度變換時,通常使用查表法。也就是,現將每個灰度值的映射后的結果計算出來,在變換時,通過查表得到變換后的灰度值。執行上面結果得到的結果如下:
由此可見對數變換對於整體對比度偏低並且灰度值偏低的圖像增強效果較好。
4. 基於伽馬變換的圖像增強
伽馬變換主要用於圖像的校正,對灰度值過高(圖像過亮)或者過低(圖像過暗)的圖像進行修正,增加圖像的對比度,從而改善圖像的顯示效果。
變換公式就是對原圖像上每一個像素值做乘積運算:
伽馬變換對圖像的修正作用其實就是通過增強低灰度或高灰度的細節實現的,從伽馬曲線可以直觀理解:
伽馬變換的效果與對數變換有點類似,對於γ<1,擴展低灰度范圍,壓縮高灰度范圍;對於γ>1,壓縮低灰度范圍,擴展高灰度范圍。這樣就能夠顯示更多的圖像的低灰度或者高灰度細節。
opencv實現:
原圖是一張有點過曝的圖像,高灰度部分的細節不清楚,通過伽馬變換擴展高灰度部分,增強對比度:這里選擇的參數為c = 1,r=4(r>1),來擴展圖像的高灰度區域,其結果如下:
int main(int argc, char** argv) { float pixels[256]; for (int i = 0; i < 256; i++) { //i的四次方 pixels[i] = powf(i,4); } Mat src; src = imread("D:/opencv練習圖片/高曝光.png"); imshow("Image", src); Mat srcLog(src.size(), CV_32FC3); for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { //冪律變換(伽馬變換) srcLog.at<Vec3f>(i, j)[0] = pixels[src.at<Vec3b>(i, j)[0]]; srcLog.at<Vec3f>(i, j)[1] = pixels[src.at<Vec3b>(i, j)[1]]; srcLog.at<Vec3f>(i, j)[2] = pixels[src.at<Vec3b>(i, j)[2]]; } } //歸一化到0~255 normalize(srcLog, srcLog, 0, 255, NORM_MINMAX); //轉換成8bit圖像顯示 convertScaleAbs(srcLog, srcLog); imshow("伽馬變換", srcLog); waitKey(0); return 0; }
還可以使用c = 1,r=0.4(r<1),來擴展圖像的低灰度區域,其結果如下:
知識點:pow, powf, powl - 計算 x 的 y 次冪:xy
#include <math.h> //頭文件
double pow(double x, double y); float powf(float x, float y); long double powl(long double x, long double y);
總結
本文主要對圖像的幾種常見的灰度變換進行了總結。
- 圖像反轉,是圖像線性變換的一種,可以得到圖像負片,能夠有效的增強圖像的暗色區域中的白色或者灰色細節
- 對數變換,擴展圖像中的低灰度區域,壓縮圖像中的高灰度區域,能夠增強圖像中的暗色區域的細節;反對數變換與此相反。對數變換還有個重要作用是,能夠壓縮圖像灰度值的動態范圍,在傅立葉變換中能夠顯示更多的變換后的頻譜細節。
- 伽馬變換,主要用於圖像的校正,根據參數 γγ的選擇不同,能夠修正圖像中灰度過高(γ>1)或灰度過低(γ<1)
參考鏈接:(8條消息) 圖像灰度變換及實現_牧野的博客-CSDN博客_圖像灰度變換