C#,图像二值化(23)——局部阈值的绍沃拉算法(Sauvola Thresholding)及源程序

news2025/1/19 3:27:48

1、局部阈值的绍沃拉算法(Sauvola Thresholding)

Niblack和Sauvola阈值算法

Niblack和Sauvola阈值是局部阈值技术,对于背景不均匀的图像非常有用,尤其是对于文本识别1、2。代替为整个图像计算单个全局阈值,通过使用考虑到局部邻域(由以像素为中心的窗口定义)的平均值和标准偏差的特定公式,为每个像素计算多个阈值。

Niblack and Sauvola Thresholding

Niblack and Sauvola thresholds are local thresholding techniques that are useful for images where the background is not uniform, especially for text recognition 1, 2. Instead of calculating a single global threshold for the entire image, several thresholds are calculated for every pixel by using specific formulae that take into account the mean and standard deviation of the local neighborhood (defined by a window centered around the pixel).

利用积分图像实现Sauvola方法

团队成员:瓦哈布·阿夫塔布、费赞·扎法尔、萨阿德·拉扎、拉贾·乌迈尔

在本项目中,我们开发了一种二值化退化或历史文档的方法。该方法是文档图像二值化研究论文的自适应阈值方法的实现(底部给出了链接)。首先将图像转换为灰度以应用阈值技术,然后使用Sauvola方法使用相邻窗口像素的平均值和标准差来计算阈值。积分图像不需要对所有像素求和以在一个窗口中找到平均值和标准偏差,而是使用4次数学运算即可有效地计算平均值和平均偏差。这使得该方法更加高效,并且大大减少了运行时间,而不依赖于窗口大小,并且不会对原始Sauvola方法的质量产生任何影响。

图像二值化:

图像二值化是拍摄灰度图像并将其转换为黑白图像的过程,本质上是将图像中包含的信息从256个灰度级减少到2个灰度级:黑白二值图像。保存所有或最大子组件(如文本、背景和图像)是扫描文档预处理中最重要的步骤。二值化计算区分对象和背景像素的阈值。如我们所知,灰度图像像素值的范围为[0-255]。因此,在转换为灰度之后,如果图像像素值高于阈值,则将其转换为白色,即255,如果低于阈值,则转换为黑色,即0,从而使所有像素为0或255,因此称为二进制。

二值化技术:

如所讨论的,二值化根据阈值将具有许多阴影的图像转换为黑白图像。有许多方法来计算阈值,全局阈值是一种方法,其中使用全局阈值(通常为127)来对整个图像进行二值化。许多其他自适应阈值技术也被使用,如otsu,以基于区域阈值对图像进行二值化,即为不同区域计算不同的阈值。这些方法在对高质量图像应用阈值时有效。然而,当处理降级图像时,这项任务变得困难。

Sauvola方法:

在Sauvola的二值化方法中,使用以像素(x,y)为中心的w×w窗口中像素强度的平均值m(x,y)和标准偏差s(x,x)来计算阈值t(x,Z):

其中k是[0.2,0.5]范围内的控制因子,R是预定的图像灰度值。原论文作者建议k=0.2,R=125。局部平均值m(x,y)和标准偏差s(x,y)根据像素的局部邻域中的对比度来调整阈值的值。当图像的某些区域存在高对比度时,s(x,y)≈R,这导致t(x,y)≈m(x,x)。这与Niblack方法的结果相同。然而,当当地社区的对比度很低时,就会出现差异。在这种情况下,阈值t(x,y)低于平均值,从而成功地去除了背景中相对较暗的区域。参数k控制局部窗口中的阈值的值,使得k的值越高,阈值与局部平均值m(x,y)越低。由于该方法适用于低对比度,并且可以解决图像中的阴影、亮度、降级、噪声、污迹、污渍等问题,因此它为我们提供了一个完美的解决方案。然而,为了计算阈值t(x,y),必须计算每个像素的局部平均值和标准偏差。以天真的方式计算m(x,y)和s(x,y)会导致N×N图像的计算复杂度为O(W^2 x N^2),这使得该过程非常缓慢。

Efficient Implementation of Sauvola Method Using Integral Images

Team members: Wahab Aftab, Faizan Zafar, Saad Raza, Raja Umair

In this Project, we developed a method to binarize degraded or historical documents. The method is the implementation of the Adaptive Thresholding Methods for Documents Image Binarization Research Paper (link given at the bottom). The image is first converted to grayscale to apply a thresholding technique, then Sauvola method is used to compute the threshold using mean and standard deviation of neighbouring window pixels. Instead of summing over all the pixels to find mean and standard deviation withtin a window, integral images are used to efficienty compute mean and standard deviation with as little as 4 mathematical operations. This makes the method much more efficient and reduces runtime drastically without relying on window size and it doesn't have any impact on original Sauvola method quality.

Image Binarization:

Image binarization is the process of taking a grayscale image and converting it to black-and-white, essentially reducing the information contained within the image from 256 shades of gray to 2: black and white, a binary image. It's the most important step in pre-processing of scanned documents to save all or maximum subcomponents such us text, background and image. Binarization computes the threshold value that differentiate object and background pixels. As we know grayscale image pixel values range from [0-255] So after conversion to grayscale, image pixel values are converted to white i.e 255 if they are above threshold value and to black i.e 0 if they are below the threshold making all the pixels either 0 or 255 hence the term binary.

Binarization Techniques:

As discussed, binarization converts the image with many shades into an image of black and white depending on the threshold value. There are many methods to compute the threshold value, global thresholding is one method where a global threshold (typically 127) is used to binarize entire image. Many other adaptive thresholding techniques are also used like otsu to binarize image based on region wise thresholding i.e different thresholdss are computed for different regions. These methods work when applying thresholding onto good quality image. However, this task becomes difficult when it deals with degraded image.

Sauvola's Method:

In Sauvola’s binarization method, the threshold t(x, y) is computed using the mean m(x, y) and standard deviation s(x, y) of the pixel intensities in a w × w window centered around the pixel (x, y):

where k is a control factor in the range of [0.2, 0.5] and R is a predetermined image graylevel value. The author of the original paper suggested k=0.2, R= 125. The local mean m(x, y) and standard deviation s(x, y) adapt the value of the threshold according to the contrast in the local neighborhood of the pixel. When there is high contrast in some region of the image, s(x, y) ≈ R which results in t(x, y) ≈ m(x, y). This is the same result as in Niblack’s method. However, the difference comes in when the contrast in the local neighborhood is quite low. In that case the threshold t(x, y) goes below the mean value thereby successfully removing the relatively dark regions of the background. The parameter k controls the value of the threshold in the local window such that the higher the value of k, the lower the threshold from the local mean m(x, y). Since this method is good for low contrast and can tackle problems like Shadows, Luminance, Degradation, Noise, smudge, stains etc in an image, So it provided us with a perfect solution for our problem. However, in order to compute the threshold t(x, y), local mean and standard deviation have to be computed for each pixel. Computing m(x, y) and s(x, y) in a naive way results in a computational complexity of O(W^2 x N^2) for an N × N image which makes the process very slow.

2、局部阈值的绍沃拉算法(Sauvola Thresholding)源代码

二值算法综述请阅读:

C#,图像二值化(01)——二值化算法综述与二十三种算法目录

https://blog.csdn.net/beijinghorn/article/details/128425225?spm=1001.2014.3001.5502

支持函数请阅读:

C#,图像二值化(02)——用于图像二值化处理的一些基本图像处理函数之C#源代码

https://blog.csdn.net/beijinghorn/article/details/128425984?spm=1001.2014.3001.5502

namespace Legalsoft.Truffer.Binarization
{
public static partial class BinarizationHelper
{
    #region 灰度图像二值化 局部算法 Sauvola 算法

    /// <summary>
    /// 局部算法
    /// 实现Sauvola算法实现图像二值化
    /// https://blog.csdn.net/weixin_43211480/article/details/106748822
    /// </summary>
    /// <param name="data"></param>
    /// <param name="kernel">以当前像素点为中心的邻域的宽度</param>
    /// <param name="k">使用者自定义的修正系数</param>
    public static void Sauvola_Algorithm(byte[,] data, int kernel = 15, double k = 0.3)
    {
        int height = data.GetLength(0);
        int width = data.GetLength(1);

        //邻域边界距离中心点的距离
        int whalf = kernel / 2;
        //int MAXVAL = 256;

        int[,] integral_image = new int[width, height];
        int[,] integral_sqimg = new int[width, height];
        int[,] rowsum_image = new int[width, height];
        int[,] rowsum_sqimg = new int[width, height];
        for (int y = 0; y < height; y++)
        {
            rowsum_image[0, y] = data[y, 0];
            rowsum_sqimg[0, y] = data[y, 0] * data[y, 0];
        }

        for (int x = 1; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                //计算图像范围内任意宽度窗口(邻域)的灰度值之和
                rowsum_image[x, y] = rowsum_image[x - 1, y] + data[y, x];

                //计算图像范围内任意宽度窗口(邻域)的灰度值平方之和
                rowsum_sqimg[x, y] = rowsum_sqimg[x - 1, y] + data[y, x] * data[y, x];
            }
        }

        for (int x = 0; x < width; x++)
        {
            integral_image[x, 0] = rowsum_image[x, 0];
            integral_sqimg[x, 0] = rowsum_sqimg[x, 0];
        }

        for (int x = 0; x < width; x++)
        {
            for (int y = 1; y < height; y++)
            {
                //计算图像范围内任意宽度窗口(邻域)的灰度值的积分
                integral_image[x, y] = integral_image[x, y - 1] + rowsum_image[x, y];

                //计算图像范围内任意宽度窗口(邻域)的灰度值平方的积分
                integral_sqimg[x, y] = integral_sqimg[x, y - 1] + rowsum_sqimg[x, y];
            }
        }

        byte[,] dump = (byte[,])data.Clone();
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int xmin = Math.Max(0, x - whalf);
                int ymin = Math.Max(0, y - whalf);
                int xmax = Math.Min(width - 1, x + whalf);
                int ymax = Math.Min(height - 1, y + whalf);
                double area = (xmax - xmin + 1) * (ymax - ymin + 1);
                if (area <= 0)
                {
                    throw new Exception("Binarize: area can't be 0 here");
                }

                double diff = 0.0;
                double sqdiff = 0.0;
                if (xmin == 0 && ymin == 0)
                {
                    diff = integral_image[xmax, ymax];
                    sqdiff = integral_sqimg[xmax, ymax];
                }
                else if (xmin == 0 && ymin > 0)
                {
                    diff = integral_image[xmax, ymax] - integral_image[xmax, ymin - 1];
                    sqdiff = integral_sqimg[xmax, ymax] - integral_sqimg[xmax, ymin - 1];
                }
                else if (xmin > 0 && ymin == 0)
                {
                    diff = integral_image[xmax, ymax] - integral_image[xmin - 1, ymax];
                    sqdiff = integral_sqimg[xmax, ymax] - integral_sqimg[xmin - 1, ymax];
                }
                else
                {
                    double diagsum = integral_image[xmax, ymax] + integral_image[xmin - 1, ymin - 1];
                    double idiagsum = integral_image[xmax, ymin - 1] + integral_image[xmin - 1, ymax];
                    //以(i,j)为中心点的w邻域内灰度值的积分
                    diff = diagsum - idiagsum;

                    double sqdiagsum = integral_sqimg[xmax, ymax] + integral_sqimg[xmin - 1, ymin - 1];
                    double sqidiagsum = integral_sqimg[xmax, ymin - 1] + integral_sqimg[xmin - 1, ymax];
                    //以(i,j)为中心点的w邻域内灰度值平方的积分
                    sqdiff = sqdiagsum - sqidiagsum;
                }

                //以(i,j)为中心点的w邻域内的灰度均值
                double mean = diff / area;

                //以(i,j)为中心点的w邻域内的标准方差
                double std = Math.Sqrt((sqdiff - diff * diff / area) / (area - 1));

                //根据Sauvola计算公式和以(i,j)为中心点的w邻域内的灰度均值与标准方差来计算当前点(i,j)的二值化阈值
                double threshold = mean * (1 + k * ((std / 128) - 1));

                //根据当前点的阈值对当前像素点进行二值化
                data[y, x] = (byte)((dump[y, x] < threshold) ? 0 : 255);
            }
        }
    }

    #endregion
}
}

3、局部阈值的绍沃拉算法(Sauvola Thresholding)计算效果

POWER BY 315SOFT.COM & TRUFFER.CN

与联高《原本》算法比起来,效果差的很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【5】K8S_Deployment

目录 1、Deployment作用 2、deployment的冗余能力 3、deployment的多副本部署 4、deployment的扩缩容 5、deployment的自愈能力 6、滚动更新 7、版本回退 1、Deployment作用 控制Pod&#xff0c;使Pod拥有多副本&#xff0c;自愈&#xff0c;扩缩容等能力 2、deployme…

【正点原子FPGA连载】第十五章开发环境搭建 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十五章开发环境…

uniapp 窗口小工具、桌面小部件、微件(日历、时间) Ba-AwCalendarS

简介&#xff08;下载地址&#xff09; Ba-AwCalendarS 是一款窗口小工具&#xff08;桌面小部件、微件&#xff09;插件&#xff0c;默认为简单的时间样式&#xff0c;有其他界面需要&#xff0c;可联系作者定制。 支持定时更新&#xff08;本插件为每分钟&#xff09;支持点…

基于springboot,vue二手交易平台

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

【数据结构】开端序幕

写在前面&#xff0c;感同身受初学数据结构&#xff0c;是不是一脸懵&#xff0c;下面你中招了几条&#xff1f;&#x1f62d;怎么全是指针&#xff01;指针都不会啊&#xff01;怎么变量名那么长&#xff0c;好难理解啊!什么p&#xff0c;什么next&#xff0c;pp->next究竟…

LeetCode[1753]移除石头的最大得分

难度&#xff1a;中等题目&#xff1a;你正在玩一个单人游戏&#xff0c;面前放置着大小分别为 a、b和 c的 三堆 石子。每回合你都要从两个 不同的非空堆 中取出一颗石子&#xff0c;并在得分上加 1分。当存在 两个或更多 的空堆时&#xff0c;游戏停止。给你三个整数 a、b和 c…

动手深度学习-多层感知机

目录感知机多层感知机激活函数sigmoid函数tanh函数ReLU函数多层感知机的简洁实现参考教程&#xff1a;https://courses.d2l.ai/zh-v2/ 感知机 模型&#xff1a; 感知机模型就是一个简单的人工神经网络。 感知机是二分类的线性模型&#xff0c;其输入是实例的特征向量&#x…

智慧管廊智能化运维管理平台详情

运维管理平台 ​ 平台主界面完成各分系统情况的全局性展现&#xff0c;用图形界面的方法提升视觉效果感染力&#xff0c;根据图色区分正常、异常情况。 1、自然环境及设备监控 ​ 选用全景分层三维可视化地理信息系统及其多元化的二维在线地图从温度、风速、电力、排水、安防…

windows检测远程主机是否连通或者某个端口是否开启

文章目录一、检测主机是否连通步骤二、测试端口是否打开步骤telnet安装一、检测主机是否连通 ping命令是个使用频率极高的网络诊断工具&#xff0c;在Windows、Unix和Linux系统下均适用。它是TCP/IP协议的一部分&#xff0c;用于确定本地主机是否能与另一台主机交换数据报。根…

2022年度总结 EXI-小洲

文章目录一、第一次自我介绍二、2022我都干了些什么(我的收获)1.大专顺利毕业2.后端开发辞职3.第二次代表学校参加江西省职业院校大数据技能大赛4.专升本考试5.参加泰迪杯第五届"数据分析技能赛"6.在csdn开始写博文7.在本科阶段&#xff0c;我又认识了几个会喝点酒的…

【2022年度总结】总结过去,展望未来

文章目录前言回顾过去一、刷题道路两眼黑二、助人为乐本身便是一种快乐展望未来兔年Flag博客文章竞赛目标学习目标志同道合前言 注册CSDN一年了&#xff0c;新年伊始&#xff0c;正好趁着这个时间复盘一下逝去的2022&#xff01; 很幸运&#xff0c;在对计算机知识懵懂无知的时…

分布式调度XXL-JOB急速入门

文章目录1.业界分布式定时任务框架简介2.分布式调度XXL-JOB核心特性3.Docker部署MySQL8.04.XXL-JOB数据库脚本介绍5.Docker部署XXL-JOB服务端6.XXL-JOB UI菜单模块介绍7.SpringBoot整合XXL-JOB8.分布式调度参数传递9.分布式调度日志埋点10.自定义返回执行成功或失败11.XXL-Job高…

C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二)

C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二) 测试软件: TIA PORTAL V15.1 S7-PLCSIM ADVANCED V3.0 Visual Studio 2019 在上次的分享中,我们了解了TIA博途一侧的具体组态配置,具体内容可参考以下链接中的内容: C#上位机基础学习_基于SOCKET实现与PLC服务…

【ROS】—— 机器人系统仿真 —URDF优化_xacro (十四)

文章目录前言1. URDF优化_xacro2. Xacro_快速体验3. Xacro_语法详解3.1 属性与算数运算3.2 宏3.3 文件包含4. Xacro_完整使用流程示例4.1 编写 Xacro 文件4.2 集成launch文件5. Xacro_实操前言 &#x1f4e2;本系列将依托赵虚左老师的ROS课程&#xff0c;写下自己的一些心得与笔…

SpringBoot自动配置原理

1、自动配置原理 1、我们编写的SpringBoot启动类上有一个SpringBootApplication注解&#xff0c;表示当前类是springboot的启动类(入口类)。 package com.baidou;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBo…

微信小程序2.9.0基础库canvas2D新API,生成海报保存到手机功能实现

canvasToTempFilePath的官方文档写着在 draw()回调里调用该方法才能保证图片导出成功。文档地址&#xff1a;wx.canvasToTempFilePath(Object object, Object this) | 微信开放文档 我在这里面使用的canva 获取canvas实例&#xff0c;使用的官方的代码。用一个变量canvas保存实…

聊聊 AI 平台存储方案和选型

最近火爆全网的 ChatGPT 再次带来一股 AI 热潮。 过去的五年&#xff0c;AI 快速发展并应用到很多领域中。作为一家存储企业&#xff0c;我们也感受到了 AI 行业的活力&#xff0c;和我们交流团队中&#xff0c;AI 企业越来越多&#xff0c;有自动驾驶、蛋白质结构预测、量化投…

【HTML】【消失的花木兰】花木兰:三兔蹦迪走,安能辨我是兔子?

前言 &#xff08;改编&#xff09;  某日&#xff0c;参军后的花木兰刚回到家乡&#xff0c;却不料遇上抓拿自己的官兵… 因此&#xff0c;花木兰变成兔子躲了起来&#xff0c;你能否找到躲起来的花木兰呢&#xff1f;一起来拭目以待… 一、游戏名称与游戏规则&#xff08…

joinquant量化数据精准吗?

在股票量化投资中&#xff0c;joinquant量化数据起到很大的作用&#xff0c;因为joinquant量化平台的数据能够从众多只股票数据中&#xff0c;能够一一罗列出来&#xff0c;也就是说&#xff0c;joinquant量化数据可以在计算和分析数据模型中&#xff0c;能够帮助投资者找到他们…

【SpringBoot1】创建第一个SpringBoot项目

创建SpringBoot项目可以通过两种方式&#xff1a; 1、通过访问&#xff1a;https://start.spring.io/&#xff0c;SpringBoot的官方网站进行创建SpringBoot项目&#xff1b; 2、通过工具&#xff08;例如&#xff1a;Idea&#xff09;创建SpringBoot项目。本次使用IDEA创建第一…