【OpenCV】Retinex图像增强(SSR,MSR,MSRCR)

10 篇文章 1 订阅

简介

1963年12月30日E. Land作为人类视觉的亮度和颜色感知的模型在俄亥俄州提出了一种颜色恒常知觉的计算理论——Retinex理论。Retinex是一个合成词,它的构成是retina(视网膜)+cortex(皮层)→ Retinex。40多年来,工作在IS&T、NASA的J. J. McCann和D. J. Jobson、Zia-Ur Rahman、G. A. Woodell等人模仿人类视觉系统发展了Retinex算法,从单尺度Retinex算法(single scale retinex, SSR)改进成多尺度加权平均的Retinex算法(multi-scale retinex, MSR),再发展成带彩色恢复的多尺度Retinex算法(multi-scale retinex with color restoration, MSRCR)。

Retinex 理论主要包含了两个方面的内容:物体的颜色是由物体对长波、中波和短波光线的反射能力决定的,而不是由反射光强度的绝对值决定的;物体的色彩不受光照非均性的影响,具有一致性。

(Retinex我简单理解为,拍摄得到的图像是反射图像与光照信息的组合,而增强要做的就是通过拍摄到的原图像,通过计算,去除光照信息,得到真实的反射图像 (个人理解可能有误))

主要思想

Retinex理论的基本假设是原始图像 S S S是光照图像 L L L和反射图像 R R R的乘积,即可表示为下式的形式:
S ( x , y ) = R ( x , y ) ∙ L ( x , y ) S(x,y) = R(x,y)\bullet L(x,y) S(x,y)=R(x,y)L(x,y)
基于Retinex的图像增强的目的就是从原始图像 S S S中估计出光照 L L L,从而分解出 R R R,消除光照不均的影响,以改善图像的视觉效果,正如人类视觉系统那样。在处理中,通常将图像转至对数域,即
log ⁡ S = log ⁡ R + log ⁡ L \log S = \log R+\log L logS=logR+logL
s = r + l s = r + l s=r+l
Retinex方法的核心就是估测照度 L L L,从图像 S S S中估测 L L L分量,并去除L分量,得到原始反射分量 R R R,即:
l = f ( s ) l = f(s) l=f(s)
r = s − f ( s ) r = s-f(s) r=sf(s)
函数 f ( x ) f(x) f(x) 实现对照度L的估计

更多请参考:
dafydd_成: 图像去雾(二)Retinex图像增强算法

单尺度Retinex: SSR(Single Scale Retinex)

r ( x , y ) = log ⁡ S ( x , y ) − log ⁡ [ F ( x , y ) ⊗ S ( x , y ) ] r(x, y) = \log S(x, y) - \log [F(x, y) \otimes S(x, y) ] r(x,y)=logS(x,y)log[F(x,y)S(x,y)]
F ( x , y ) = λ e − ( x 2 + y 2 ) c 2 F(x, y) = \lambda e^{\frac{-(x^2 + y^2)}{c^{2}}} F(x,y)=λec2(x2+y2)
其中的 c c c 是高斯环绕尺度, c c c 值一般取值在80–100`之间, λ \lambda λ是一个尺度,它的取值必须满足下式:
∫ ∫ F ( x , y ) d x d y = 1 \int \int F(x, y)dxdy = 1 F(x,y)dxdy=1
这里的卷积是一个高斯卷积,按照公式计算得到 log ⁡ R \log R logR后进行正规化,将像素值映射到 0-255范围内(计算时几乎没有人按 log ⁡ R \log R logR反求 R R R
更多请参考:
琦小虾:Retinex图像增强算法(SSR, MSR, MSRCR)详解及其OpenCV源码

多尺度Retinex: MSR(Multi-Scale Retinex)

r ( x , y ) = ∑ k K w k { log ⁡ S ( x , y ) − log ⁡ [ F k ( x , y ) ⋅ S ( x , y ) ] } r(x, y) = \sum_{k}^{K}w_{k} \{ \log S(x, y) - \log [F_{k}(x, y) \cdot S(x, y) ] \} r(x,y)=kKwk{logS(x,y)log[Fk(x,y)S(x,y)]}
式中, K K K是高斯中心环绕函数的个数。当 K = 1 K=1 K=1 时,MSR退化为SSR。
通常来讲,为了保证兼有SSR高、中、低三个尺度的优点来考虑, K K K取值通常为3,且有:
w 1 = w 2 = w 3 = 1 3 w_{1} = w_{2} = w_{3} = \frac{1}{3} w1=w2=w3=31
此外,实验表明, c i c_i ci分别取15, 80, 200可以得到较好效果。
一般的Retinex算法对光照图像估计时,都会假设初始光照图像是缓慢变化的,即光照图像是平滑的。但实际并非如此,亮度相差很大区域的边缘处,图像光照变化并不平滑。所以在这种情况下,Retinuex增强算法在亮度差异大区域的增强图像会产生光晕。
另外MSR常见的缺点还有边缘锐化不足,阴影边界突兀,部分颜色发生扭曲,纹理不清晰,高光区域细节没有得到明显改善,对高光区域敏感度小等。

更多请参考:
琦小虾:Retinex图像增强算法(SSR, MSR, MSRCR)详解及其OpenCV源码

带颜色恢复的多尺度Retinex: (Multi-Scale Retinex with Color Restoration)

R M S R C R i ( x , y ) = C i ( x , y ) R M S R i ( x , y ) R_{MSRCR_{i}}(x, y) = C_{i}(x, y) R_{MSR_{i}}(x, y) RMSRCRi(x,y)=Ci(x,y)RMSRi(x,y)

C i ( x , y ) = f [ I i ′ ( x , y ) ] = f [ I i ( x , y ) ∑ j = 1 N I j ( x , y ) ] C_{i}(x, y) = f[I_{i}^{'}(x, y)] = f[\frac{I_{i}(x, y)}{ \sum_{j=1}^{N} I_{j}(x, y)}] Ci(x,y)=f[Ii(x,y)]=f[j=1NIj(x,y)Ii(x,y)]

f [ I i ′ ( x , y ) ] = β log ⁡ [ α I i ′ ( x , y ) ] = β { log ⁡ [ α I i ′ ( x , y ) ] − log ⁡ [ ∑ j = 1 N I j ( x , y ) ] } f[I_{i}^{'}(x, y)] = \beta \log [\alpha I_{i}^{'}(x, y)] = \beta \{ \log [\alpha I_{i}^{'}(x, y)] - \log [\sum_{j=1}^{N}I_{j}(x, y)] \} f[Ii(x,y)]=βlog[αIi(x,y)]=β{log[αIi(x,y)]log[j=1NIj(x,y)]}

其中参数说明如下:

I i ( x , y ) I_{i}(x,y) Ii(x,y)表示第 i i i个通道的图像
C i C_i Ci表示第 i i i个通道的彩色回复因子,用来调节3个通道颜色的比例;
f ( ⋅ ) f(·) f()表示颜色空间的映射函数;
β β β是增益常数;
α α α是受控制的非线性强度;

MSRCR算法利用彩色恢复因子 C C C,调节原始图像中3个颜色通道之间的比例关系,从而把相对较暗区域的信息凸显出来,达到了消除图像色彩失真的缺陷。
处理后的图像局部对比度提高,亮度与真实场景相似,在人们视觉感知下,图像显得更加逼真。

但是MSRCR算法处理图像后,像素值一般会出现负值。所以从对数域 r ( x , y ) r(x, y) r(x,y) 转换为实数域 R ( x , y ) R(x, y) R(x,y) 后,需要通过改变增益Gain,偏差Offset对图像进行修正。使用公式可以表示为:
R M S R C R i ( x , y ) ′ = G ⋅ R M S R C R i ( x , y ) + O R_{MSRCR_{i}}(x, y)' = G\cdot R_{MSRCR_{i}}(x, y) + O RMSRCRi(x,y)=GRMSRCRi(x,y)+O
其中, G G G 表示增益Gain, O O O 表示偏差Offset。它们的值取决于软件中的算法实现。

更多请参考:
琦小虾:Retinex图像增强算法(SSR, MSR, MSRCR)详解及其OpenCV源码

OpenCV代码

#include <opencv2\opencv.hpp>
#include <math.h>

/********************************************************************************
单尺度Retinex图像增强程序
src为待处理图像
sigma为高斯模糊标准差
*********************************************************************************/
void SingleScaleRetinex (const cv::Mat &src, cv::Mat &dst, int sigma);

/********************************************************************************
多尺度Retinex图像增强程序
src为待处理图像
k为尺度参数
w为权重参数
sigma为高斯模糊标准差
*********************************************************************************/
void MultiScaleRetinex  (const cv::Mat &src, cv::Mat &dst, int k, std::vector<double> w, std::vector<double> sigmas);

/********************************************************************************
多尺度Retinex图像增强程序
src     为待处理图像
k       为尺度参数
w       为权重参数
sigma   为高斯模糊标准差
alpha   增益常数
beta    受控的非线性强度
gain    增益
offset  偏差
*********************************************************************************/
void MultiScaleRetinexCR(const cv::Mat &src, cv::Mat &dst, int k, std::vector<double> w, std::vector<double> sigmas, int alpha , int beta , int gain, int offset);

int main()
{

	cv::Mat src = cv::imread("D:\\CPP_Project\\OpenCV410\\OpenCV410\\image\\test_MSRCR.jpg", cv::IMREAD_COLOR);
	if (src.empty()) 
	{
		std::cout << "The image is empty" << std::endl;
		
		return 1;
	}
		
	cv::Mat res1 ,res2, res3;
	

	int k = 3;

	std::vector < double > w(k);
	w[0] = 0.333333333;
	w[1] = 0.333333333;
	w[2] = 0.333333334;

	std::vector<double> s(k);
	s[0] = 15;
	s[1] = 80;
	s[2] = 200;


	SingleScaleRetinex (src, res1, 200);

	MultiScaleRetinex  (src, res2, k, w, s);

	MultiScaleRetinexCR(src, res3, k, w, s, 1, 1, 1, 0);

	cv::imshow("org", src);
	cv::imshow("res1", res1);
	cv::imshow("res2", res2);
	cv::imshow("res3", res3);
	cv::waitKey(0);
	
	return 0;
}

void SingleScaleRetinex(const cv::Mat &src, cv::Mat &dst, int sigma)
{
	cv::Mat doubleI, gaussianI, logI, logGI, logR;

	src.convertTo(doubleI, CV_64FC3, 1.0, 1.0);                    //转换范围,所有图像元素增加1.0保证cvlog正常
	cv::GaussianBlur(doubleI, gaussianI, cv::Size(0,0), sigma);    //SSR算法的核心之一,高斯模糊,当size为零时将通过sigma自动进行计算
	cv::log(doubleI, logI);
	cv::log(gaussianI, logGI);
	logR = logI - logGI;                                           //Retinex公式,Log(R(x,y))=Log(I(x,y))-Log(Gauss(I(x,y)))
	cv::normalize(logR, dst, 0, 255, cv::NORM_MINMAX,CV_8UC3);     //SSR算法的核心之二,线性量化 (似乎在量化的时候没有谁会将 Log[R(x,y)]进行Exp函数的运算而直接得到R(x,y))
}


void MultiScaleRetinex(const cv::Mat &src, cv::Mat &dst, int k, std::vector<double> w, std::vector<double> sigmas) 
{
	cv::Mat doubleI, logI;
	cv::Mat logR = cv::Mat::zeros(src.size(),CV_64FC3);

	src.convertTo(doubleI, CV_64FC3, 1.0, 1.0);                    //转换范围,所有图像元素增加1.0保证cvlog正常
	cv::log(doubleI, logI);

	for (int i = 0; i < k; i++)
	{//Retinex公式,Log(R(x,y)) += w_k(Log(I(x,y))-Log(Gauss_k(I(x,y))))
		cv::Mat tempGI;
		cv::GaussianBlur(doubleI, tempGI, cv::Size(0, 0), sigmas[i]);
		cv::Mat templogGI;
		cv::log(tempGI, templogGI);
		logR += w[i]*(logI - templogGI);
	}

	cv::normalize(logR, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3);  //SSR算法的核心之二,线性量化 (似乎在量化的时候没有谁会将 Log[R(x,y)]进行Exp函数的运算而直接得到R(x,y))
}

//
void MultiScaleRetinexCR(const cv::Mat &src, cv::Mat &dst, int k, std::vector<double> w, std::vector<double> sigmas, int alpha, int beta, int gain, int offset)
{
	

	cv::Mat doubleIl, logI;
	cv::Mat logMSR = cv::Mat::zeros(src.size(), CV_64FC3);

	src.convertTo(doubleIl, CV_64FC3, 1.0, 1.0);                    //转换范围,所有图像元素增加1.0保证cvlog正常
	cv::log(doubleIl, logI);

	for (int i = 0; i < k; i++)
	{//Retinex公式,Log(R(x,y)) += w_k(Log(I(x,y))-Log(Gauss_k(I(x,y))))
		cv::Mat tempGI;
		cv::GaussianBlur(doubleIl, tempGI, cv::Size(0, 0), sigmas[i]);
		cv::Mat templogGI;
		cv::log(tempGI, templogGI);
		logMSR += w[i] * (logI - templogGI);
	}


	std::vector<cv::Mat> logMSRc(3);
	cv::split(logMSR, logMSRc);

	cv::Mat doubleI;
	src.convertTo(doubleI, CV_64FC3);

	std::vector<cv::Mat> doubleIc(3);
	cv::split(doubleI, doubleIc);


	cv::Mat sumDoubleIc =cv::Mat::zeros(doubleI.size(),CV_64FC1);
	for (int i = 0; i < doubleI.rows; i++)
	{
		for (int j = 0; j < doubleI.cols; j++)
		{
			sumDoubleIc.ptr<double>(i)[j] = doubleI.ptr<cv::Vec3d>(i)[j][0] + doubleI.ptr<cv::Vec3d>(i)[j][1] + doubleI.ptr<cv::Vec3d>(i)[j][2];
		}
	}


	std::vector<cv::Mat> divideDoubleIc(3);
	std::vector<cv::Mat> Cc(3);
	std::vector<cv::Mat> MSRCRc(3);
	cv::Mat tempResult;

	for (int i = 0; i < 3; i++)
	{
		cv::divide(doubleIc[i], sumDoubleIc, divideDoubleIc[i]);
		divideDoubleIc[i].convertTo(divideDoubleIc[i], CV_64FC1, 1.0, 1.0);
		cv::log(alpha * divideDoubleIc[i], Cc[i]);
		Cc[i] *= beta;
		MSRCRc[i] = Cc[i].mul(logMSRc[i]);
		MSRCRc[i] = gain * MSRCRc[i] + offset;
	}


	cv::merge(MSRCRc, tempResult);
	cv::normalize(tempResult, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3);
}
  • 14
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
SSRMSRMSRCR都是图像增强算法。其中SSR(Single-Scale Retinex)是一种基于多尺度空间的算法,通过对原始图像的亮度和反射成分进行分离,对反射成分进行增强,以提高图像的对比度和细节。引用中提到,SSR的公式部分为r=s-l=logS-logL,其中原始图像为S(x, y),反射图像为R(x, y),亮度图像为L(x, y)。 MSR(Multi-Scale Retinex)也是一种多尺度空间的图像增强算法,其原理与SSR类似,也是通过分离亮度和反射成分来增强图像。不同之处在于,MSR考虑了多个尺度的信息,以更好地适应不同尺度的细节。 MSRCR(Multi-Scale Retinex with Color Restoration)是在MSR算法的基础上进行了改进,主要用于彩色图像增强MSRCR算法通过对图像的亮度和颜色进行分离,对颜色进行修复,以提高彩色图像的质量和视觉效果。引用中提到,MSRCR算法在处理图像后,像素值一般会出现负值,因此需要通过改变增益和偏差来对图像进行修正。 总的来说,SSRMSRMSRCR都是通过分离图像的亮度和反射成分,对反射成分进行增强,以提高图像的对比度和细节。其中,MSRCR算法还考虑了颜色的修复。这些算法的具体实现细节,包括增益和偏差的取值,取决于算法的软件实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【OpenCVRetinex图像增强SSRMSRMSRCR)](https://blog.csdn.net/Gordon_Wei/article/details/102173309)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Retinex图像增强算法(SSR, MSR, MSRCR)详解](https://blog.csdn.net/Julialove102123/article/details/89312058)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魏Gordon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值