精华内容
下载资源
问答
  • 图像增强算法

    2016-07-07 10:53:51
    图像增强算法
  • 本章介绍几个传统的图像增强算法,并给出matlab实现代码,看一看不同算法的实现效果,最后再介绍一下深度学习在图像增强上的应用。01直方图均衡在直方图中,如果灰度级集中于高灰度区域,图像低灰度就不容易分...

    引言

    由于受到环境,光线等的影响,拍摄的照片清晰度和对比度比较低,不能够突出图像中的重点。图像增强就是通过一定手段来增强图像的对比度,使得其中的人物或者事物更加明显,有利于后边的识别等处理。本章介绍几个传统的图像增强算法,并给出matlab实现代码,看一看不同算法的实现效果,最后再介绍一下深度学习在图像增强上的应用。

    01

    直方图均衡

    在直方图中,如果灰度级集中于高灰度区域,图像低灰度就不容易分辨,如果灰度级集中于低灰度区域,那么高灰度就不容易分辨。为了能够让高低灰度都容易分辨,最好的办法是将图像进行转换,使得灰度级分布概率相同。这就是直方图均衡的目的。假设图像经过如下变换:

    97fa282abae94b547a9ab22e75a318b8.png

    其中L为灰度级。我们的目的是使得灰度级概率分布相等:

    4c894691212b24a26fcd18bd8e458079.png

    变换前灰度级分布和变换后灰度级分布关系为:

    49ccba09514b8511e55cc4eedeaf8dfc.png

    因此有:

    ede2c8bc1e2899257681075379cca9f2.png

    积分有:

    bb6eb92a1c105c49ade5d610ae25f34f.png

    用离散化表示:

    daa402935a213da1ce467df0057fb73d.png

    Matlab代码如下:

    function histogramEqual        imgData=imread('../data/img0.jpg');    gray=rgb2gray(imgData);    imshow(gray);    imwrite(gray, '../data/gray0.jpg');    %calculate histogram    histgramData=linspace(0, 0, 256);    [grayRow, grayColumn]=size(gray);    grayPixelNumber=grayRow*grayColumn;    for i=1:grayRow        for j=1:grayColumn            histgramData(gray(i, j)+1)=histgramData(gray(i, j)+1)+1;        end    end    %histogram equalization    histogramIntegral=linspace(0, 0, 256);    for i=1:256        for j=1:i            histogramIntegral(i)=histogramIntegral(i)+histgramData(j);        end    end        for i=1:grayRow        for j=1:grayColumn            gray(i, j)=round(255*histogramIntegral(gray(i, j)+1)/grayPixelNumber);        end    end        imshow(gray);    imwrite(gray, '../output/histogramEqual.jpg');end

    处理结果:

    160fdd2c075ad77f58847c74dfa46c5d.pnge0846f81d08da6b8e4c0cd5d90b9e0a1.png

    图1.1 直方图均衡化结果(左)原图像(右)结果

    02

    Gamma变换

    Gamma变换主要用于图像修正,将灰度过高或者过低的图片进行修正,增强对比度。变换公式是对每个像素进行乘积运算:

    170704c0da2bfd189d07337eeec45933.png

    从下图的gamma曲线中可以看出其变换原理:

    90ef7e585d2ab8aa69a0ec9a813d8554.png

    图2.1 图像gamma变换

    从图中可以看出当r值大于1,会拉伸图像中灰度级较高的区域,压缩灰度级较低部分;当r值小于1时,会拉伸灰度级较低部分,而压缩灰度级较高部分。这样来调整图像对比度。

    Matlab代码:

    function imageGamma(r)    imgData=imread('../data/img0.jpg');    gray=rgb2gray(imgData);    [grayRow, grayColumn]=size(gray);        gray=double(gray);        for i=1:grayRow        for j=1:grayColumn            gray(i, j)=255*((gray(i, j)/255)^r);            gray(i, j)=round(gray(i, j));        end    end        gray=uint8(gray);        fileName='../output/gamma';    fileSuf='.jpg';    gammaStr=num2str(r);    file=[fileName, gammaStr, fileSuf];    imshow(gray);    imwrite(gray, file);            end

    结果如下:

    8869bb19adaae75aeb7be5bd534c1b90.png5dacd1cd7f3f616af627c8bdf1766168.png

    图2.2 gamma变换(左)r=0.5(右)r=1.5

    03

    Laplace变换

    对图像进行二阶微分操作可以突出图像边缘,增强细节。通常希望构造一个同性滤波器,其对图像方向的变化不敏感。一个最简单的同性滤波器就是laplace算子,定义为:

    4223dab88dde1273d2d3e38188756777.png

    表示为离散形式为:

    20e238921cb29f6b081b07e3653eaff4.png

    实现上式的模板为:

    378f16ccadeedefb6a04c8fcbf5f1682.png

    将laplace变换的结果按照一定比例加入到原灰度图像中:

    efa078dd75fab0a47fb7691b7f814d3d.png

    既可以来突出对比度。

    Matlab代码为:

    % g(x, y)=f(x, y)+c*delta2 f(x, y)function laplace(c)    imgData=imread('../data/img0.jpg');    gray=rgb2gray(imgData);    [grayRow, grayColumn]=size(gray);        gray=double(gray);        %laplace        laplacePlate=[0, 1, 0; 1, -4, 1; 0, 1, 0];    laplaceResult=zeros(grayRow, grayColumn);    laplaceGray=zeros(grayRow, grayColumn);    laplaceGray=double(laplaceGray);    for i=1:grayRow        for j=1:grayColumn            for k=-1:1                for n=-1:1                    if (i+k>=1) && (i+k<=grayRow) && (j+n>=1) && (j+n<=grayColumn)                        grayValue=gray(i+k, j+n);                    else                        grayValue=0;                    end                    laplaceResult(i, j)=laplaceResult(i, j)+laplacePlate(k+2, n+2)*grayValue;                end            end            laplaceGray(i, j)=round(gray(i, j)+c*laplaceResult(i, j));        end    end    maxLaplaceGray=max(max(laplaceGray));    minLaplaceGray=min(min(laplaceGray));    laplaceGray=((laplaceGray-minLaplaceGray) .* 255) ./(maxLaplaceGray-minLaplaceGray);    laplaceGray=uint8(laplaceGray);    fileName='../output/laplace';    fileSuf='.jpg';    gammaStr=num2str(c);    file=[fileName, gammaStr, fileSuf];    figure('name', 'gray');    imshow(laplaceGray);    figure('name', 'laplace');    imshow(laplaceResult);    imwrite(laplaceGray, file);      imwrite(laplaceResult, '../output/laplaceResult.jpg');  end

    结果为:

    bfb8f1e89eef522576c12e933b8a31ca.pnga0b4aa9d7afffd76df283965880a3374.png0b3781d6762aa987fe32d74ed10bc25e.png

    图3.1 laplace算子增强(上左)laplace变换结果(上右)C=0.5(下)C=0.8

    04

    Retix算法

    Retix是一种建立在光学物理特性基础上的算法,假设入射光L(x, y)入射到物体上,经过反射R(x, y),进入到人眼的光变为:

    d14eb6ff155080ecea7c7614fcae5524.png

    通常来说,R(x, y)为物体的内在属性,包含了大量的信息,我们应该最大程度的保留。Retix理论的提出者指出这个L(x, y)可以通过高斯模糊来得到。为了降低运算难度,上式取log,得到:

    fe8e8722e327f8e147db97df9bc41ad9.png

    L(x, y)是通过高斯函数G(x, y)和观察图像S(x, y)卷积得到的。高斯函数为:

    bc718527e025149de17eb2b329c95c05.png

    为了降低卷积运算的的运算量,我们取了7x7的高斯卷积模板。

    Matlab代码为:

    function singleRetix(c)       imgData=imread('../data/img0.jpg');    gray=rgb2gray(imgData);    [grayRow, grayColumn]=size(gray);        gray=double(gray);        gaussConv=zeros(grayRow, grayColumn);    for i=1:grayRow        for j=1:grayColumn            for k=-3:3                for n=-3:3                    gaussValue=two_d_gauss(k, n, c);                    if (i+k>=1) && (i+k<=grayRow) && (j+n>=1) && (j+n<=grayColumn)                        grayValue=gray(i+k, j+n);                    else                        grayValue=0;                    end                                        gaussConv(i, j)=gaussConv(i, j)+grayValue*gaussValue;                end            end        end    end    gray=log(gray);    gaussConv=log(gaussConv);    reflectGray=exp(gray-gaussConv);    maxReflectGray=max(max(reflectGray));    minReflectGray=min(min(reflectGray));    reflectGray=((reflectGray-minReflectGray) .* 255) ./ (maxReflectGray-minReflectGray);    reflectGray=uint8(reflectGray);        fileName='../output/retix';    fileSuf='.jpg';    gammaStr=num2str(c);    file=[fileName, gammaStr, fileSuf];    figure('name', 'processed');    imshow(reflectGray);    imwrite(reflectGray, file);        endfunction res=two_d_gauss(x, y, c)    res=(1/sqrt(2*pi*c))*(-(x^2+y^2)/c^2);end

    结果:

    2caec221d5c47f016f8566a3b6735cbb.png2caec221d5c47f016f8566a3b6735cbb.png

    图4.1 Retix结果(左)sigma=90(右)sigma=150

    05

    基于深度学习的图像增强

    LL-NET是第一个用深度学习来增强图像的方法。在其论文中使用自动编码器从表示学习的角度来解决低光图像增强的问题,这些自动编码器经过训练以学习低光图像中的基础信号特征并自适应地增亮和去噪。LL-NET借鉴了SSDA网络的稀疏特性,可以用来去除图像中噪声。运用网络的泛华能力来提供低照度下的测试图片,让网络来学习到图片的特征,从而降低噪声,提高图像对比度。

    网络结构如下:

    8b88ea204ca4a5202b1fb0c2c2297ef4.png

    图5.1 LL-NET网络结构

    结果为:

    1338451d4d2fb4b7aa0b06fdc8e7a95b.png

    图5.2 结果

    结论

    本文介绍了四种传统的图像增强算法,以及一种基于深度学习的方法。

    往期回顾

    1 【图像处理一】直方图

    2 【图像处理一】加速直方图统计

    3 【图像处理二】HDMI显示1

    4 【图像处理二】HDMI显示2

    bf16b6244351e7bd2d8476bbad7fc06a.pngd2eda501e2f94fdb9343c1de1a25f844.png53f17523acefa4118905e98b4e52659d.pngd2d1aabf28731ab8561bf87c614090ba.png2930817f80c1fcc3728bc45ac8f709a2.png

    公众号

    AI加速

    1e4569cd341914aff1f7f0fd749814c6.png

    用FPGA做有趣的事

    f97dd7a5a833baf7a76dfb3885c2879a.png98f48b1221d14d62853e15f50d496151.png
    展开全文
  • 前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强、图像去雾、彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解。Retinex理论Retinex理论始于Land和McCann于20世纪60年代作出的一...

    前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强、图像去雾、彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解。

    Retinex理论

    Retinex理论始于Land和McCann于20世纪60年代作出的一系列贡献,其基本思想是人感知到某点的颜色和亮度并不仅仅取决于该点进入人眼的绝对光线,还和其周围的颜色和亮度有关。Retinex这个词是由视网膜(Retina)和大脑皮层(Cortex)两个词组合构成的.Land之所以设计这个词,是为了表明他不清楚视觉系统的特性究竟取决于此两个生理结构中的哪一个,抑或是与两者都有关系。

    Land的Retinex模型是建立在以下的基础之上的:

    一、真实世界是无颜色的,我们所感知的颜色是光与物质的相互作用的结果。我们见到的水是无色的,但是水膜—肥皂膜却是显现五彩缤纷,那是薄膜表面光干涉的结果;

    二、每一颜色区域由给定波长的红、绿、蓝三原色构成的;

    三、三原色决定了每个单位区域的颜色。

    Retinex 理论的基本内容是物体的颜色是由物体对长波(红)、中波(绿)和短波(蓝)光线的反射能力决定的,而不是由反射光强度的绝对值决定的;物体的色彩不受光照非均性的影响,具有一致性,即Retinex理论是以色感一致性(颜色恒常性)为基础的。如下图所示,观察者所看到的物体的图像S是由物体表面对入射光L反射得到的,反射率R由物体本身决定,不受入射光L变化。

    图1.Retinex理论中图像的构成

    Retinex理论的基本假设是原始图像S是光照图像L和反射率图像R的乘积,即可表示为下式的形式:

    基于Retinex的图像增强的目的就是从原始图像S中估计出光照L,从而分解出R,消除光照不均的影响,以改善图像的视觉效果,正如人类视觉系统那样。在处理中,通常将图像转至对数域,即,从而将乘积关系转换为和的关系:

    Retinex方法的核心就是估测照度L,从图像S中估测L分量,并去除L分量,得到原始反射分量R,即:

    函数实现对照度L的估计(可以去这么理解,实际很多都是直接估计r分量)。

    Retinex理论的理解

    如果大家看论文,那么在接下去的篇幅当中,肯定会介绍两个经典的Retinex算法:基于路径的Retinex以及基于中心/环绕Retinex。在介绍两个经典的Retinex算法之前,我先来讲一点个人的理解,以便第一次接触该理论的朋友能够更快速地理解。当然,如果我的理解有问题,也请大家帮忙指出。

    Retinex理论就我理解,与降噪类似,该理论的关键就是合理地假设了图像的构成。如果将观察者看到的图像看成是一幅带有乘性噪声的图像,那么入射光的分量就是一种乘性的,相对均匀,且变换缓慢的噪声。Retinex算法所做的就是合理地估计图像中各个位置的噪声,并除去它。

    在极端情况下,我们大可以认为整幅图像中的分量都是均匀的,那么最简单的估计照度L的方式就是在将图像变换到对数域后对整幅图像求均值。因此,我设计了以下算法来验证自己的猜想,流程如下:

    (1) 将图像变换到对数域

    (2) 归一化去除加性分量

    (3) 对步骤3得到的结果求指数,反变换到实数域

    这里为了简化描述,省略了对图像本身格式的变换,算法用Matlab实现:

    % ImOriginal:原始图像

    %type:'add'表示分量是加性的,如雾天图像;'mult'表示分量是乘性的,如对照度的估计

    [m,n,z] = size(ImOriginal);ImOut = uint8(zeros(m,n,z));for i = 1:z

    if strcmp(type,'add')

    ImChannel = double(ImOriginal(:,:,i))+eps; elseif strcmp(type,'mult')

    ImChannel = log(double(ImOriginal(:,:,i))+eps);else

    error('type must be ''add'' or ''mult''');end

    ImOut(:,:,i) = EnhanceOneChannel(ImChannel);end

    ImOut = max(min(ImOut,255), 0);end

    function ImOut = EnhanceOneChannel(ImChannel)

    % 计算计算单个通道的反射分量

    %1.对全图进行照射分量估计

    %2.减去照射分量

    %3.灰度拉伸

    ImChannel = ImChannel./max(ImChannel(:));ImRetinex = round(exp(ImChannel.*5.54));ImOut = uint8(ImRetinex);end

    为了验证算法的有效性,这里使用经典的Retinex算法与我所用的算法进行对比试验,效果如下:

    图2.测试原图

    图3.经典Retinex算法结果

    图4.上述方法结果

    从对比中可以看到,对于去除照度,还原图像本身来讲,效果还可以,并且不会在边缘位置产生光晕现象。缺点就是在去除照度分量L过程中,保留的反射分量R我在上述算法中使用归一化后直接进行反变换。这一步的作用可以近似看成去除一个均匀的直流分量,即均匀的照度分量。由于操作都是全局的,这里默认假设了所有位置的照射分量都是相同的,因此在灰度拉伸的时候没有照顾到局部的特性,图像整体亮度偏暗。当然,全局的照度估计对于图像的增强肯定有相当的局限性,其增强效果在色彩的还原和亮度处理等方面还是有一定缺陷的。

    个人认为,Retinex算法的关键还是正确的分析了噪声的性质。相信很多人都看到利用基于Retinex的图像水下增强、基于Retinex的图像去雾等等,我也好奇,那就试试吧。大雾图片嘛谁没有,前一阵子大雾天,没事拍了几张照片,终于用上了,请看对比图:

    图5.有雾原图

    图6.经典Retinex去雾效果

    图7.上述方法去雾效果

    还是老规矩,这时候对比试验还是最能说明效果的,为此选了一幅干扰很大的图像。基本上各位要是显示器比较差一点,从原图当中是很难看出大雾后面的东西。从去雾效果来看,上述方法的效果并不比经典算法要差,至少在去雾的效果上,本实验结果从主观上给人的感觉还是不错的。

    在上述案例中,最重要的就是正确分析有雾图像的结构,与Retinex理论一开始的核心思想有区别的是,在针对这种加性的干扰时,经典的Retinex算法在处理过程中,其实仅仅是利用其估计加性的干扰分量;当然,抛开Retinex理论对照度、反射率对最终图像形成的核心思想(如图1),后续最重要的就是对这个加性的干扰的估计了。

    对于有雾的图像,我们大可以看作透过一块磨砂玻璃去看一幅清晰的图像,这样大家就能很好理解为什么认为在这个案例中,将雾的干扰认为是一个加性的了。诸如后面两个经典的算法,所有的这类算法归根结底就是更好地利用原图像中的像素点去估计原始照度。从上面例程上可以看出,使用一个全局估计对局部的增强是比较差的,如果存在照度不均匀(雾的浓度不均匀),或者背景颜色亮度很高等情况时,处理结果会趋向恶劣,效果比较差。

    当然,经典也不是完美,从图3中可以看到,经典的算法容易出现光晕效果(蓝色书本文字周围一圈白色),因此后续对于照度估计和去除光晕等问题又有很多基于Retinex理论的变体算法,这里暂不进行介绍。下面开始介绍两个经典的算法,查看Matlab代码下载点击:

    McCann Retinex 算法是McCann和Frankle一起提出的一种Retinex算法,该算法是一种基于多重迭代策略的Retinex算法,单个点的像素值取决于一条特定路径的环绕的结果,经过多次迭代逼近理想值。通过比较螺旋式路径上的各像素点的灰度值来估计和去除图像的照度分量。

    图8.McCann Retinex算法路径选择示意图

    这个图是参照人家论文的,不过我准备像论文那样讲,因为太复杂了,不容易懂。从图中我们可以看到,算法沿着这个螺旋式的路径选取用于估计的点,并且越靠近预测的中心点选取的点数越多。这个从实际物理上也解释的通,靠的近的像素点与中心像素点的相关性肯定要要比远处的点要高。

    该算法估测图像经过以下几个步骤:

    1. 将原图像变换到对数域,彩色图像对各通道都进行对数变换;

    2. 初始化常数图像矩阵,该矩阵作为进行迭代运算的初始值;

    3. 计算路径,如上图8所示,这里令为路径上的点,从远到近排列;

    4. 对路径上的像素点按照如下公式运算:

    公式所表示的大致意思为:从远到近,中心点像素值减去路径上的像素值得到的差值的一半与前一时刻的估计值之间的和。最终,中心像素点的像素大致的形式为

    其中表示中心位置最终的反射率估计,为常数值为转换后的图像中的最大值,在步骤2中被确定。从这里将按照Retinex理论进行分解,最终公式中可以看到,最终照度分量被去除了,而中心位置的反射率由路径上各点的反射率之间的差值进行估计,并且从轨迹上可以看到,靠的越近的在最终估计的时候所占比重越大。

    就我个人理解,这类估计算法,实质是将中心位置和周围亮度之间的差异作为最终中心位置的反射率的估计。如果中心位置亮度本身高,那么最终的结果还是高亮度的;如果中心位置亮度低,那么中心与其它点的差肯定是负值,最终的结果就比较小,亮度就比较低。这就要求路径上的点需要能够很好地代表整幅图像的特性,如果图像本身很规则,那么可能中央与周围计算的结果无法估测该点像素本身的灰度特性,结果就与预期的可能不一样了。如下图9可以看到,算法实质是估计中心和周边的差值,因此图中原本黑色区域的图像由于与周边差别很小,因此呈现高亮度;而在小型的矩形周围随着距离的增大,差别渐渐变小,因此亮度逐渐升高,无法体现原本黑色像素点处原本的亮度特性。

    图9.算法的测试图(来自Retinex in Matlab)

    从原始算法中可以看到,还有一个重要的步骤,就是迭代。迭代的作用是尽可能保留中央周边差的分量,原本每次只保留中央周边差的一半(见步骤4中最后的除2的处理),迭代次数越多,保留的分量就越多,迭代n次保留的分量就是,这样局部的信息就更多,相当于降低动态范围的压缩。这样的操作可以使图像更加自然,但是会增加运算量,下图可以更加明显地看出迭代次数的影响:

    图10.迭代次数的影响

    为了方便各位自己研究,下面我给出该算法源码供大家参考:

    function Retinex = retinex_frankle_mccann(L, nIterations)

    %RETINEX_FRANKLE_McCANN:% Computes the raw Retinex output from an intensity image, based on the

    % original model describedin:

    % Frankle, J.and McCann, J., "Method and Apparatus for Lightness Imaging"% US Patent #4,384,336, May 17, 1983%

    %INPUT:L - logarithmic single-channel intensity image to be processed

    % nIterations - number of Retinex iterations

    %

    %OUTPUT:Retinex - raw Retinex output

    %

    %NOTES: - The input image is assumed to be logarithmic and in the range [0..1]

    % - To obtain the retinex"sensation"prediction, a look-up-table needs to

    % be applied to the raw retinex output

    % - For colour images, apply the algorithm individually for each channel

    %

    %AUTHORS: Florian Ciurea, Brian Funt andJohn McCann.

    % Code developed at Simon Fraser University.

    %

    % For information about the codesee: Brian Funt, Florian Ciurea, andJohn McCann

    %"Retinex in Matlab,"by Proceedings of the IS&T/SID Eighth Color Imaging

    %Conference: Color Science, Systems and Applications, 2000, pp 112-121.

    %

    % paper available online athttp://www.cs.sfu.ca/~colour/publications/IST-2000/

    %

    % Copyright2000. Permission granted to use and copy the code for research and% educational purposes only. Sale of the code isnotpermitted. The code may be

    % redistributed so long as the original sourceandauthors are cited.

    global RR IP OP NP Maximum

    RR = L;Maximum = max(L(:));% maximum color value in the image

    [nrows, ncols] = size(L);shift =2^(fix(log2(min(nrows, ncols)))-1);% initial shift

    OP = Maximum*ones(nrows, ncols);% initialize Old Product

    while (abs(shift) >=1)

    for i =1:nIterations

    CompareWith(0, shift);% horizontal step

    CompareWith(shift, 0);% vertical step

    end

    shift = -shift/2;% update the shift

    end

    Retinex = NP;function CompareWith(s_row, s_col)

    global RR IP OP NP Maximum

    IP = OP;if (s_row + s_col > 0)

    IP((s_row+1):end, (s_col+1):end) = OP(1:(end-s_row), 1:(end-s_col)) + ...

    RR((s_row+1):end, (s_col+1):end) - RR(1:(end-s_row), 1:(end-s_col));else

    IP(1:(end+s_row), 1:(end+s_col)) = OP((1-s_row):end, (1-s_col):end) + ...

    RR(1:(end+s_row),1:(end+s_col)) - RR((1-s_row):end, (1-s_col):end);end

    IP(IP > Maximum) = Maximum;% The Reset operation

    NP = (IP + OP)/2;% average with the previous Old Product

    OP = NP;% get ready for the next comparison

    McCann99 Retinex算法

    McCann99 Retinex算法本质上与McCann Retinex算法没有区别,两者不同的就是在McCann99算法中,不再是使用螺旋式的路径来选取估计像素点,而是使用图像金字塔的方式逐层选取像素。算法同样经取点、比较、平均这几步进行迭代运算。

    图像金字塔的概念很简单,就是对图像进行下采样,以多分辨率的形式表示图像。最顶层的图像分辨率最低,底层的最高(一般为原图)。

    图11.图像金字塔示意图(来自网络)

    如上图所示,McCann99算法就是从顶层开始让每一个像素点与其8个相邻的像素进行比较,估计反射率分量;前一层计算结束之后对估计的反射率分类进行插值运算,使上一层估计的结果的图像与金字塔下一层图像尺寸相同,并再一次进行相同的比较运算;最终,对原始图像进行8邻域的比较结束后就能得到最终的结果,即增强后的图像了。其中,比较操作与McCann算法相同,都是相减后求平均,见上一节步骤4中描述。

    因此,McCann99算法,此处简化描述为以下几步:

    1. 将原图像变换到对数域,彩色图像对各通道都进行对数变换;

    2. 初始化(计算图像金字塔层数;初始化常数图像矩阵,该矩阵作为进行迭代运算的初始值);

    3. 从顶层开始,到最后一层进行8邻域比较运算,运算规则与MccCann Retinex算法相同,见上一节步骤4;

    4. 第n层运算结束后对第n层的运算结果进行插值,变成原来的两倍,与n+1层大小相同(此处默认n越大越靠近底层);

    5. 当最底层计算完毕得到的即最终增强后的图像。

    为了方便各位自己研究,下面我给出该算法源码供大家参考:

    function Retinex = retinex_mccann99(L, nIterations)

    global OPE RRE Maximum

    [nrows ncols] = size(L);% get size of the input image

    nLayers = ComputeLayers(nrows, ncols);% compute the number of pyramid layers

    nrows = nrows/(2^nLayers);% size of image to process for layer 0

    ncols = ncols/(2^nLayers);if (nrows*ncols > 25)                                % not processing images of area > 25error('invalid image size.')                       % at first layer

    end

    Maximum = max(L(:));% maximum color value in the image

    OP = Maximum*ones([nrows ncols]);% initialize Old Product

    for layer = 0:nLayers

    RR = ImageDownResolution(L,2^(nLayers-layer));% reduce input to required layer size

    OPE = [zeros(nrows,1) OP zeros(nrows,1)];% pad OP with additional columns

    OPE = [zeros(1,ncols+2);OPE; zeros(1,ncols+2)];  % and rows

    RRE = [RR(:,1) RR RR(:,end)];% pad RR with additional columns

    RRE = [RRE(1,:);RRE; RRE(end,:)];                % and rows

    for iter =1:nIterations

    CompareWithNeighbor(-1, 0);% North

    CompareWithNeighbor(-1, 1);% North-East

    CompareWithNeighbor(0, 1);% East

    CompareWithNeighbor(1, 1);% South-East

    CompareWithNeighbor(1, 0);% South

    CompareWithNeighbor(1, -1);% South-West

    CompareWithNeighbor(0, -1);% West

    CompareWithNeighbor(-1, -1);% North-West

    end

    NP = OPE(2:(end-1), 2:(end-1));   OP = NP(:, [fix(1:0.5:ncols) ncols]);%%% these two lines are equivalent with

    OP = OP([fix(1:0.5:nrows) nrows], :);%%% OP = imresize(NP, 2) if using Image

    nrows = 2*nrows;ncols = 2*ncols;                 % Processing Toolbox in MATLAB

    end

    Retinex = NP;function CompareWithNeighbor(dif_row, dif_col)

    global OPE RRE Maximum

    % Ratio-Product operation

    IP = OPE(2+dif_row:(end-1+dif_row), 2+dif_col:(end-1+dif_col)) + ...

    RRE(2:(end-1),2:(end-1)) - RRE(2+dif_row:(end-1+dif_row), 2+dif_col:(end-1+dif_col));IP(IP > Maximum) = Maximum;% The Reset step

    % ignore the results obtainedin the rows orcolumns for which the neighbors are undefined

    if (dif_col == -1) IP(:,1) = OPE(2:(end-1),2);end

    if (dif_col == +1) IP(:,end) = OPE(2:(end-1),end-1);end

    if (dif_row == -1) IP(1,:) = OPE(2, 2:(end-1));end

    if (dif_row == +1) IP(end,:) = OPE(end-1, 2:(end-1));end

    NP = (OPE(2:(end-1),2:(end-1)) + IP)/2;% The Averaging operation

    OPE(2:(end-1), 2:(end-1)) = NP;function Layers = ComputeLayers(nrows, ncols)

    power =2^fix(log2(gcd(nrows, ncols)));% start from the Greatest Common Divisor

    while(power > 1 & ((rem(nrows, power) ~= 0) | (rem(ncols, power) ~= 0)))

    power = power/2;% and find the greatest common divisor

    end                                                  % that is a power of 2Layers = log2(power);function Result = ImageDownResolution(A, blocksize)

    [rows, cols] = size(A);% the input matrix A is viewed as

    result_rows = rows/blocksize;% a series of square blocks

    result_cols = cols/blocksize;% of size = blocksize

    Result = zeros([result_rows result_cols]);for crt_row = 1:result_rows                          % then each pixel is computed as

    for crt_col =1:result_cols                       % the average of each such block

    Result(crt_row, crt_col) = mean2(A(1+(crt_row-1)*blocksize:crt_row*blocksize, ...1+(crt_col-1)*blocksize:crt_col*blocksize));end

    en

    总结      在上述两个经典的估计算法之后经过反对数变换就可以恢复成原格式的图像。通过试验可以发现,这些算法都还是有一定缺陷的,对于照度的估计后续还有很多算法如:单尺度Retinex (SSR)、多尺度Retinex (MSR)、可变框架的Retinex等等;还有针对增强后的光晕现象先用进行照度分割,然后在再计算等等方法,本质上都大同小异。这些改进算法这里不再进行介绍,有兴趣的朋友可以去下载些论文看看。有不明白的或者本文有错误的地方也希望各位能够指出,以免误导后面的读者。

    展开全文
  • 使用python编写了共六种图像增强算法:1)基于直方图均衡化2)基于拉普拉斯算子3)基于对数变换4)基于伽马变换5)限制对比度自适应直方图均衡化:CLAHE6)retinex-SSR7)retinex-MSR其中,6和7属于同一种下的变化。...

    使用python编写了共六种图像增强算法:

    1)基于直方图均衡化

    2)基于拉普拉斯算子

    3)基于对数变换

    4)基于伽马变换

    5)限制对比度自适应直方图均衡化:CLAHE

    6)retinex-SSR

    7)retinex-MSR其中,6和7属于同一种下的变化。

    将每种方法编写成一个函数,封装,可以直接在主函数中调用。

    采用同一幅图进行效果对比。

    图像增强的效果为:

    直方图均衡化:对比度较低的图像适合使用直方图均衡化方法来增强图像细节

    拉普拉斯算子可以增强局部的图像对比度

    log对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好

    伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的图像增强效果明显

    CLAHE和retinex的效果均较好

    python代码为:

    # 图像增强算法,图像锐化算法

    # 1)基于直方图均衡化 2)基于拉普拉斯算子 3)基于对数变换 4)基于伽马变换 5)CLAHE 6)retinex-SSR 7)retinex-MSR

    # 其中,基于拉普拉斯算子的图像增强为利用空域卷积运算实现滤波

    # 基于同一图像对比增强效果

    # 直方图均衡化:对比度较低的图像适合使用直方图均衡化方法来增强图像细节

    # 拉普拉斯算子可以增强局部的图像对比度

    # log对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好

    # 伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的图像增强效果明显

    import cv2

    import numpy as np

    import matplotlib.pyplot as plt

    # 直方图均衡增强

    def hist(image):

    r, g, b = cv2.split(image)

    r1 = cv2.equalizeHist(r)

    g1 = cv2.equalizeHist(g)

    b1 = cv2.equalizeHist(b)

    image_equal_clo = cv2.merge([r1, g1, b1])

    return image_equal_clo

    # 拉普拉斯算子

    def laplacian(image):

    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])

    image_lap = cv2.filter2D(image, cv2.CV_8UC3, kernel)

    return image_lap

    # 对数变换

    def log(image):

    image_log = np.uint8(np.log(np.array(image) + 1))

    cv2.normalize(image_log, image_log, 0, 255, cv2.NORM_MINMAX)

    # 转换成8bit图像显示

    cv2.convertScaleAbs(image_log, image_log)

    return image_log

    # 伽马变换

    def gamma(image):

    fgamma = 2

    image_gamma = np.uint8(np.power((np.array(image) / 255.0), fgamma) * 255.0)

    cv2.normalize(image_gamma, image_gamma, 0, 255, cv2.NORM_MINMAX)

    cv2.convertScaleAbs(image_gamma, image_gamma)

    return image_gamma

    # 限制对比度自适应直方图均衡化CLAHE

    def clahe(image):

    b, g, r = cv2.split(image)

    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))

    b = clahe.apply(b)

    g = clahe.apply(g)

    r = clahe.apply(r)

    image_clahe = cv2.merge([b, g, r])

    return image_clahe

    def replaceZeroes(data):

    min_nonzero = min(data[np.nonzero(data)])

    data[data == 0] = min_nonzero

    return data

    # retinex SSR

    def SSR(src_img, size):

    L_blur = cv2.GaussianBlur(src_img, (size, size), 0)

    img = replaceZeroes(src_img)

    L_blur = replaceZeroes(L_blur)

    dst_Img = cv2.log(img/255.0)

    dst_Lblur = cv2.log(L_blur/255.0)

    dst_IxL = cv2.multiply(dst_Img, dst_Lblur)

    log_R = cv2.subtract(dst_Img, dst_IxL)

    dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX)

    log_uint8 = cv2.convertScaleAbs(dst_R)

    return log_uint8

    def SSR_image(image):

    size = 3

    b_gray, g_gray, r_gray = cv2.split(image)

    b_gray = SSR(b_gray, size)

    g_gray = SSR(g_gray, size)

    r_gray = SSR(r_gray, size)

    result = cv2.merge([b_gray, g_gray, r_gray])

    return result

    # retinex MMR

    def MSR(img, scales):

    weight = 1 / 3.0

    scales_size = len(scales)

    h, w = img.shape[:2]

    log_R = np.zeros((h, w), dtype=np.float32)

    for i in range(scales_size):

    img = replaceZeroes(img)

    L_blur = cv2.GaussianBlur(img, (scales[i], scales[i]), 0)

    L_blur = replaceZeroes(L_blur)

    dst_Img = cv2.log(img/255.0)

    dst_Lblur = cv2.log(L_blur/255.0)

    dst_Ixl = cv2.multiply(dst_Img, dst_Lblur)

    log_R += weight * cv2.subtract(dst_Img, dst_Ixl)

    dst_R = cv2.normalize(log_R,None, 0, 255, cv2.NORM_MINMAX)

    log_uint8 = cv2.convertScaleAbs(dst_R)

    return log_uint8

    def MSR_image(image):

    scales = [15, 101, 301] # [3,5,9]

    b_gray, g_gray, r_gray = cv2.split(image)

    b_gray = MSR(b_gray, scales)

    g_gray = MSR(g_gray, scales)

    r_gray = MSR(r_gray, scales)

    result = cv2.merge([b_gray, g_gray, r_gray])

    return result

    if __name__ == "__main__":

    image = cv2.imread("example.jpg")

    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    plt.subplot(4, 2, 1)

    plt.imshow(image)

    plt.axis('off')

    plt.title('Offical')

    # 直方图均衡增强

    image_equal_clo = hist(image)

    plt.subplot(4, 2, 2)

    plt.imshow(image_equal_clo)

    plt.axis('off')

    plt.title('equal_enhance')

    # 拉普拉斯算法增强

    image_lap = laplacian(image)

    plt.subplot(4, 2, 3)

    plt.imshow(image_lap)

    plt.axis('off')

    plt.title('laplacian_enhance')

    # LoG对象算法增强

    image_log = log(image)

    plt.subplot(4, 2, 4)

    plt.imshow(image_log)

    plt.axis('off')

    plt.title('log_enhance')

    # 伽马变换

    image_gamma = gamma(image)

    plt.subplot(4, 2, 5)

    plt.imshow(image_gamma)

    plt.axis('off')

    plt.title('gamma_enhance')

    # CLAHE

    image_clahe = clahe(image)

    plt.subplot(4, 2, 6)

    plt.imshow(image_clahe)

    plt.axis('off')

    plt.title('CLAHE')

    # retinex_ssr

    image_ssr = SSR_image(image)

    plt.subplot(4, 2, 7)

    plt.imshow(image_ssr)

    plt.axis('off')

    plt.title('SSR')

    # retinex_msr

    image_msr = MSR_image(image)

    plt.subplot(4, 2, 8)

    plt.imshow(image_msr)

    plt.axis('off')

    plt.title('MSR')

    plt.show()

    增强效果如下图所示:

    f8170ba0e09ab740e2f043cdeff28c1b.png

    到此这篇关于python 图像增强算法实现详解的文章就介绍到这了,更多相关python 图像增强算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    展开全文
  • 图像增强算法.pdf

    2020-11-19 21:32:12
    图像增强算法 摘要本文简要介绍图像增强的概念和图像增强算法的分类说明了图像增强技术的应用和 前景展望并简要的介绍了灰度变换和直方图均衡化处理方法结合实际重点对维纳滤波 的代码和去噪效果进行了研究 关键词...
  • 图像增强算法实现

    2016-04-22 19:18:15
    图像增强算法实现
  • CLAHE图像增强算法.docx

    2021-04-11 13:19:12
    CLAHE图像增强算法.docx
  • 图像增强算法.docx

    2019-08-26 14:46:27
    基于去雾理论的低照度视频增强算法论文转换为opencv-c++图像增强算法原理。
  • 基于图像融合策略的Retinex背光图像增强算法
  • 图像去雾(二)Retinex图像增强算法

    万次阅读 多人点赞 2019-07-23 14:47:16
    前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强、图像去雾、彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解。 Retinex理论 Retinex理论始于Land和McCann于20世纪60年代作出的...

    前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强、图像去雾、彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解。

    Retinex理论

        Retinex理论始于Land和McCann于20世纪60年代作出的一系列贡献,其基本思想是人感知到某点的颜色和亮度并不仅仅取决于该点进入人眼的绝对光线,还和其周围的颜色和亮度有关。Retinex这个词是由视网膜(Retina)和大脑皮层(Cortex)两个词组合构成的.Land之所以设计这个词,是为了表明他不清楚视觉系统的特性究竟取决于此两个生理结构中的哪一个,抑或是与两者都有关系。

         Land的Retinex模型是建立在以下的基础之上的:

         一、真实世界是无颜色的,我们所感知的颜色是光与物质的相互作用的结果。我们见到的水是无色的,但是水膜—肥皂膜却是显现五彩缤纷,那是薄膜表面光干涉的结果;

         二、每一颜色区域由给定波长的红、绿、蓝三原色构成的;

         三、三原色决定了每个单位区域的颜色。Retinex 理论的基本内容是物体的颜色是由物体对长波(红)、中波(绿)和短波(蓝)光线的反射能力决定的,而不是由反射光强度的绝对值决定的;物体的色彩不受光照非均性的影响,具有一致性,即Retinex理论是以色感一致性(颜色恒常性)为基础的。如下图所示,观察者所看到的物体的图像S是由物体表面对入射光L反射得到的,反射率R由物体本身决定,不受入射光L变化。

                                                              

    Retinex理论的基本假设是原始图像S是光照图像L和反射率图像R的乘积,即可表示为下式的形式:

                                                                    

    基于Retinex的图像增强的目的就是从原始图像S中估计出光照L,从而分解出R,消除光照不均的影响,以改善图像的视觉效果,正如人类视觉系统那样。在处理中,通常将图像转至对数域,即

                                                                    

    从而将乘积关系转换为和的关系:

                                                                         

    Retinex方法的核心就是估测照度L,从图像S中估测L分量,并去除L分量,得到原始反射分量R,即:

                                                                              

    函数 f(x) 实现对照度L的估计(可以去这么理解,实际很多都是直接估计r分量)。

    Retinex理论的理解

    如果大家看论文,那么在接下去的篇幅当中,肯定会介绍两个经典的Retinex算法:基于路径的Retinex以及基于中心/环绕Retinex。在介绍两个经典的Retinex算法之前,我先来讲一点个人的理解,以便第一次接触该理论的朋友能够更快速地理解。当然,如果我的理解有问题,也请大家帮忙指出。

    Retinex理论就我理解,与降噪类似,该理论的关键就是合理地假设了图像的构成。如果将观察者看到的图像看成是一幅带有乘性噪声的图像,那么入射光的分量就是一种乘性的,相对均匀,且变换缓慢的噪声。Retinex算法所做的就是合理地估计图像中各个位置的噪声,并除去它。

    在极端情况下,我们大可以认为整幅图像中的分量都是均匀的,那么最简单的估计照度L的方式就是在将图像变换到对数域后对整幅图像求均值。因此,我设计了以下算法来验证自己的猜想,流程如下:

    (1) 将图像变换到对数域

                                                                                   

    (2) 归一化去除加性分量

                                                                                 

    (3) 对步骤3得到的结果求指数,反变换到实数域

                                                                               

    这里为了简化描述,省略了对图像本身格式的变换,算法用Matlab实现:

    Matable 代码
    
    
    % ImOriginal:原始图像
    % type:'add'表示分量是加性的,如雾天图像;'mult'表示分量是乘性的,如对照度的估计
    [m,n,z] = size(ImOriginal);
    ImOut = uint8(zeros(m,n,z));
    for i = 1:z
        if strcmp(type,'add')
            ImChannel = double(ImOriginal(:,:,i))+eps;
        elseif strcmp(type,'mult')
            ImChannel = log(double(ImOriginal(:,:,i))+eps);
        else
            error('type must be ''add'' or ''mult''');
        end
        ImOut(:,:,i) = EnhanceOneChannel(ImChannel);
    end
    ImOut = max(min(ImOut,255), 0);
    end
    
    function ImOut = EnhanceOneChannel(ImChannel)
    % 计算计算单个通道的反射分量
    % 1.对全图进行照射分量估计
    % 2.减去照射分量
    % 3.灰度拉伸
    ImChannel = ImChannel./max(ImChannel(:));
    ImRetinex = round(exp(ImChannel.*5.54));
    ImOut = uint8(ImRetinex);
    end

                                                                   

                                                                                   测试原图

                                                                   

                                                                              经典Retinex算法结果

                                                                   

                                                                               上述方法结果

    从对比中可以看到,对于去除照度,还原图像本身来讲,效果还可以,并且不会在边缘位置产生光晕现象。缺点就是在去除照度分量L过程中,保留的反射分量R我在上述算法中使用归一化后直接进行反变换。这一步的作用可以近似看成去除一个均匀的直流分量,即均匀的照度分量。由于操作都是全局的,这里默认假设了所有位置的照射分量都是相同的,因此在灰度拉伸的时候没有照顾到局部的特性,图像整体亮度偏暗。当然,全局的照度估计对于图像的增强肯定有相当的局限性,其增强效果在色彩的还原和亮度处理等方面还是有一定缺陷的。

    个人认为,Retinex算法的关键还是正确的分析了噪声的性质。相信很多人都看到利用基于Retinex的图像水下增强、基于Retinex的图像去雾等等,我也好奇,那就试试吧。大雾图片嘛谁没有,前一阵子大雾天,没事拍了几张照片,终于用上了,请看对比图:

                                                                 

                                                                                     有雾原图

                                                                 

                                                                            经典Retinex去雾效果

                                                                  

                                                                             上述方法去雾效果

    还是老规矩,这时候对比试验还是最能说明效果的,为此选了一幅干扰很大的图像。基本上各位要是显示器比较差一点,从原图当中是很难看出大雾后面的东西。从去雾效果来看,上述方法的效果并不比经典算法要差,至少在去雾的效果上,本实验结果从主观上给人的感觉还是不错的。

    在上述案例中,最重要的就是正确分析有雾图像的结构,与Retinex理论一开始的核心思想有区别的是,在针对这种加性的干扰时,经典的Retinex算法在处理过程中,其实仅仅是利用其估计加性的干扰分量;当然,抛开Retinex理论对照度、反射率对最终图像形成的核心思想(如图1),后续最重要的就是对这个加性的干扰的估计了。

    对于有雾的图像,我们大可以看作透过一块磨砂玻璃去看一幅清晰的图像,这样大家就能很好理解为什么认为在这个案例中,将雾的干扰认为是一个加性的了。诸如后面两个经典的算法,所有的这类算法归根结底就是更好地利用原图像中的像素点去估计原始照度。从上面例程上可以看出,使用一个全局估计对局部的增强是比较差的,如果存在照度不均匀(雾的浓度不均匀),或者背景颜色亮度很高等情况时,处理结果会趋向恶劣,效果比较差。

    当然,经典也不是完美,从图中可以看到,经典的算法容易出现光晕效果(蓝色书本文字周围一圈白色)。

     

     

    展开全文
  • 基于MSR的水下图像增强算法研究Computer Science and Application 计算机科学与应用, 2018, 8(1), 9-15Published Online January 2018 in Hans. /journal/csa/10.12677/csa.2018.81002Underwater Image Enhancement ...
  • 作者:李昌利,孙亚伟,闫敬文,樊棠怀摘要:针对水下环境存在的颜色衰减和散射效应导致水下图像颜色严重失真的问题,提出一种多通道均衡化的水下图像增强算法.首先,对原始图像在对数域上进行归一化处理后转换到...
  • 针对煤矿井下视频监控系统采集图像对比度低、光照不均、伴有大量噪声等问题,提出...通过主观视觉效果和客观质量评价对该算法进行验证,结果表明该算法较传统图像增强算法可获得更好的图像视觉效果,且图像处理速度更快。
  • 基于能量调整的射线图像增强算法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,259
精华内容 1,703
关键字:

图像增强算法