【OCR 学习笔记】二值化——全局阈值方法

news2024/9/22 17:25:17

二值化——全局阈值方法

  • 固定阈值方法
  • Otsu算法
  • 在OpenCV中的实现
    • 固定阈值
    • Otsu算法

图像二值化(Image Binarization)是指将像素点的灰度值设为0或255,使图像呈现明显的黑白效果。二值化一方面减少了数据维度,另一方面通过排除原图中噪声带来的干扰,可以凸显有效区域的轮廓结构。OCR效果很大程度上取决于该步骤,高质量的二值图像可以显著提升识别的准确率。目前,二值化的方法主要分为全局阈值方法(Global Binarization)、局部阈值方法(Local Binarization)、基于深度学习的方法和其他方法。

固定阈值方法

该方法对输入图像中的所有像素点统一使用同一个固定阈值。其算法如下:
g ( x , y ) = { 255 , 若 f ( x , y ) ≥ T 0 , 否则 g(x,y)=\begin{cases} 255, & 若f(x,y)\geq T \\ 0, & 否则 \end{cases} g(x,y)={255,0,f(x,y)T否则

  • T T T为全局阈值

不同的阈值 T T T会产生不同的二值化效果。对于不同的输入图像,最佳的阈值 T T T也不一样,这也是固定阈值方法的主要缺陷。
于是,解决这一缺陷的相应算法也随之而出现;下面的几种方法均采用了根据输入图像计算最佳阈值的思想。

Otsu算法

Ostu算法又称最大类间方差法,由日本学者Nobuyuki Ostu于1979年提出,是一种在自适应的阈值确定方法。
Ostu算法将输入图像分为 L L L个灰度级, n i n_i ni表示灰度级为 i i i的像素个数,则像素总数 N = n 1 + n 2 + ⋯ + n L N=n_1+n_2+ \cdots +n_L N=n1+n2++nL。为了简化讨论,这里使用归一化的灰度直方图,并将其视为输入图像的概率分布:
p i = n i / N , p i > 0 , ∑ i = 1 L p i = 1 p_i=n_i/N, p_i>0, \sum_{i=1}^{L}p_i=1 pi=ni/N,pi>0,i=1Lpi=1
现假设在第 k k k个灰度级设置阈值,将图像分为 C 0 C_0 C0 C 1 C_1 C1(背景和目标物体), C 0 C_0 C0表示灰度级为 [ 1 , ⋯   , k ] [1, \cdots, k] [1,,k]的像素点, C 1 C_1 C1表示灰度级为 [ k + 1 , ⋯   , L ] [k+1, \cdots, L] [k+1,,L]的像素点,那么两类出现的概率以及类内灰度级的均值分别为:
ω 0 = P r ( C 0 ) = ∑ i = 1 k p i = ω ( k ) ω 1 = P r ( C 1 ) = ∑ i = k + 1 L p i = 1 − ω ( k ) μ 0 = ∑ i = 1 k i P r ( i ∣ C 0 ) = ∑ i = 1 k i p i / ω 0 = μ ( k ) / ω ( k ) μ 1 = ∑ i = k + 1 L i P r ( i ∣ C 1 ) = ∑ i = k + 1 k i p i / ω 1 = μ T − μ ( k ) 1 − ω ( k ) \omega_0=Pr(C_0)=\sum_{i=1}^{k}p_i=\omega(k) \\ \omega_1=Pr(C_1)=\sum_{i=k+1}^{L}p_i=1-\omega(k) \\ \mu_0=\sum_{i=1}^{k}i Pr(i|C_0)=\sum_{i=1}^{k}ip_i/\omega_0=\mu(k)/\omega(k) \\ \mu_1=\sum_{i=k+1}^{L}i Pr(i|C_1)=\sum_{i=k+1}^{k}ip_i/\omega_1=\frac{\mu_T-\mu(k)}{1-\omega(k)} ω0=Pr(C0)=i=1kpi=ω(k)ω1=Pr(C1)=i=k+1Lpi=1ω(k)μ0=i=1kiPr(iC0)=i=1kipi/ω0=μ(k)/ω(k)μ1=i=k+1LiPr(iC1)=i=k+1kipi/ω1=1ω(k)μTμ(k)

  • ω ( k ) \omega(k) ω(k) μ ( k ) \mu(k) μ(k)分别为灰度级从1到 k k k的累计出现概率和平均灰度级;
  • μ T \mu_T μT为整张图像的平均灰度级。

容易证得,对于任意 k k k值均有:
ω 0 μ 0 + ω 1 μ 1 = μ T , ω 0 + ω 1 = 1 \omega_0\mu_0+\omega_1\mu_1=\mu_T, \omega_0+\omega_1=1 ω0μ0+ω1μ1=μT,ω0+ω1=1
这两类得类内方差也可以算得:
σ 0 2 = ∑ i = 1 k ( i − μ 0 ) 2 P r ( i ∣ C 0 ) = ∑ i = 1 k ( i − μ 0 ) 2 p i / ω 0 σ 1 2 = ∑ i = k + 1 L ( i − μ 1 ) 2 P r ( i ∣ C 0 ) = ∑ i = k + 1 L ( i − μ 1 ) 2 p i / ω 1 \sigma_0^2=\sum_{i=1}^{k}(i-\mu_0)^2Pr(i|C_0)=\sum_{i=1}^{k}(i-\mu_0)^2p_i/\omega_0 \\ \sigma_1^2=\sum_{i=k+1}^{L}(i-\mu_1)^2Pr(i|C_0)=\sum_{i=k+1}^{L}(i-\mu_1)^2p_i/\omega_1 σ02=i=1k(iμ0)2Pr(iC0)=i=1k(iμ0)2pi/ω0σ12=i=k+1L(iμ1)2Pr(iC0)=i=k+1L(iμ1)2pi/ω1
为了评价阈值 k k k的好坏,需要引入判别式:
λ = σ B 2 / σ W 2 , κ = σ T 2 / σ W 2 , η = σ B 2 / σ T 2 ( 1 ) \lambda=\sigma_B^2/\sigma_W^2, \kappa=\sigma_T^2/\sigma_W^2, \eta=\sigma_B^2/\sigma_T^2 \qquad (1) λ=σB2/σW2,κ=σT2/σW2,η=σB2/σT2(1)

其中

  • σ W 2 = ω 0 σ 0 2 + ω 1 σ 1 2 \sigma_W^2=\omega_0\sigma_0^2+\omega_1\sigma_1^2 σW2=ω0σ02+ω1σ12,即类内方差
  • σ B 2 = ω 0 ( μ 0 − μ T ) 2 + ω ( μ 1 − μ T ) 2 = ω 0 ω 1 ( μ 1 − μ 0 ) 2 \sigma_B^2=\omega_0(\mu_0-\mu_T)^2+\omega(\mu_1-\mu_T)^2=\omega_0\omega_1(\mu_1-\mu_0)^2 σB2=ω0(μ0μT)2+ω(μ1μT)2=ω0ω1(μ1μ0)2,即类间方差
  • σ T 2 = ∑ i = 1 L ( i − μ T ) 2 p i \sigma_T^2=\sum_{i=1}^{L}(i-\mu_T)^2p_i σT2=i=1L(iμT)2pi,即灰度级的总方差

由于 σ W 2 + σ B 2 = σ T 2 \sigma_W^2+\sigma_B^2=\sigma_T^2 σW2+σB2=σT2始终成立,而对同一张图片来说 σ T 2 \sigma_T^2 σT2是确定的,所以 σ W 2 \sigma_W^2 σW2 σ B 2 \sigma_B^2 σB2,一个越大,另一个就会越小。这样的话,(1)式中的三个目标值 λ , κ , η \lambda, \kappa, \eta λ,κ,η就总是同向运动的。
但是从计算简单程度上来说,因为 σ T 2 \sigma_T^2 σT2 k k k无关,且 σ B 2 \sigma_B^2 σB2只涉及均值的运算。因此, η \eta η是判别 k k k取值好坏的最简单的衡量标准:
η = σ B 2 ( k ) / σ T 2 \eta = \sigma_B^2(k)/\sigma_T^2 η=σB2(k)/σT2
因此,最佳的 k k k值选择( k ∗ k^* k)满足:
σ B 2 ( k ∗ ) = max ⁡ 1 ≤ k ≤ L σ B 2 ( k ) \sigma_B^2(k^*)=\max_{1\leq k \leq L}\sigma_B^2(k) σB2(k)=1kLmaxσB2(k)

在OpenCV中的实现

固定阈值

固定阈值可以在OpenCV中用adptiveThreshold()函数来实现,其函数原型如下:

void cv::adptiveThreshold(	InputArray	src,
							OutputArray	dst,
							double		maxValue,
							int			adaptiveMethod,
							int			thresholdType,
							int			blockSize,
							double		C)

将其中的第5个参数thresholdType指定为THRESH_BINARY就是固定阈值方法。

Otsu算法

Otsu算法可以在OpenCV中用threshold()函数来实现,其函数原型如下:

double cv::threshold(	InputArray	src,
						OutputArray	dst,
						double		thresh,
						double		maxval,
						int			type)

将其中的第5个参数type指定为THRESH_OTSU就是Otsu算法。
这个函数也可以用来通过将该参数指定为THRESH_BINARY来使用固定阈值的方法。
以下是Otsu算法的一个结果示例(上:原图,中:直方图,下:二值化后的结果):
Otsu算法示例
直方图中的红色竖线为Otsu算法找出的最佳阈值。

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

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

相关文章

MyBatis--XML映射文件

MyBatis–XML映射文件 lombok工具包 为了解决声明实体类的get()和set()函数臃肿的问题,我们使用lombok工具包。 我们看一下lombok工具包为我们提供的注解: XML映射文件 我们需要遵守下面的规则: 首先XML映射文件和Mapper接口包应该在同…

用栈访问最后若干元素——682、71、388

682. 棒球比赛(简单) 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。 比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[…

2024 Studio One6.6.1最新版中文版图文破解版教程

在数字音频工作站(DAW)的浩瀚宇宙中,Studio One始终以其独特的魅力和强大的功能脱颖而出。随着6.6.1版本的发布,这款由PreSonus精心打造的音乐制作软件再次迈上了一个全新的台阶,为音乐创作者们带来了前所未有的创作体…

【C++】vector及模拟实现

🚀个人主页:奋斗的小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 💥1、vector的主要函数接口💥2、vector的模拟实现💥2.1 构造和析构&…

Python 3 入门基础知识【1】数据类型 安装下载 推荐

Python的重要性这里不多说了,是一门面向对象的解释型语言,使用缩进作为逻辑层次,功能强大且容易上手,其受欢迎程度也在逐年上升的。这里回顾一下python的基础知识,以便自己查看,欢迎正在学习python的同学参…

ArcGIS10.8 安装教程

目录 一、环境及安装包准备 二、安装流程 1、解压安装包ArcGIS_108.rar 2、安装 三、汉化 四、激活 五、自定义菜单(可选) 六、打开软件按查看 七、安装过程中出现的报错 八、其他 一、环境及安装包准备 安装环境:win7 安装包下载…

[FBCTF2019]RCEService1

打开题目 它给出了提示要求json格式,先尝试一下{"cmd":"ls"} 的确可以执行。接下来就记录过滤了那些关键字。发现键盘上有的特殊符号好像都被过滤。 flag在home目录下,不知道为什么find命令返回为空。。。 cat在这里仍然不能用。…

go语言后端开发学习(六) ——基于雪花算法生成用户ID

前言 在我们日常进行开发的时候,不可避免的会出现对用户表的操作,而为了保证每一个用户的唯一性,这就需要我们创建一个唯一性的id,但是现在有一个问题,如果我们仅仅像通过自增这样方式来创建唯一的id,这无疑是非常不合…

第N5周:Pytorch文本分类入门

本文为365天深度学习训练营 中的学习记录博客原作者:K同学啊 任务: ●1. 了解文本分类的基本流程 ●2. 学习常用数据清洗方法 ●3. 学习如何使用jieba实现英文分词 ●4. 学习如何构建文本向量 一、前期准备 环境安装 这是一个使用PyTorch实现的简单文…

超详细教程:贴片电阻要怎么焊接?

在电子硬件中,焊接是必不可少的一个技能。 但是在实际的学习或者工作过程中,往往会碰上各种各样的焊接条件,焊接环境,如果是对于直插式的元件,比如说焊接一个直插式LED灯或者直插式电解电容,可能很容易焊接…

15个网络工程师必须记住的专业术语和概念

网络工程师在日常工作中确实需要掌握大量的专业术语和概念,这些术语和概念是理解和应用网络技术的基础。以下是一些网络工程师必知的重要术语及其应用场景: 1. IP地址(IP Address) 定义:互联网协议地址,用…

Elasticsearch 8 RAG 技术分享

作者:来自 Elastic 中国区首席架构师 Jerry 本文由 Elastic 中国区首席架构师 Jerry Zhu 在【AI 搜索 TechDay】上的分享整理而成。【AI 搜索 TechDay】 是 Elastic 和阿里云联合主办的 AI 技术 Meetup 系列,聚焦企业级 AI 搜索应用和开发者动手实践&am…

framebuffer总结

FrameBuffer,可以译作"帧缓冲",有时简称为 fbdrv。 这是一种独立于硬件的抽象图形设备。 是Linux为显示设备提供的一个接口,把显存抽象后的一种设备, 允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作 什么是…

QT 网络聊天室简易版

视频:qt开发网络聊天w室软件3.4界面开发_哔哩哔哩_bilibili 目录 UI部分 设计稿图 放置控件 界面美化 拖动窗体 设置界面 网络部分 配置对话框 多项目结果和服务器端设计 客户端框架开发 UI部分 设计稿图 放置控件 界面美化 现在我们把窗体自带的标题栏给去了,用我们自…

软件设计之MySQL(1)

软件设计之MySQL(1) 此篇应在JavaSE之后进行学习: 路线图推荐: 【Java学习路线-极速版】【Java架构师技术图谱】 Navicat可以在软件管家下载 使用navicat连接mysql数据库创建数据库、表、转储sql文件,导入sql数据 学习内容: 数据库概述表、…

6.IIC

理论 参考51单片机IIC理论:链接 在起始信号后必须发送一个7位从机地址 1位方向位,用“0”表示主机发送数据,“1”表示主机接收数据 代码编写 IIC三个模式配置 IIC(阻塞模式)配置 主要方式 IIC(中断模式)配置 IIC(DMA模式)配置 阻塞模式 mi…

智源研究院举办第一期数据与行业应用Workshop

近日,北京智源人工智能研究院联合中国互联网协会人工智能工委会、中国AIIA联盟数据委员会、CSDN举办了以“行业革新,数据先行”为主题的第一期数据与行业应用Workshop。来自智源研究院、中国信息通信研究院、航天信息技术有限公司、北京市科学技术研究院…

学习记录第二十七天

进程 wait函数 功能 等待子进程结束:父进程调用wait函数后,会暂停执行,直到它的某个子进程结束。收集子进程状态:当子进程结束时,wait函数会返回子进程的终止状态,包括是正常终止还是被信号终止等信息。…

单链表leetcode刷题/中(C语言版)

目录 题目1:合并两个有序链表 题目2:分割链表 题目3:随机链表的复制 “单链表leetcode刷题/上”的链接:https://blog.csdn.net/2302_80297338/article/details/140409360?spm1001.2014.3001.5501 题目1:合并两个有…