1. 程式人生 > >OpenCV影象增強演算法實現(直方圖均衡化、拉普拉斯、Log、Gamma)

OpenCV影象增強演算法實現(直方圖均衡化、拉普拉斯、Log、Gamma)

1. 基於直方圖均衡化的影象增強

直方圖均衡化是通過調整影象的灰階分佈,使得在0~255灰階上的分佈更加均衡,提高了影象的對比度,達到改善影象主觀視覺效果的目的。對比度較低的影象適合使用直方圖均衡化方法來增強影象細節。 彩色影象的直方圖均衡化實現:
#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;

int main(int argc, char *argv[])
{
	Mat image = imread("Test.jpg", 1);
	if (image.empty())
	{
		std::cout << "開啟圖片失敗,請檢查" << std::endl;
		return -1;
	}
	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鄰域拉普拉斯運算元與影象卷積可以達到銳化增強影象的目的,拉普拉斯運算元如下圖所示:   
拉普拉斯運算元可以增強區域性的影象對比度:
#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;

int main(int argc, char *argv[])
{
	Mat image = imread("Test.jpg", 1);
	if (image.empty())
	{
		std::cout << "開啟圖片失敗,請檢查" << std::endl;
		return -1;
	}
	imshow("原影象", image);
	Mat imageEnhance;
	Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, 0, 5, 0, 0, -1, 0);
	filter2D(image, imageEnhance, CV_8UC3, kernel);
	imshow("拉普拉斯運算元影象增強效果", imageEnhance);
	waitKey();
	return 0;
}


拉普拉斯運算元增強前原影象:
拉普拉斯運算元增強後效果:

3. 基於對數Log變換的影象增強

對數變換可以將影象的低灰度值部分擴充套件,顯示出低灰度部分更多的細節,將其高灰度值部分壓縮,減少高灰度值部分的細節,從而達到強調影象低灰度部分的目的。變換方法:


對數變換對影象低灰度部分細節增強的功能過可以從對數圖上直觀理解:


x軸的0.4大約對應了y軸的0.8,即原圖上0~0.4的低灰度部分經過對數運算後擴充套件到0~0.8的部分,而整個0.4~1的高灰度部分被投影到只有0.8~1的區間,這樣就達到了擴充套件和增強低灰度部分,壓縮高灰度部分的值的功能。

從上圖還可以看到,對於不同的底數,底數越大,對低灰度部分的擴充套件就越強,對高灰度部分的壓縮也就越強。


#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main(int argc, char *argv[])
{
	Mat image = imread("Test.jpg");
	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;
}

對數Log變換增強前原影象:

對數Log變換增強後效果:

對數變換對於整體對比度偏低並且灰度值偏低的影象增強效果較好。

4. 基於伽馬變換的影象增強

伽馬變換主要用於影象的校正,將灰度過高或者灰度過低的圖片進行修正,增強對比度。變換公式就是對原影象上每一個畫素值做乘積運算:


伽馬變換對影象的修正作用其實就是通過增強低灰度或高灰度的細節實現的,從伽馬曲線可以直觀理解:


γ值以1為分界,值越小,對影象低灰度部分的擴充套件作用就越強,值越大,對影象高灰度部分的擴充套件作用就越強,通過不同的γ值,就可以達到增強低灰度或高灰度部分細節的作用。

伽馬變換對於影象對比度偏低,並且整體亮度值偏高(對於於相機過曝)情況下的影象增強效果明顯。
#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main(int argc, char *argv[])
{
	Mat image = imread("Test.jpg");
	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("原圖", image);
	imshow("伽馬變換影象增強效果", imageGamma);
	waitKey();
	return 0;
}

伽馬變換增強前原影象:

伽馬變換增強後效果: