当前位置: 代码网 > it编程>软件设计>算法 > 图像处理:Retinex算法

图像处理:Retinex算法

2024年08月05日 算法 我要评论
这里将会介绍一种图像增强的算法——Retinex算法。在查找资料的过程中,我发现对于这一部分的讲解并不是很清楚,所以这里我觉得有必要写一篇通俗且清晰的介绍。这里主要介绍三种Retinex算法的变种,它们在原有的Retinex算法的基础上做了进一步的改进和优化。Retinex常用于图像增强的算法,其核心思想是在保留图像细节信息的前提下,调整图像的对比度和亮度。Retinex算法主要有三种不同的实现方式:单尺度Retinex(SSR)、多尺度Retinex(MSR)和多尺度自适应增益Retinex(MSR)。

目录

前言

概念介绍

retinex算法理论

单尺度retinex(ssr)

多尺度retinex(msr)

多尺度自适应增益retinex(msrcr)

opencv实现retinex算法

ssr算法

mcr算法

msrcr算法

效果展示

总结

参考文章


 

前言

这里将会介绍一种图像增强的算法——retinex算法。在查找资料的过程中,我发现对于这一部分的讲解并不是很清楚,所以这里我觉得有必要写一篇通俗且清晰的介绍。这里主要介绍三种retinex算法的变种,它们在原有的retinex算法的基础上做了进一步的改进和优化。

概念介绍

retinex算法理论

retinex的理论基础是三色理论和颜色恒常性。

这意味着物体的颜色是由它对红、绿、蓝三种光线的反射能力来决定的,而不是由反射光强度的绝对值来决定的。同时,物体的颜色也不会受到光照不均匀性的影响,具有一致性。

retinex模型利用这种颜色恒常性,可以在动态范围压缩、边缘增强和颜色恒常三个方面打到平衡,因此可以对各种不同类型的图像进行自适应的增强,不同于传统的只能增强图像某一类特征的方法。

38e5b5599c5d48589b0c13bd7ea628d6.png

retinex理论认为图像是由照度图像与反射图像组成。照度图像指的是物体的入射分量的信息,用eq?%5cfn_phv%20l%28x%2c%20y%29表示;反射图像指的是物体的反射部分,用eq?%5cfn_phv%20r%28x%2c%20y%29表示。公式:

eq?%5cfn_phv%20i%28x%2c%20y%29%20%3dr%28x%2c%20y%29%20*%20l%28x%2c%20y%29

同时,由于对数形式与人类在感受亮度的过程属性最相近,因此将上述过程转换到对数域进行处理,这样做也将复杂的乘法转换为加法:

eq?%5cfn_phv%20i%28x%2c%20y%29%20%3d%20r%28x%2c%20y%29%20+%20l%28x%2c%20y%29

当然,上面的流程是retinex基本框架,不同的retinex算法可能会有不同的细节处理方式。

单尺度retinex(ssr)

单尺度视网膜算法是 retinex 算法中最基础的一个算法。运用的就是上面的方法:

  • 将输入图像转换为对数空间:

eq?%5cfn_phv%20i_%7blog%7d%3din%28i+1%29

其中,eq?%5cfn_phv%20i为输入图像,eq?%5cfn_phv%20i_%7blog%7d为对数图像。

  • 对对数图像进行高斯平滑:

eq?%5cfn_phv%20i_%7bg%7d%3dg*i_%7blog%7d

其中,eq?%5cfn_phv%20i_%7bg%7d为平滑后的对数图像,eq?%5cfn_phv%20g为高斯滤波核。

  • 计算照度图像:

eq?%5cfn_phv%20l%3di_%7blog%7d-i_%7bg%7d

其中,eq?%5cfn_phv%20l为照度图像,即物体的入射分量信息。

  • 计算反射图像:

eq?%5cfn_phv%20r%3di_%7blog%7d-l

其中,eq?%5cfn_phv%20r为反射图像,即物体的反射部分。

  • 将照度图像和反射图像进行指数变换:

eq?%5cfn_phv%20l_%7bexp%7d%3dexp%28l%29-1%5cqquad%20r_%7bexp%7d%3dexp%28r%29-1

其中,eq?%5cfn_phv%20l_%7bexp%7deq?%5cfn_phv%20r_%7bexp%7d分别为指数变换后的照度图像和反射图像。

  • 对输出图像进行亮度调整:

eq?%5cfn_phv%20o%3d%5cfrac%7br_%7bexp%7d%7d%7bmax%28r_%7bexp%7d%29%7dx255

其中,eq?%5cfn_phv%20o为输出图像,eq?%5cfn_phv%20max%28r_%7bexp%7d%29为反射图像中的最大值。通过将反射图像归一化到[0,1]区间,再将其放大到[0, 255]区间,可以增强图像的对比度和细节。

需要注意的是,ssr算法中只使用了一个固定的高斯滤波尺度(没有使用高斯滤波,只是高斯核),因此称为单尺度retinex。虽然算法简单,但在一些场景下仍能取得较好的效果。

多尺度retinex(msr)

1.将原始图像分解为多个尺度的图像

eq?%5cfn_phv%20i_%7b0%7d%3dg%28i_%7b0%7d%2c%5csigma%20_%7b0%7d%29

eq?%5cfn_phv%20i_%7b1%7d%3dg%28i_%7b0%7d%2c%5csigma%20_%7b1%7d%29

......

eq?%5cfn_phv%20i_%7bn%7d%3dg%28i_%7b0%7d%2c%5csigma%20_%7bn%7d%29

其中eq?%5cfn_phv%20g为高斯滤波器,eq?%5cfn_phv%20%5csigma_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的高斯核尺度,eq?%5cfn_phv%20i_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的图像。

2.对每一层尺度图像进行 retinex 处理

eq?%5cfn_phv%20l_%7bi%7d%3dlog%28i_%7bi%7d%29-log%7bg%28i_%7bi%7d%2c%5csigma%20_%7bg%7d%29%7d

eq?%5cfn_phv%20s_%7bi%7d%3dlog%7bg%28i_%7bi%7d%2c%5csigma%20_%7bs%7d%29%7d-log%7bg%28i_%7bi%7d%2c%5csigma%20_%7bg%7d%29%7d

eq?%5cfn_phv%20r_%7bi%7d%3dexp%28l_%7bi%7d+s_%7bi%7d%29

其中eq?%5cfn_phv%20l_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的反射分量,eq?%5cfn_phv%20s_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的光照分量,eq?%5cfn_phv%20r_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的增强后的图像。

3.将各层增强后的图像进行加权融合,得到最终的增强图像

eq?%5cfn_phv%20r_%7bf%7d%3d%5cfrac%7b%5csum%20_%7bi%3d0%7d%5e%7bn%7dw_%7bi%7dr_%7bi%7d%7d%7b%5csum%20_%7bi%3d0%7d%5e%7bn%7dw_%7bi%7d%7d

其中eq?%5cfn_phv%20w_%7bi%7d表示第eq?%5cfn_phv%20i层尺度的权重。

综上所述,多尺度retinex算法与单尺度retinex算法的不同之处在于对图像的分解方式,它将原始图像分解为多个尺度的图像,然后对每一层尺度的图像进行retinex处理,最后进行加权融合得到最终的增强图像。

多尺度自适应增益retinex(msrcr)

msrcr算法是在msr算法的基础上进一步改进而来的,主要是通过自适应增益控制算法的方式来实现对图像的增强。相对于msr算法,msrcr算法主要增加了以下步骤:

  • 多尺度分解:将原始图像分解成不同尺度的子图像。
  • 对数域操作:对每个尺度下的子图像进行对数变换,得到对数域图像。
  • 自适应增益控制:对于每个尺度下的对数域图像,通过计算每个像素点周围像素点的标准差,来确定该像素点的增益系数,即:

eq?%5cfn_phv%20g_%7bi%2cj%7d%3d%5cfrac%7b%5csigma%20_%7bi%2cj%7d%5e%7b2%7d%7d%7b%5csigma%20_%7bi%2cj%7d%5e%7b2%7d+k%7d

其中,eq?%5cfn_phv%20g_%7bi%2cj%7d表示像素点eq?%5cfn_phv%20%28i%2cj%29的增益系数,eq?%5cfn_phv%20%5csigma_%7bi%2cj%7d表示像素点eq?%5cfn_phv%20%28i%2cj%29周围的像素点的标准差,eq?%5cfn_phv%20k为一个常数,用于控制增益系数的大小。

  • 增强处理:对每个尺度下的对数域图像进行乘法增强,即:

eq?%5cfn_phv%20l_%7bi%2cj%7d%5e%7b%27%7d%3dg_%7bi%2cj%7d*l_%7bi%2cj%7d

其中,eq?%5cfn_phv%20l_%7bi%2cj%7d%5e%7b%27%7d为增强后的像素值,eq?%5cfn_phv%20l_%7bi%2cj%7d为原始对数域图像的像素值。

  • 逆对数变换:对每个尺度下的增强后的对数域图像进行逆对数变换,得到增强后的子图像。
  • 尺度合成:将所有增强后的子图像进行合成,得到最终增强后的图像。

需要注意的是,msrcr算法中的增益系数计算公式与msr算法不同,增加了常数eq?%5cfn_phv%20k,这样可以控制增益系数的大小,避免增益系数过大导致图像的过度增强。此外,msrcr算法中还增加了多尺度分解、增强处理和尺度合成等步骤,进一步提高了对不同尺度、不同光照条件下图像的增强效果。

opencv实现retinex算法

在python中是没有集成的第三方库的函数(可能调查不到位),这里我们就根据它的这个原理来实现这三种retinex算法。

在我这里我讲详细一点,尽量让大家去理解,而不是只是套代码去用。

ssr算法

def ssr(img, sigma):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    img_fft = np.fft.fft2(img_log)
    g_recs = sigma // 2 + 1
    result = np.zeros_like(img_fft)
    rows, cols, deep = img_fft.shape
    for z in range(deep):
        for i in range(rows):
            for j in range(cols):
                for k in range(1, g_recs):
                    g = np.exp(-((np.log(k) - np.log(sigma)) ** 2) / (2 * np.log(2) ** 2))
                    result[i, j] += g * img_fft[i, j]
    img_ssr = np.real(np.fft.ifft2(result))
    img_ssr = np.exp(img_ssr) - 1
    img_ssr = np.uint8(cv2.normalize(img_ssr, none, 0, 255, cv2.norm_minmax))
    return img_ssr

实现思路:

mcr算法

def msr(img, scales):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    result = np.zeros_like(img_log)
    img_light = np.zeros_like(img_log)
    r, c, deep = img_log.shape
    for z in range(deep):
        for scale in scales:
            kernel_size = scale * 4 + 1
            # 高斯滤波器的大小,经验公式kernel_size = scale * 4 + 1
            sigma = scale
            img_smooth = cv2.gaussianblur(img_log[:, :, z], (kernel_size, kernel_size), sigma)
            img_detail = img_log[:, :, z] - img_smooth
            result[:, :, z] += cv2.resize(img_detail, (c, r))
            img_light[:, :, z] += cv2.resize(img_smooth, (c, r))
    img_msr = np.exp(result+img_light) - 1
    img_msr = np.uint8(cv2.normalize(img_msr, none, 0, 255, cv2.norm_minmax))
    return img_msr

实现思路:

关于尺度选择

msrcr算法

def msrcr(img, scales, k):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    result = np.zeros_like(img_log)
    img_light = np.zeros_like(img_log)
    r, c, deep = img_log.shape
    for z in range(deep):
        for scale in scales:
            kernel_size = scale * 4 + 1
            # 高斯滤波器的大小,经验公式kernel_size = scale * 4 + 1
            sigma = scale
            g_ratio=sigma**2/(sigma**2+k)
            img_smooth = cv2.gaussianblur(img_log[:, :, z], (kernel_size, kernel_size), sigma)
            img_detail = img_log[:, :, z] - img_smooth
            result[:, :, z] += cv2.resize(img_detail, (c, r))
            result[:, :, z]=result[:, :, z]*g_ratio
            img_light[:, :, z] += cv2.resize(img_smooth, (c, r))

    img_msrcr = np.exp(result+img_light) - 1
    img_msrcr = np.uint8(cv2.normalize(img_msrcr, none, 0, 255, cv2.norm_minmax))
    return img_msrcr

实现思路:

效果展示

7529f5314afb46869a9afd10e6b08b0c.png

上(左)原图,上(右)ssr,下(左)msr,下(右)msrcr 

if __name__=="__main__":
    path=r'./images/ai2.png'
    img=cv2.imread(path)
    imgssr=ssr(img,7)
    imgmsr=msr(img, [1, 3, 5])
    imgmsrcr=msrcr(img,[1,3,5],12)
    imgstack=zjr.stackimages(0.6,([img,imgssr],[imgmsr,imgmsrcr]))
    cv2.imshow("retinex",imgstack)
    cv2.waitkey(0)

总结

在尝试实现像retinex这种没有集成函数的算法时,我遇到了一些困难。这些算法需要深入理解其原理和流程,并在代码具体实现。为了解决这些问题,我参考了其他大佬的代码,但大多数代码并不完整,经常出现报错。我也只能依照自己对算法的理解来实现其功能,可能存在部分错误。因此,我希望可以与大家共同讨论,一起学习和进步。

参考文章

(6条消息) retinex 算法_chaiky的博客-csdn博客

(7条消息) retinex算法详解_chenlee_1的博客-csdn博客

(6条消息) retinex图像增强算法——ssr,msr,msrcr,msrcp,automsrcr_chaoy6565的博客-csdn博客

传统图像处理——图像增强retinex - 知乎 (zhihu.com)

retinex图像增强算法理论基础 - 知乎

 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com