1. 程式人生 > >opencv影象增強之MSR

opencv影象增強之MSR

Retinex影象增強演算法

  最近在研究影象增強演算法,發現Retinex這個演算法在彩色增強,尤其是低對比度下特別好用,基於網上已經有不少相關的演算法原理了,我這裡就不說原理性的東西了,下面給出一條連線請初學者自行get(~~)

https://blog.csdn.net/ajianyingxiaoqinghan/article/details/71435098

下面給出一張未經過增強的原圖,很明顯該原圖對比度很低,不仔細看幾乎就獲取不到任何有用資訊,那麼就是我們Retinex大顯身手的時候了,下面直接上程式碼,讓我帶你去挖掘它的本質(>oo<)


#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int M1 = 0;
int M2 = 0;
int M3 = 0;
void MSR(int, void* userdata)
{
	Mat src = imread("fog2.png");
	src.convertTo(src, CV_32FC1, 1.0, 1.0);
	Mat gaussian_src, gaussian_src1, gaussian_src2;
	
	//這裡我是使用的很簡單的高斯模糊,網上也給出了很多不同方式的高斯模糊以及加速,請自行嘗試
	//分別在不同尺度下進行高斯模糊,我分別取了19,39,59的卷積核,各位也可自行嘗試←_←
	GaussianBlur(src, gaussian_src, Size(19, 19), 0, 0);
	GaussianBlur(src, gaussian_src1, Size(39, 39), 0, 0);
	GaussianBlur(src, gaussian_src2, Size(59, 59), 0, 0);
	
	//核心,這裡就是MSR的“M”,通過不同程度的自增達到multi的效果,各位也可以自行嘗試更野的路子O(∩_∩)O
	for (int i = 0; i < M1;i++)
		add(gaussian_src, gaussian_src, gaussian_src);
	for (int i = 0; i < M2; i++)
		add(gaussian_src, gaussian_src, gaussian_src);
	for (int i = 0; i < M3; i++)
		add(gaussian_src2, gaussian_src2, gaussian_src2);
	
	//自增之後當然要進行合併了嘛,不然就不叫累積了嘛
	add(gaussian_src, gaussian_src1, gaussian_src);
	add(gaussian_src, gaussian_src2, gaussian_src);
	log(gaussian_src, gaussian_src);
	log(src, src);
	subtract(src, gaussian_src, src);


	//下面的這個也是核心之一,到了上面這一步,從原理出發,我應該用exp將圖片轉換回去然後歸一化
	//但如果這麼操作的話效果很差,幾乎可以說沒有進行增強,至於為什麼?各位自行百度,畢竟我只是個碼農%>_<%
	//因此我採影象的均值、方差,使用影象的均值方差等資訊進行變換,利用如下的公式
	//(1) Min = Mean - Dynamic * Var;  
	//(2) Max = Mean + Dynamic * Var;
	//然後對Log[R(x,y)]的每一個值Value,進行線性對映: 
	//(3)R(x,y) = ( Value - Min ) / (Max - Min) * (255-0)
	Mat mean_val, stddev_value;
	meanStdDev(src, mean_val, stddev_value);
	double min[3];
	double max[3];
	double minmax[3];
	for (int i = 0; i < 3; i++)
	{
		min[i] = mean_val.at<double>(i, 0) - 2 * stddev_value.at<double>(i, 0);
		max[i] = mean_val.at<double>(i, 0) + 2 * stddev_value.at<double>(i, 0);
		minmax[i] = max[i] - min[i];
	}
	for (int i = 0; i < src.rows; i++)
	for (int j = 0; j < src.cols; j++)
	for (int t = 0; t < 3; t++)
		src.at<Vec3f>(i, j)[t] = 255 * (src.at<Vec3f>(i, j)[t] - min[t]) / minmax[t];
	src.convertTo(src, CV_8UC1, 1);
	imshow("fog", src);
}
int main(int argc,char** argv[])
{
	//原理:S(x,y)= R(x,y)*L(x,y),其中,S(x,y)為你看到的影象,L(x,y)為光照,R(x,y)為物體的本質
	//什麼叫增強?無非就是挖掘物體的本身,撇開這個L(x,y)的R(x,y)就是結果!!!
	//這裡建立一個視窗作為主視窗
	namedWindow("fog", WINDOW_AUTOSIZE);
	
	//這裡建立幾個trackbar來便於觀看不同權值下的效果
	//這裡給出的滾動條的值是為了進行不同程度的自增從而實現不同程度的權值,主要是為了方便,方便,方便!!!
	//如果這裡不進行自增而單純的都賦值為0那就是SSR
	createTrackbar("rate1", "fog", &M1, 10, MSR);
	createTrackbar("rate2", "fog", &M2, 10, MSR);
	createTrackbar("rate3", "fog", &M3, 10, MSR);
	waitKey(0);




}

效果測試,如圖