轮换一个输入图像中每一个像素值,那几个连串不能选取灰度图像(典型的是8位每像素)

      相关小说可知:带色彩复苏的多尺度视网膜增强算法(MSRCR)的规律、落成及利用。

      参考文档: Adaptive Thresholding for the
DigitalDesk.pdf

直方图引入

直方图是一个简便的表,它交给了一幅图像或一组图像中拥有给定数值的像素数量。因此,灰度图像的直方图有256个条款(或称为容器)。0号容器给出值为0的像素数量,1号容器给出值为1的像素个数,以此类推。

   
 从历史的逐一上讲,本篇应该放在MSRCR往日的,只是由于现行基本上论文都是描述的MSRCR,因而我也是先读书MSRCR的。

            Adaptive Thresholding Using the Integral
Image.pdf 

直方图反投影

直方图是图像内容的一个关键特征。假诺一幅图像的区域中显得的是一种特殊的纹路或是一个独特的实体,那么那个区域的直方图可以用作一个概率函数,它交给的是某个像素属于该纹理或物体的票房价值。那使得大家可以依靠图像的直方图来检测特定的内容。
反投影直方图的艺术是一种把对象概率分布映射到考察图像的简约方法。其意义是,替换一个输入图像中每一个像素值,使其成为感兴趣区域(ROI)的直方图中对应的概率值
其在opencv2的C++ API为:

cv::calcBackProject(&image,         
    1,              //一幅图像
    channels,       //通道数量
    histogram,      //进行反投影的直方图
    result,         //生成的反投影图像
    ranges,         //每个维度的值域
    255.0           //缩放因子
    );

   
 昨天,无意中找寻一些Retinex资料,搜索到一篇文章《Retinex in
matlab》,原以为是MSRCR之类的matlab完结,结果仔细一看,和MSRCR算法的叙说完全不一样。于是找了有的素材,对Retinex的野史有了越发明白,以下复制一些随笔中的文档以供表达:

710官方网站,一、问题的原委

HSV颜色空间

HSV(Hue,Saturation,Value)是基于颜色的直观特性(色调H,饱和度S,亮度V)成立的一种颜色空间,
也称六角锥体模型(Hexcone Model)。

   
 ******************************************************************************************************************************************************************************

      一个切实:
当用照像机拍摄一副黑纸白字的纸张时,照相机获得的图像并不是真正的是非曲直图像。不管从哪些角度拍照,那幅图像实际上是灰度或者彩色的。除非仔细的安装灯光,否则照相机所拍摄的放在桌子上的纸张图像并不可以表示原始效果。不像在扫描仪或打印机内部,想操纵好桌子表面的光源是不行坚苦的。那么些盛开的半空中可能会遭到台灯、吊灯、窗户、移动的影子等影响。人类的视觉系统能自行补偿那一个,可是机器没有设想到那几个元素由此拍出的功能会很差。

色调H

用角度度量,取值范围为0°~360°,从革命开头按逆时针方向统计,蓝色为0°,红色为120°,黑色为240°。它们的补色是:粉红色为60°,红色为180°,品红为300°;

   
小说地址:http://www.doc88.com/p-993974139685.html

   
 这些问题在处理那种高相比度的章程线条或文字时进一步非凡,因为那么些东西都是确实的青色或白色。而拍摄头会爆发一副具有分歧阶段的灰度图像。许多行使都不可以不精通的通晓图像的那部分是纯黑或纯白,以便将文字传递给OCR软件去分辨。那一个系统不可以使用灰度图像(典型的是8位每像素),由此必须将她们转移为黑白图像。那有很多种主意去已毕。在某些情状下,如若这个图像最后是给人看的,这个图像会使用一些颠簸技术,以便使他们看起来更像灰度图像。可是对于机械处理的经过,比如文字识别,选用复制操作,或八个图像合成,系统就不得以行使振动的图像。系统仅仅须要不难的线条、文字或相对大块的肉色和白色。从灰度图像获得那种黑白图像的经过一般称作为阈值化。

饱和度S

取值范围为0.0~1.0,值越大,颜色越饱和。

   
近年来,在当代生农学和心绪学的开导下,美利哥地法学家Land等人布署出了Retinex(视网膜皮层)模型,并在适合人眼的颜色恒常性理论前提下,提议了基于Retinex的图像增强算法。那种算法建立的功底是只要人眼感知目的的亮度和颜料由环境光照和对象表面的反射光照决定,保持目的的水彩恒常性主要就是揣测环境光照,并删除环境光照的影象。那样就取得了可靠的目的颜色和亮度新闻。由于Retinex算法具有高动态范围减小、高色彩保真度和良好的有些细节增强等特点,引起了大气的国外学者的趣味。为规范揣摸亮度分量,采纳统计路径常见有一维和二维的差别。早期,Land提出选拔随机路径,并对路线所通过的像素进行添加计算亮度,那种办法的弱项在于当前像素点的亮度和无限制路径上的像素亮度有关和其世界周围的像素亮度大约毫无干系,使得增强后的图像出现亮度不总是的现象。随后现身了二种迭代分段线性路径,即McCann99
Retinex 和弗兰克(Frank)le-McCann
Retinex,比较随机路径的Retinex而言,他们的增强成效较好。然则,他们的一起缺陷在于总括复杂度相比高,且迭代次数的取舍对增加功能的影响主要。二零零四年,Ciurea和Funt公布了机关接纳迭代次数的舆论后,这一难题才足以缓解。
Land分析了一维路径拔取的弱点,提议了二维路径的挑选方式,即着力/环绕Retinex算法。那种方法下,当前像素点周围领域内像素亮度值作为统计根据,且乔布斯(Jobs)(Jobs)on等人谨慎的求证了高斯卷积函数满意基本/环绕函数须要…………………………………….(以下就是SSR\MSR\MSRCR…等等)。

   
 有很多种方式来阈值化一副图像,可是基本的处理进度都是检查每一个灰度像素,然后决定她是反革命和如故青色。本文描述了已经开发的两样的算法来阈值一副图像,然后提议了一种相比适当的算法。这几个算法(那里大家誉为神速自适应阈值法)可能不是最合适的。可是她对大家所描述的题目处理的一定好。

亮度V

取值范围为0.0(褐色)~1.0(白色)。
HSV模型的三维表示从RGB立方体衍生和变化而来。设想从RGB沿立方体对角线的白色顶点向绿色顶点观看,就可以见到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

710官方网站 1

HSV颜色空间

hue表示颜色的相位角,取值范围是0—360;S表示颜色的饱和度;S为一比例值,范围从0到1,它象征成所选颜色的纯度和该颜色最大的纯度之间的比率,通俗点讲,S表示的是某种颜色的“纯度”,
S取值越大,表示色彩越纯,取值越小,表示色彩越灰。V表示色彩的领会程度,范围从0到1。V等于0表示圆锥的最底层定点,也就是青色,V等于1意味着圆锥的顶面,当V=1并且S=0时表示纯白色。

710官方网站 2

HSV圆锥

   
 ******************************************************************************************************************************************************************************

二、全局阈值法

运用示范:建立颜色概率模型

是因为我们要开展的是通过一种算法来落到实处检测特定物体(越发是面部)的功效,所以通过那些示例的引入,来为前边介绍Mean
Shift算法打下基础。
因为肤色在颜色空间的分析出色集中,但会境遇光照和种族的熏陶。为了减弱肤色收光照强度的熏陶,常常将颜色空间从RBG转换来亮度和色度分离的某部颜色空间,如HSV颜色空间,然后放弃亮度分量。
征集肤色样本,吧肤色样本中的每个像素从RGB空间转换来HSV空间,总计其H分量的直方图,并对该直方图进行归一化处理,就可以博得肤色在H空间的概率分布,该概率分布就是所需的跟踪方式。

具体步骤如下:
1、将观测图像中各类像素从RGB空间映射到HSV空间,按公式统计H分量大小建立起总结直方图
2、根据直方图进行反向投影运算,即,将观察图像中的每个像素值,用其H分量在已确立的计算直方图中对应的值代替
3、所获得输出图像就是考察图像的颜料概率分布图像

现在,用程序演示直方图反投影算法中动用颜色新闻。

class ContentFinder
{
private:
    float hranges[2];
    const float* ranges[3];
    int channels[3];
    float threshold;
    cv::MatND histogram;

public:
    ContentFinder():threshold(-1.0f){
        ranges[0] = hranges;//所有通道的值相同
        ranges[1] = hranges;
        ranges[2] = hranges;
    }

    //设置直方图的阈值[0,1]
    void setThreshold(float t)
    {
        threshold = t;
    }

    //获取阈值
    float getThreshold()
    {
        return threshold;
    }

    //设置参考直方图
    void setHistogram(const cv::MatND& h)
    {
        histogram = h;
        cv::normalize(histogram,histogram,1.0);//输入直方图必须是归一化后的
    }

    cv::Mat find(const cv::Mat& image,
                float minValue,float maxValue,
                int* channels,int dim);

};

cv::Mat ContentFinder::find(const cv::Mat& image,
                            float minValue,float maxValue,
                            int* channels,int dim)
{
    cv::Mat result;
    hranges[0] = minValue;
    hranges[1] = maxValue;

    for(int i=0;i<dim;i++)
    {
        this->channels[i] = channels[i];
    }
    cv::calcBackProject(&image,1,   //输入图片
                        channels,   //所有通道列表
                        histogram,  //直方图
                        result,     //反投影的结果
                        ranges,     //值域
                        255.0       //缩放因子
                        );
    //进行阈值化以得到二值图像
    if(threshold > 0.0)
        cv::threshold(result,result,255*threshold,255,cv::THRESH_BINARY);
    return result;
}

   
由上述描述可知,弗兰克le-McCann Retinex选用了一维路径寻找办法算计亮度,而MSRCR是二维的,后者则进一步复杂。

      
在某种程度上说,阈值法是比较度增强的最好形式,或者说他使得亮的像素更亮而暗的像素更暗。最简便的(也是最常用的)方法就是将图像中稍差于某个阈值的像素设置为青色,而任何的设置为白色。那么随着问题就是怎么着设置这么些阈值。一种可能性就是采用具有可能取值的中游值,因而对此8位深的图像(范围从0到255),128将会被选中。这么些措施在图像红色像素确实在128以下,而白色也在128之上时工作的很好。不过只要图像过或欠暴露,图像可能全白或全黑。所以找到图像实际的取值范围代替可能取值范围会更好些。首先找到图像中具有像素的最大值和纤维值,然后取中点作为阈值。一个更好的抉择阈值的办法是不仅翻开图像实际的限量,还要看其分布。比如说,你愿意图像类似于一副灰色线条画,或者在白纸上的文字效果,那么您就巴望一大半像素是背景颜色,而少部分是黄色。一副像素的直方图可能如图1所示。

均值漂移(Mean Shift)算法

假若大家现在了解物体的切近地方,概率映射可用以找到的靶子的熨帖地点。最有可能的岗位是在已知窗口区域中获得最几乎率的任务。因而,固然大家从初期的职位上马,并且迭代移动,边可以找到确切的岗位。那便是均值漂移算法所要落成的天职。

   
关于FMR算法的原理呢,我瞬间也讲不清,那里稍微对算法的部分进程举办不难的牵线吧。

 

原理

均值漂移算法以迭代的法子锁定概率函数的一部分最大值。它最重假设寻觅预约义窗口中数据点的重心点,或者说加权平均值。该算法将窗口中央移动到数据点的大旨处,并再一次那一个进度直到窗口重心收敛到一个安居点。
从数学角度上说,Mean
Shift算法行使概率密度的梯度爬升来寻觅局地最优。当输入一个图像的限制,然后按照反向投影图和输入的方框举行Mean
Shift迭代,它是向主导移动,即向反向投影图中概率大的地方移动,所以平素会活动到目的上,Mean
Shift算法是一个变步长的梯度上涨算法
现考虑一个点集(那足以是因而直方图反投影的像素点的分布),现有一个小窗口,须要将其移至像素点最密集的区域。如下图所示:

710官方网站 3

meanshift_basics

初期的窗口表示为C1以此大的灰色圆圈,其原有宗旨为”C1_o”。随着那个主题点向一些密度较大的区域活动,获得了”C1_r”的主旨点。随着那么些进程的迭代,最后会获得一个最大像素点分布的区域,即C2,该区域蕴含了最多数据的点。

小结下来,Mean
Shift的基本思路
是,从种种像素伊始,首先臆想有相似颜色的濒临像素点的密度(局地密度)的梯度,而后利用迭代算法求出部分密度的峰值(即重心点),把可以聚类到同一个峰值点的有着像素点划分成一个区域。

   
首先,算法的输入需如果[0,1]范围的浮点数,并且是按对数分布的,那几个普通必要将[0,255]按对数格局量化到[0,1]范围内。

                                 
 710官方网站 4   

大旨流程

(1)选拔跟踪窗口的轻重和初阶地方。在Mean
Shift跟踪算法中,核窗宽(即核函数的定义域的大小,就是摸索窗口的轻重缓急)的轻重缓急起着极度关键的功力。因为它不只决定了加入Mean
Shift迭代的范本数量,而且也体现了跟踪窗口的尺寸。寻常,核窗宽由起头跟踪窗口的尺码决定,而且在任何跟踪进度中不再暴发变化。

710官方网站 5

meanshift_step1

(2)总结跟踪窗口内的质心(或重点)。在离散二维(2D)概率分布图像中,总计某窗口的质心同物理上测算某物体的质心一样,即利用窗口的零阶矩M00和(x,y)的一阶矩(M10,M01)之间的关联,总结得到窗口的质心。

710官方网站 6

公式

710官方网站 7

meanshift_step2

(3)调整跟踪窗口的主题到质心;

(4)重复第二步和第三步,直到跟踪窗口中央和质心“汇聚”,即每一趟窗口移动的离开小于一定的阈值。

710官方网站 8

meanshift_step3

一般一个图像就是个矩阵,像素点均匀的分布在图像上,就从不点的稠密性。所以怎么来定义点的概率密度,那才是最根本的。而大家可以根据像素点的水彩相近年来定义为概率密度高。
其作为人脸跟踪的利用由下图演示:

710官方网站 9

meanshift_face

   
然后根据下图所示的路子对各种点的数额开展对照、想乘、复位和平均操作。

                                图1 

优点

Mean
Shift作为一种高效的方式匹配算法,由于不须求举办全局搜索,而且搜索精度高,已经普随地动用在种种形式识别、实时可视跟踪等世界。

                 
 710官方网站 10

     
 上图中,可以窥见一个背景颜色的大峰值,以及一个粉色墨水的小的峰值。根据周围的光辉整个曲线可想向左或者向右偏移,不过在其余意况下,最了不起的阈值就是在四个峰值之间的波谷处。那在争鸣上很好,然而他在实质上中到底表现如何呢。

不足

缺失必要的模型更新方法;整个跟踪进度中跟踪窗口的尺寸保持不变,当对象存在尺度变化的时候会促成尺度定位不标准。

     
那几个我实际是说不清楚了,给多少个链接我们温馨看看啊:

        710官方网站 11

总是自适应的Meanshift(CamShift)算法

布拉德(Brad)ski按照Mean
Shift算法的不足,提议了Camshift算法。CamShift算法,即Continuously
Adaptive
Mean-Shift算法,基本思维就是对录像图像的多帧进行MeanShift运算,将上一帧结果作为下一帧的发轫值,迭代下去。
该算法接纳不变矩对目标的尺码进行估价,落成了连续自适应地调整跟踪窗口的轻重缓急和岗位,并将其使用在对连日彩色图像连串中的运动目的的长足跟踪。
简单易行点说,Mean
Shift是本着单张图片检索最优迭代结果,而Camshift则是针对性录像连串来处理,并对该体系中的每一帧图片都调用Mean
Shift来寻找最优迭代结果。正是出于Camshift针对一个视频种类举行处理,从而保障其可以穿梭调整窗口的轻重,如此一来,当目标的轻重爆发变化的时候,该算法就可以自适应地调整目标区域三番五次跟踪。

      按照心绪物历史学评价和宠爱映射的高动态范围图像的色泽映射算子的筹划

                                   图 2 

原理

Camshift算法首先按照跟踪目的颜色概率模型,将录像图像转化为概率分布图像(PDI),并初叶化一个矩形搜索窗口,对每一帧PDI图像利用Mean
Shift算法搜索目的匹配的最优区域,并基于查找区域的不变矩估计跟踪目的的主题和尺寸,保存和出口当前帧搜索结果,并且用当下帧搜索结果作为下一帧图像伊始化搜索窗口。如此循环往复,即可兑现对目标的接连跟踪。Camshift算法是一种动态变化的非参数密度函数梯度估计方法

        基于色彩恒常性的图像去雾技术

     
图2及其直方图呈现任何技术工作的很好。平滑后的直方图展现出2个地下的峰值,通过拟合直方图曲线或简捷的取多少个峰值之间的平均值来测算出一个接近理想阈值并不是一件困难的事务。这不是一个非凡的图像,因为她有雅量的褐色和白色的像素点。算法必须还要对近似图3那样的图像进行阈值处理。那那幅图像的直方图中,较小的黑色峰值一度埋藏在噪音中,由此要可依赖地在峰值之间确定哈一个最小值是不太可能的。

具体步骤

(1)创设指定窗口的颜料概率分布图,开首化一个摸索窗口W,其尺寸为S

710官方网站 12

camshift_1

由上图左图的直方图可以知晓,选定区域最普遍的色度范围。要是新的视频帧到来时,每个像素点的色度值被检测,通过直方图给出该像素点的票房价值值。
(2)利用Mean
Shift算法使搜索窗口“收敛”;在2D概率分布图像中,计算搜索窗口的质心;调整搜索窗口的基本到总括的质心地方。重复该进程,直到“收敛”(即着力的移动小于给定的阈值)
(3)重新安装搜索窗口的大小S并总结跟踪目的的出口参数,并用新的窗口大小起始化下一帧Mean
Shift的物色窗口

710官方网站 13

camshift_2

上图表示经过Camshift算法跟踪人脸时总计一个视频帧图像中或许存在人脸的图像。黄色像素概率值最低,白色像素概率值最高,粉色像素介于二者之间。
(4)跳转到第二步举办下一帧的轮回

下边是Camshift算法的人脸跟踪演示:

710官方网站 14

camshift_face

      Retinex in
Matlab

           710官方网站 15

参考资料

OpenCV 3.0.0-dev
documentation

OpenCV 2 总计机视觉编程手册,科学出版社
依照OpenCV的人脸跟踪识别系统研商,雷静,罗利(罗利)电影学院,大学生学位散文,2010
Meanshift,聚类算法

     
最终把拍卖的数额从对数域转换到[0,255]界定内(那里须要使用exp函数哦)。

                                                                       
  图   3

     
大家如故把日子放在算法效果的简易分析上。

     
 在其余动静下,一个大的(背景)峰值总是存在的还要也简单找到,由此,一个一蹴而就的阈值策略可讲述如下:

   
 710官方网站 16

  1)  总计直方图。

   
 一般景况下,可以认为FMR算法唯有迭代次数一个参数。由上图可知,迭代次数越小,图像的相比较度越小,连读越亮,动态压缩范围越小。迭代次数越大,图像的对峙统一度越强烈。从直方图上看,迭代次数时辰,直方图汇聚集在一道,随着迭代次数等充实,直方图逐渐分布到方方面面动态范围内。
当迭代次数尤其大时,图像会和原来图像很相近。

     2) 
依照一定的半径对直方图数据开展平整,并总结平滑后数据的最大值。平滑的目标裁减噪声对最大值的影响,如图2和图3所示。

     
我们在贴一些该算法处理的结果。

     3) 
依照上述峰值和最小值(不包蕴在直方图中为0的项)的离开依据一定的百分比选取阈值。

   
  710官方网站 17  710官方网站 18  710官方网站 19

     
试验声明那些距离的一半力所能及对很大范围内的图像爆发一定好的机能,从非常亮到大致完全黑的图像。比如,在图3中,峰值在215处,而最小值为75,由此可以利用的阈值为145。图4是四副在不一致的光照条件下抓取的图像以及按照上述基于直方图技术阈值处理后的效率。就算私服图像有那较广的娄底范围(可以从直方图中观察),该算法都拔取了较为合适的阈值,而阈值处理后的图像基本一致。

   
  710官方网站 20  710官方网站 21  710官方网站 22

                      710官方网站 23

   
  710官方网站 24  710官方网站 25  710官方网站 26

                          710官方网站 27

                     
 原图                                                迭代一次          
                                     迭代10次

                      710官方网站 28

   
 可知,对有的偏暗的图像的加强作用如故很醒目。

                      710官方网站 29

   
 经过测试注脚,这几个算法对于大家在健康光照下拍摄的相片的处理有出人意料的功能,可以暴发类似HDR的功能,贴出如下:

                                图      
  4

   
 710官方网站 30  710官方网站 31

     
 那些基于直方图的大局阈值技术对于如下面所举的那一个光线条件均匀或那多少个光线变化不多的局地图像处理的很好。可是对于在常规办公光照条件下他一筹莫展获取满意的结果。因为对总体图像使用一个如出一辙的阈值,图像的一些区域变得太白而其余地区又太黑。由此一大半文字变得不得读,如图5所示。

   
 710官方网站 32  710官方网站 33

             710官方网站 34

                     
         原图                                                          
                   处理后

                                  图  
      5

 
 此外,该算法对偏色图像也有一定的纠偏能力,比如下图。

     
 从光照不均匀的纸张图像中发出较好的二值化图像需要一种自适应的阈值算法。这些技术根据各类像素的背景亮度来改变阈值。上面的研商都配以图5先出示新算法的效应。那是一个装有挑衅性的测试,因为图像边缘有光源,并且其在白色背景上有肉色文字(PaperWorks整个词,以及灰色背景中的白色文字(“XEROX”),还有白色背景中的黄色文字(”The
best
way。。。”)还有两样的阴影和一个在单词“PaperWorks”下很细小的档次紫色线。

                     
   710官方网站 35                       
                         
 710官方网站 36

三 自适应阈值

 
 710官方网站 37 
 710官方网站 38

      
一个出色的自适应阈值算法应该力所能及对光照不均匀的图像发生类似上述全局阈值算法对光照均匀图像暴发的机能一样好。
为了填补或多或少的照明,每个像素的亮度须要正统,之后才能操纵某个像素时褐色如故白色。问题是怎么样控制每个点的背景亮度。一个概括的主意就是在拍摄需要二值图片此前先拍一张空白的页面。那些空白的页面可以视作参考图像。对于每一个要拍卖的像素,在拍卖前相应的参考图像像素都将从内部减去。

                     
           原图                                                        
                    处理后

      
只要在参考图像和实际要拍卖的图像拍摄时光照尺度尚未发出任何变化,那一个点子能生出分外好的职能,可是,光照条件会收到人、台灯或任何运动物体的影子的影响。假若房间有窗户,那么光照条件还会随着时光变化而改变。一个化解方案就是在平等的岗位,同样的每日拍摄一种空白的页面作为参照,不过那即便使用扫描仪一样不太方便

 
 贴出一段比较粗糙的兑现该函数的matlab代码:

      
其它一种方法就是通过有些关于图像实际该是什么样的假若来推断每个像素的背景亮度。例如,大家可以假若,图像半数以上是背景(也就是反革命),黑色只占图像的小一些。其它一个要是就是背景光改变相对较为迟缓。基于以上假诺有成百上千算法都有效。由于并未有关自适应阈值的数学理论,由此,也就不曾一个正经仍然最优的格局来兑现它。代替的是,有局地特其余方法要比其余一些越发使用的多。由于这么些艺术比较更加,由此测量他们的性能比较有用。为此,Haralick

Shapiro指出了以下提议:区域需和灰度调统一;区域内部应该不难,没有过多的小孔;相邻的区域应该有不问可知的例外值;每个部分的边缘也应该不难,不应凹凸不平,其空间上要精确。

 

      
按照Pratt的辩护,对于图像二值化,还尚未其余量化性能目的提议过。就像根本评价算法性能的法子就是粗略看看结果然后判断其是不是很好。对于文字图像,有一个实用的量化办法:差别光照条件下的图样采纳不一致的二值化算法处理的后的结果被送往OCR系统,然后将OCR识其余结果和原文字相比。即便该法可能有用,然而她不可以用在以下描述的算法中,因为无法付出一个看起来好的正儿八经。对于有些交互式的行使,比如复制黏贴操成效户必须等到二值的处理。因而别的一个首要的目的就是速度。以下一些指出了不一致的自适应阈值算法已经他们暴发的结果。

function Test()
    clear all
    rgb=imread('c:\222.jpg');%需要处理的图片
    m=size(rgb,1);
    n=size(rgb,2);
    rr=zeros(m,n);
    gg=zeros(m,n);
    bb=zeros(m,n);
    for i=1:m
        for j=1:n
            rr(i,j)=logm(double(rgb(i,j,1))+eps);
            gg(i,j)=logm(double(rgb(i,j,2))+eps);
            bb(i,j)=logm(double(rgb(i,j,3))+eps);
        end
    end
    rr=rr/max(max(rr(:)));
    gg=gg/max(max(gg(:)));
    bb=bb/max(max(bb(:)));
    rrr= retinex_frankle_mccann(rr, 4);
    ggg= retinex_frankle_mccann(gg, 4);
    bbb= retinex_frankle_mccann(bb, 4);
    for i=1:m
        for j=1:n
            rrr(i,j)=round(exp(rrr(i,j)*5.54));
            ggg(i,j)=round(exp(ggg(i,j)*5.54));
            bbb(i,j)=round(exp(bbb(i,j)*5.54));
        end
    end
    rgb=cat(3,uint8(rrr),uint8(ggg),uint8(bbb));
    rgb=max(min(rgb,255),0);
    imshow(rgb);
end

function [ Retinex ] = retinex_frankle_mccann( L, nIterations )
    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;
end

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
end

四、基于Wall算法的自适应阈值

   
同样,提供个编译好的文书给有趣味切磋该算法的情人看看效果:

       R. J.
Wall开发的依照背景亮度动态统计阈值的算法描述可知《Castleman, K. Digital
Image Processing. Prentice-哈尔(Hal)l Signal Pro-cessing Series, 1979.》
。以下描述基本是依照其杂谈的。首先,将图像分成较小的块,然后分别总计每块的直方图。依照每个直方图的峰值,然后为各种块总结其阈值。然后,每个像素点的阈值依照附近的块的阈值举办插值得到。图6是用该算法对图5举行拍卖的结果。

 
 http://files.cnblogs.com/Imageshop/Frankle_Mccann_Retinex.zip

                                                     
  710官方网站 39

 

                                       图    
6

 ***************************小编:
laviewpbt   时间: 2013.4.18    联系QQ:  33184777
 转发请保留本行新闻*************************

   
 这一个图像被分为9个块(3*3),每个块的阈值选用为比峰值低20%。那几个结果比全局阈值要好,可是她的统计量大,速度交慢。别的一个问题不怕,对于有些图像,局地的直方图可能会被大量的灰色或白色点欺骗,导致阈值在整幅图像中不是平整的变迁,结果可能那么些不佳,见图7.

 

            710官方网站 40

                                图    7 

五、火速自适应阈值

      
文献中记载的一大半算法都比Wall算法更为复杂,由此必要越来越多的运作时刻。开发一个简练的更快的自适应阈值算法是卓有成效的,因而那接大家介绍下相关的论战。

     
 算法基本的细想就是遍历图像,统计一个活动的平均值。要是某个像素显然的小于这几个平均值,则设置为灰色,否则设置为白色。仅需一个遍历就够了,用硬件去贯彻算法也很简答。注意到下边的算法和IBM
1968年用硬件已毕的算法的相似性是比较有趣的。

     
即使Pn为图像中位居点n处的像素。此刻大家只要图像是由拥有行按顺序连接起来的一个单行。那那致使了在每行伊始的时候会时有发生局部非常,但那个相当要比每行都从零初始要小。

        710官方网站 41

       假设fs(n)是点n处最终 s个像素的总数:

                710官方网站 42 

     
 最终的图像T(n)是1(红色)或0(白色)则借助于其是不是比其前s个像素的平均值的百分之t的暗。

        710官方网站 43

     
 对于s使用图像的1/8宽而t取值15似乎对分化的图像都能发出较好的效用。图8突显了选择该算法从左到右扫描行的结果。

         
 710官方网站 44710官方网站 45

            图  
8                            图   9  

     
 图9是运用同样算法从右到左处理的结果,注意在那一个图像中,最右侧的较小的文字是不完整的。在字符PaperWorks中也有更加多的窟窿眼儿。同样,最左边的青色边缘也窄很多。那第一是出于图像的背景光源是从左到右逐步变黑的。

     
 此外一个问题就是什么样开始算法,或者说怎么总计g(0)。一个可能是使用s*p0,可是出于边缘的结果,P0不是一个头名的值。因而另外一个立竿见影是127*s(基于8位图像的中值)。不论怎么着,那二种方案都只会影响到g的很少一部分值。在总结gs(n)时,g(0)的权重是:

             710官方网站 46

     
因而假诺s=10,那么对于其余的n>6,g(0)的孝敬则少于g10(n)的10%,对于n>22,g(0)的进献值则少于1%。对于s=100,在8个像素之后g(0)的共享就低于10%,在68像素后则少于1%.

     
 假如计算均值时不是从某一个倾向效果应该会更好,图12展现应用其它一种办法来计算平均值的成效。该措施通过计算点n对称两侧的像素的平均值来顶替某一个大方向的平均值。此时f(n)的定义如下:

         710官方网站 47

     
其余一种替代的法门就是轮番的从左到右及从右到左总计平均值,如下所示:

     710官方网站 48

    

       那暴发的机能和着力平均相比较,没有多大的区分。

       
一个微小修改或者会对一大半图像暴发更好的功用,那就是保存前一行的平分效果(和当下行反方向的),然后把近日行的平均值和上一上的平均值再取平均作为新的平均值,即接纳:

      710官方网站 49

       这使得阈值的一个钱打二十四个结考虑了僵直方向上的新闻,发生的结果如图:

                 710官方网站 50

     
 请注意她对字符的划分的功能。那也是为数不多的保存了PaperWorks下那条水平线的算法之一。

   部分原文因现行看来已经不创立了,未做翻译。

      从地点的事物来看,Wellner
自适应滤波阈值实际上就是对像素做指定半径的一维平滑,然后原像素和平滑后的值做相比较来控制黑依然白。小说中很大片段篇幅都是在谈论取样的那个像素的方向问题,是完全在右边、完全在左边依旧左右对称,抑或是考虑到前一行的功用。
可是,总的来看,他只考虑到了行方向上的像素对平滑的震慑。之后,Derek布拉·德利(Bra·dley)和Gerhard Roth 在她们的舆论Adaptive Thresholding Using the
Integral Image 中

提议了以W*W为模板的矩形区域的二维平滑值来代替一维加权值。从而抛开了一维平滑的方向性问题。

   
 当然,对于二维平滑他们提议了0(1)时间复杂度的算法,其实很不难,就是先总计整幅图像的累加表。然后再三回巡回通过加单的加减得到以某个像素为主干的累加值。

   
上面给出一个简答的从左到右的本来面目标Wellner算法的代码(我认为分外所有行并成一行并不会好,并且只要那样做还要考虑扫描行的无用数据):

        public static void WellneradaptiveThreshold1(FastBitmap bmp, int Radius = 5, int Threshold = 15)
        {
            if (bmp == null) throw new ArgumentNullException();
            if (bmp.Handle == IntPtr.Zero) throw new ArgumentNullException();
            if (bmp.IsGrayBitmap() == false) throw new ArgumentException("Binaryzation functions can only be applied to 8bpp graymode Image.");
            if (Radius < 0 || Radius > 255) throw new ArgumentOutOfRangeException();
            if (Threshold < 0 || Threshold > 100) throw new ArgumentOutOfRangeException();
            int Width, Height, Stride, X, Y;
            int Sum, InvertThreshold, XX, OldValue;
            byte* Pointer;
            Width = bmp.Width; Height = bmp.Height; Stride = bmp.Stride; Pointer = bmp.Pointer; InvertThreshold = 100 - Threshold;
            byte* Row = (byte*)Marshal.AllocHGlobal(Width);
            for (Y = 0; Y < Height; Y++)
            {
                Pointer = bmp.Pointer + Stride * Y;
                Sum = *Pointer * Radius;
                Win32Api.CopyMemory(Row, Pointer, Width);
                for (X = 0; X < Width; X++)
                {
                    XX = X - Radius;
                    if (XX < 0) XX = 0;
                    Sum += Row[X] - Row[XX];
                    if (Row[X] * 100 * Radius < Sum * InvertThreshold)
                        Pointer[X] = 0;
                    else
                        Pointer[X] = 255;
                }
            }
            Marshal.FreeHGlobal((IntPtr)Row);
        }

  

  那个是依据自身自己的一个法斯特Bitmap类的,要改成GDI+的 Bitmap
类也很简短,注意二值处理一般只针对灰度图像。

   
 操作中必须先对于行数据开展一个备份,因为在计算进度中会改变像素值的。

     同时也付出二维的Wellner算法的代码供大家参考:

       public static void WellneradaptiveThreshold2(FastBitmap bmp, int Radius = 5, int Threshold = 50)
        {
            if (bmp == null) throw new ArgumentNullException();
            if (bmp.Handle == IntPtr.Zero) throw new ArgumentNullException();
            if (bmp.IsGrayBitmap() == false) throw new ArgumentException("Binaryzation functions can only be applied to 8bpp graymode Image.");
            if (Radius < 0 || Radius > 255) throw new ArgumentOutOfRangeException();
            if (Threshold < 0 || Threshold > 100) throw new ArgumentOutOfRangeException();

            int Width, Height, Stride, X, Y;
            int Sum, X1, X2, Y1, Y2, Y2Y1, InvertThreshold;
            byte* Pointer;
            Width = bmp.Width; Height = bmp.Height; Stride = bmp.Stride; Pointer = bmp.Pointer; InvertThreshold = 100 - Threshold;
            int* Integral = (int*)Marshal.AllocHGlobal(Width * Height * 4);
            int* IndexOne, IndexTwo;
            for (Y = 0; Y < Height; Y++)
            {
                Sum = 0;
                Pointer = bmp.Pointer + Stride * Y;
                IndexOne = Integral + Width * Y;
                for (X = 0; X < Width; X++)
                {
                    Sum += *Pointer;
                    if (Y == 0)
                        *IndexOne = Sum;
                    else
                        *IndexOne = *(IndexOne - Width) + Sum;
                    IndexOne++;
                    Pointer++;
                }
            }

            for (Y = 0; Y < Height; Y++)
            {
                Pointer = bmp.Pointer + Stride * Y;
                Y1 = Y - Radius; Y2 = Y + Radius;
                if (Y1 < 0) Y1 = 0;
                if (Y2 >= Height) Y2 = Height - 1;
                IndexOne = Integral + Y1 * Width;
                IndexTwo = Integral + Y2 * Width;
                Y2Y1 = (Y2 - Y1) * 100;
                for (X = 0; X < Width; X++)
                {
                    X1 = X - Radius; X2 = X + Radius;
                    if (X1 < 0) X1 = 0;
                    if (X2 >= Width) X2 = Width - 1;
                    Sum = *(IndexTwo + X2) - *(IndexOne + X2) - *(IndexTwo + X1) + *(IndexOne + X1);
                    if (*Pointer * (X2 - X1) * Y2Y1 < Sum * InvertThreshold)
                        *Pointer = 0;
                    else
                        *Pointer = 255;
                    Pointer++;
                }
            }
            Marshal.FreeHGlobal((IntPtr)Integral);
        }

  

  其中if (*Pointer * (X2 – X1) * Y2Y1 < Sum * InvertThreshold)
是为了幸免耗时的除操作,升高程序速度。

     
其实,上述计算平均值的情势并不是最快的,有能达标其2倍以上速度的代码。
并且上述算法还设有一个问题,就是对此有些大一点的图像,累加的长河会超越int所能表明的限制,从而使得结果不科学,当然,在C#中,大家得以应用long类型来保存结果,不过这造成2个结果:一是先后占用内存更大,二十对此明日多数的32位操作系统,long所表示的64位数的臆度速度比32位要慢不少。当然对于64位就不相同了。

     
关于杂文中的贴的功效,如同根据他的算法的参数是达不到的,不了然是或不是因为我们的原有图片是从其杂文中截图得到而有降质的缘故。

     
总的而言,那种依照局地特征的二值,在重重情景下比全局阈值的一刀切的效益要好些,对于Wellner来说,搜索的半径的大小对于结果的影响或者很大的,不过也不自然。比如莉娜那么些漂亮的女子图:

   710官方网站 51 
 710官方网站 52   
 710官方网站 53

                          原图                                          
                大律法                    
  S=50,T=15的效果。

 

相关文章