【OCR 学习笔记】二值化——全局阈值方法
二值化——全局阈值方法
- 固定阈值方法
- 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算法1又称最大类间方差法,由日本学者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=1∑Lpi=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=1∑kpi=ω(k)ω1=Pr(C1)=i=k+1∑Lpi=1−ω(k)μ0=i=1∑kiPr(i∣C0)=i=1∑kipi/ω0=μ(k)/ω(k)μ1=i=k+1∑LiPr(i∣C1)=i=k+1∑kipi/ω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=1∑k(i−μ0)2Pr(i∣C0)=i=1∑k(i−μ0)2pi/ω0σ12=i=k+1∑L(i−μ1)2Pr(i∣C0)=i=k+1∑L(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∗)=1≤k≤Lmaxσ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 N. A Threshold Selection Method From Gray-Level Histogram. IEEE Transactions On Systems Man Cybernetics, 1979, 9(1): 62-66. ↩︎
相关文章:
【OCR 学习笔记】二值化——全局阈值方法
二值化——全局阈值方法 固定阈值方法Otsu算法在OpenCV中的实现固定阈值Otsu算法 图像二值化(Image Binarization)是指将像素点的灰度值设为0或255,使图像呈现明显的黑白效果。二值化一方面减少了数据维度,另一方面通过排除原图中…...
Java - IDEA开发
使用IDEA开发Java程序步骤: 创建工程 Project;创建模块 Module;创建包 Package;创建类;编写代码; 如何查看JDK版本 Package介绍: package是将项目中的各种文件,比如源代码、编译生成的字节码、配置文件、…...
Oracle(62)什么是内存优化表(In-Memory Table)?
内存优化表(In-Memory Table)是指将表的数据存储在内存中,以提高数据访问和查询性能的一种技术。内存优化表通过利用内存的高速访问特性,显著减少I/O操作的延迟,提升数据处理的速度。这种技术在需要高性能数据处理的应…...
#window家庭版安装hyper-v#
由于window 11 家庭版没有hyper-v虚拟机服务,则需要安装一下,使用如下操作 1:新建一个txt文件,拷贝如下脚本到里面 pushd "%\~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findst…...
【云原生】Pass容器研发基础——汇总篇
云原生基础汇总 系列综述: 💞目的:本系列是个人整理为了云计算学习的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:每个知识点的修正和深入主要参考各平台大佬的文章,…...
【Py/Java/C++三种语言详解】LeetCode743、网络延迟时间【单源最短路问题Djikstra算法】
可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过) 文章目录 相关推荐阅读一、题目描述二、题目解析三、参考代码PythonJavaC 时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 相关推荐阅读 …...
交替输出
交替输出 题目:线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc wait notify 版 public class SyncWaitNotify {private volatile int flag;private volatile int loopNumber;public SyncWaitNo…...
JS(三)——更改html内数据
获取 DOM 元素,然后修改其属性或内容。使用 getElementById 方法获取特定 ID 的元素: <p id"myParagraph">这是初始的文本</p> const paragraph document.getElementById(myParagraph); paragraph.innerHTML 这是修改后的文本…...
CSS小玩意儿:文字适配背景
一,效果 二,代码 1,搭个框架 添加一张背景图片,在图片中显示一行文字。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" conte…...
C++:平衡二叉搜索树之红黑树
一、红黑树的概念 红黑树, 和AVL都是二叉搜索树, 红黑树通过在每个节点上增加一个储存位表示节点的颜色, 可以是RED或者BLACK, 通过任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树能够确保没有一条路径会比…...
CentOS 7 系统优化
CentOS 7 系统优化 1、配置YUM源 阿里云的YUM源配置: CentOS 7使用以下命令: sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repoCentOS 8使用以下命令: sudo wget -O /etc/yum.repos.d/CentOS…...
扫雷游戏——附源代码
扫雷游戏的源代码比较简单,不设计比较复杂的代码,主要是多个函数的组合,每个函数执行自己的功能,最终支持游戏的完成。 1.菜单 我们需要一个提醒信息来让用户进行选择。 void menu() {printf("***********************\n&…...
Vue3列表(List)
效果如下图:在线预览 APIs List 参数说明类型默认值bordered是否展示边框booleanfalsevertical是否使用竖直样式booleanfalsesplit是否展示分割线booleantruesize列表尺寸‘small’ | ‘middle’ | ‘large’‘middle’loading是否加载中booleanfalsehoverable是否…...
HarmonyOS NEXT - Navigation组件封装BaseNavigation
demo 地址: https://github.com/iotjin/JhHarmonyDemo 代码不定时更新,请前往github查看最新代码 在demo中这些组件和工具类都通过module实现了,具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils 官方介绍 组件导航 (Navigation)(推…...
浅看MySQL数据库
有这么一句话:“一个不会数据库的程序员不是合格的程序员”。有点夸张,但是确是如此。透彻学习数据库是要学习好多知识,需要学的东西也是偏难的。我们今天来看数据库MySQL的一些简单基础东西,跟着小编一起来看一下吧。 什么是数据…...
Pytorch常用训练套路框架(CPU)
文章目录 1. 数据准备示例:加载 CIFAR-10 数据集 2. 模型定义示例:定义一个简单的卷积神经网络 3. 损失函数和优化器示例:定义损失函数和优化器 4. 训练循环示例:训练循环 5. 评估和测试示例:评估模型 6. 保存和加载模…...
C++ | Leetcode C++题解之第338题比特位计数
题目: 题解: class Solution { public:vector<int> countBits(int n) {vector<int> bits(n 1);for (int i 1; i < n; i) {bits[i] bits[i & (i - 1)] 1;}return bits;} };...
智慧校园云平台电子班牌系统源码,智慧教育一体化云解决方案
智慧校园云平台电子班牌系统,利用先进的云计算技术,将教育信息化资源和教学管理系统进行有效整合,实现生态基础数据共享、应用生态统一管理,为智慧教育建设的统一性,稳定性,可扩展性,互通性提供…...
数据库系统 第17节 数据仓库 案例赏析
下面我将通过几个具体的案例来说明数据仓库如何在不同的行业中发挥作用,并解决实际业务问题。 案例 1: 零售业 背景: 一家大型零售商希望改进其库存管理和市场营销策略,以提高销售额和顾客满意度。 解决方案: 数据仓库: 构建一个数据仓库࿰…...
硬件面试经典 100 题(71~90 题)
71、请问下图电路的作用是什么? 该电路实现 IIC 信号的电平转换(3.3V 和 5V 电平转换),并且是双向通信的。 上下两路是一样的,只分析 SDA 一路: 1) 从左到右通信(SDA2 为输入状态&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
