二值图像分析:OpenCV中的二值化阈值操作

  • 1.二值图像的定义
  • 2.OpenCV中的基本阈值操作
  • 3.OTSU二值寻找算法
    • 3.1 OTSU二值寻找算法介绍
    • 3.2 OTSU二值寻找算法分析
    • 3.2 OpenCV中OTSU算法的使用
  • 4.TRIANGLE二值寻找算法
    • 41 TRIANGLE二值寻找算法介绍
    • 4.2 TRIANGLE二值寻找算法分析
    • 4.3 OpenCV中TRIANGLE算法的使用
  • 5.自适应二值化阈值算法

1.二值图像的定义

二值图像就是图像中灰度值只有2个的图像,一般就是黑白图像,2个灰度值分别为0(表示黑色)和255(表示白色)。二值图像处理与分析在机器视觉与机器人视觉中非常重要,涉及到非常多的图像处理相关的知识。

常见的二值图像分析包括轮廓分析、对象测量、轮廓匹配与识别、形态学处理与分割、各种形状检测与拟合、投影与逻辑操作、轮廓特征提取与编码等。此外图像二值化的方法也有很多,OpenCV支持几种经典的二值化算法。

从编程与代码角度来说,OpenCV中二值图像是单通道的、字节类型的Mat对象。对于任意的输入图像首先需要把图像转换为灰度图,然后通过二值化方法转换为二值图像。本质上来说,从灰度到二值图像是对数据的二分类分割,所以很多数据处理的方法都可以使用,但是图像是特殊类型的数据,它有很多限制条件,这决定了只有一些合适的方法才会取得比较好的效果。这些方法的本质任务就是寻找合理的分割阈值T,使得对于任意一个给定的像素点灰度值经过如下变换成为0或255其中的一个:
P(x,y)={255,P(x,y)>T.0,P(x,y)≤T.P(x, y) = \begin{cases} 255, \qquad & P(x, y) \gt T. \\ 0, \qquad & P(x, y) \le T. \end{cases}P(x,y)={255,0,​P(x,y)>T.P(x,y)≤T.​

2.OpenCV中的基本阈值操作

如果已经寻找到合适的阈值T,那么对图像二值化分割可以看成是一种基本的阈值化操作,OpenCV除了支持正常的二值化阈值分割操作之外,还支持一些其它的阈值操作。

OpenCV中支持的基本阈值操作的C++ API如下:

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

其中src为单通道的输入图像,dst为输出的二值图像,maxval为最大值,一般为255,thresh为阈值,可以与type表示的阈值分割方法配合使用产生不同的二值化效果,type在基本二值化时支持如下五种:

  • THRESH_BINARY = 0:正向二值分割,大于阈值为maxval,反之为0。
  • THRESH_BINARY_INV = 1:反向二值分割,大于阈值为0,反之为maxval
  • THRESH_TRUNC = 2:截断,大于阈值时设为为阈值,否则保持原值不改变。
  • THRESH_TOZERO = 3:取零,大于阈值保留原值不变,低于阈值为0。
  • THRESH_TOZERO_INV = 4:反向取零,大于阈值时设为0,否则保持原值不变。

返回值double类型用于返回实际使用的阈值,因为threshold不仅可以用给定的阈值,也支持一些自动生成阈值的二值化方法,这个时候就可以用这个返回值来得到自动方法所生成的阈值。

举个栗子:

cv::threshold(grayImage,binaryImage,value,255.0,0);

指定二值化方法为THRESH_BINARY = 0时,几个不同阈值时的二值化效果如下:


图像二值化除了第二部分中的手动阈值设置方法之外,还有几个根据图像直方图实现自动全局阈值寻找的方法。OpenCV中支持的有OTSUTriangle这两种直方图阈值寻找算法,这两个非常具有代表性,可以覆盖常见的直方图分布图像。

3.OTSU二值寻找算法

3.1 OTSU二值寻找算法介绍

OTSU是通过计算类间最大方差(找到一个阈值 kkk 将像素灰度值分为2类,使得这2个类的类间方差最大)来确定分割阈值的阈值选择算法,该算法针对图像直方图来计算阈值,对有两个波峰(前景对象和背景)、中间有明显波谷的直方图对应的图像二值化效果比较好,而对于只有一个单峰的直方图对应的图像分割效果没有双峰的好。

3.2 OTSU二值寻找算法分析

假设一幅图像大小为 M∗NM*NM∗N,像素值属于集合 {0,1,2,...,255}\{0,1,2,...,255\}{0,1,2,...,255},用 nin_ini​ 表示像素值为 iii 的像素点的个数,由此可以得到图像的归一化直方图,直方图横轴分量 pi=ni/MNp_i=n_i/MNpi​=ni​/MN ,由概率和统计知识可以得到:
像素总数M∗N=n0+n1+...+n255.(1)像素总数M*N=n_0+n_1+...+n_{255}.\tag{1}像素总数M∗N=n0​+n1​+...+n255​.(1)
∑i=0255pi=1,pi≥0.(2)\sum_{i=0}^{255}p_i=1,p_i\geq0.\tag{2}i=0∑255​pi​=1,pi​≥0.(2)

首先来看对于任意一个给定的介于 0~255的阈值 kkk,将其作为图像阈值来对图像进行二值化操作,可以将像素灰度值分为背景 C1C_1C1​ 和前景对象C2C_2C2​两个类,其中C1C_1C1​由图像中灰度值在区间 [0,kkk] 的所有像素组成,C2C_2C2​由图像中灰度值在区间 [kkk+1,255] 的所有像素组成。

则此图像中,像素被分到C1C_1C1​的概率(或者说C1C_1C1​发生的概率)由如下的累计和给出:
P1(k)=∑i=0kpi.(3)P_1(k)=\sum_{i=0}^{k}p_i.\tag{3}P1​(k)=i=0∑k​pi​.(3)

像素被分到C2C_2C2​的概率(或者说C2C_2C2​发生的概率)由如下的累计和给出:
P2(k)=∑i=k+1255pi=1−P1(k).(4)P_2(k)=\sum_{i=k+1}^{255}p_i=1-P_1(k).\tag{4}P2​(k)=i=k+1∑255​pi​=1−P1​(k).(4)

分配到C1C_1C1​类的平均像素值为:
m1(k)=∑i=0ki⋅P(i/C1)=∑i=0ki⋅P(C1/i)P(i)/P(C1)=1P1(k)∑i=0ki⋅pi(5)m_1(k)=\sum_{i=0}^{k}i·P(i/C_1)\\\qquad\qquad=\sum_{i=0}^{k}i·P(C_1/i)P(i)/P(C_1)\\={\frac{1}{P_1(k)}}{\sum_{i=0}^{k}i·p_i}{\tag{5}} m1​(k)=i=0∑k​i⋅P(i/C1​)=i=0∑k​i⋅P(C1​/i)P(i)/P(C1​)=P1​(k)1​i=0∑k​i⋅pi​(5)

上式中第二行可由贝叶斯公式得到,而在第三行中,在给定 iii 的前提下 C1C_1C1​ 发生的概率 P(C1/i)P(C_1/i)P(C1​/i) 为1,P(i)P(i)P(i) 是第 iii 个值的概率,即归一化直方图 pip_ipi​ 分量的第 iii 个分量,P(C1)P(C_1)P(C1​) 是 C1C_1C1​ 发生的概率,等于(3)式中计算得到的 P1(k)P_1(k)P1​(k)。

同理,分配到C2C_2C2​类的平均像素值为:
m2(k)=∑i=k+1255i⋅P(i/C2)=1P2(k)∑i=k+1255i⋅pi(6)m_2(k)=\sum_{i=k+1}^{255}i·P(i/C_2)\\\qquad\qquad=\frac{1}{P_2(k)}\sum_{i=k+1}^{255}i·p_i{\tag{6}}m2​(k)=i=k+1∑255​i⋅P(i/C2​)=P2​(k)1​i=k+1∑255​i⋅pi​(6)

整个图像的平均像素值为:
mG=∑i=0255i⋅pi(7)m_G=\sum_{i=0}^{255}i·p_i{\tag{7}}mG​=i=0∑255​i⋅pi​(7)

为了评估k的分类质量,假设 σG2\sigma_G^2σG2​为全局方差,即图像中所有像素灰度值的方差,该值是一个常数且只需要计算一次。σB2\sigma_B^2σB2​为类间方差,则有:
σG2=∑i=0255(i−mG)2⋅pi(8)\sigma_G^2=\sum_{i=0}^{255}(i-m_G)^2·p_i{\tag{8}}σG2​=i=0∑255​(i−mG​)2⋅pi​(8)
σB2=P1(m1−mG)2+P2(m2−mG)2=P1P2(m1−m2)2=(mGP1−m)2P1(1−P1)(9)\sigma_B^2=P_1(m_1-m_G)^2+P_2(m_2-m_G)^2{\tag{9}}\\=P_1P_2(m_1-m_2)^2\\=\frac{{(m_GP_1-m)}^2}{P_1(1-P_1)}σB2​=P1​(m1​−mG​)2+P2​(m2​−mG​)2=P1​P2​(m1​−m2​)2=P1​(1−P1​)(mG​P1​−m)2​(9)

至此对于给定的 kkk,已经可以求出此时两个类的类间方差,那么接下来要做的就是对于0~255之间每一个可能的 kkk 按照上面的方式来计算类间方差,找到使其最大化的那一个,如果能使类间方差最大的 kkk 值有多个,则一般取这些 kkk 的平均值。

3.2 OpenCV中OTSU算法的使用

OpenCVOTSU算法使用只需要在threshold()函数的type类型声明THRESH_OTSU即可,举个栗子:

double t = threshold(gray,binary,0,255,THRESH_BINARY|THRESH_OTSU);

同样对于上面的图,计算得到的阈值为147,运行结果如下:

4.TRIANGLE二值寻找算法

41 TRIANGLE二值寻找算法介绍

对于直方图为双波峰的图像来说,是比较好的二值化方法。而对于直方图为单波峰的图像来说,三角阈值法更为有效。之所以叫三角阈值法,是因为该算法通过在图像直方图上构建一个三角形来获得阈值。

4.2 TRIANGLE二值寻找算法分析

来看这样一张图像的归一化直方图:

对于该图像的直方图,首先引一条直线,即图中的红色线,使得该直线经过波峰最高点 AAA 和横轴最远点 BBB,然后不断地作该条直线的垂线,找到使得 ddd 最大化就可以了。实际上可以通过构造等腰直角三星形(如图,ααα 和 βββ 都是45度)来寻找最大 ddd ,则寻找最大 ddd 等价于寻找最大 hhh,显然 hhh 更好找。经 hhh 计算得到的 ddd 就是本算法寻找到的阈值。
h2=2⋅d2−>d=sqrt(h22).h^2=2·d^2->d=sqrt(\frac{h^2}{2}).h2=2⋅d2−>d=sqrt(2h2​).

这里有一个细节,就是对于上面的直方图,该直方图波峰是在靠0的位置,偏左侧。如果实际直方图波峰是靠1.0(不归一化是255),偏右侧的时候,则可以对所有像素取反,然后按照之前的方式来处理就可以了。

4.3 OpenCV中TRIANGLE算法的使用

OpenCVTRIANGLE算法使用只需要在threshold()函数的type类型声明THRESH_TRIANGLE即可,举个栗子:

double t = threshold(gray,binary,0,255,THRESH_BINARY|THRESH_TRIANGLE);

同样对于上面的图,计算得到的阈值为249,运行结果如下:

5.自适应二值化阈值算法

OpenCV中的自适应阈值算法主要是基于均值实现,根据计算均值的方法不同分为盒子模糊(box filter)均值与高斯模糊均值,然后使用原图减去均值图像,得到的差值图像进行自适应分割,相关的API如下:

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

其中blockSize取值必须是奇数,C取值在10左右

adaptiveMethod自适应方法类型:

  • ADAPTIVE_THRESH_GAUSSIAN_C = 1
  • ADAPTIVE_THRESH_MEAN_C = 0

当阈值操作类型thresholdType为:

  • THRESH_BINARY:二值图像 = 原图–均值图像> C? 255:0。
  • THRESH_BINARY_INV:二值图像 = 原图–均值图像>C? 0:255。

举个栗子:

cv::adaptiveThreshold(grayImage,binaryImage,255.0,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,3,10.0);

运行结果如下:

二值图像分析:OpenCV中的二值化阈值操作相关推荐

  1. Python使用openCV把原始彩色图像转化为灰度图、使用OpenCV把图像二值化(仅仅包含黑色和白色的简化版本)、基于自适应阈值预处理(adaptive thresholding)方法

    Python使用openCV把原始彩色图像转化为灰度图.使用OpenCV把图像二值化(仅仅包含黑色和白色的简化版本).基于自适应阈值预处理(adaptive thresholding)方法 目录

  2. 二值化阈值自动选取方法

    二值化阈值自动选取方法 1. 双峰法 双峰法的原理及其简单:它认为图像由前景和背景组成,在灰度直方图上,前后二景都形成高峰,在双峰之间的最低谷处就是图像的阈值所在.根据这一原理,我们给出了它的实现,部 ...

  3. 图像二值化阈值选取常用方法

    图像二值化阈值选取常用方法: 1. 双峰法. 2. P参数法. 3. 最大类间方差法(Otsu.大津法). 4. 最大熵阈值法. 5. 迭代法(最佳阈值法). 1. 双峰法. 1996年,Prewit ...

  4. matlab利用滑动条控制图片二值化阈值

    前言 由于做项目的时候需要对图片进行二值化,而且图片不同需要达到二值化的效果也不同,如果一直要在程序里试探阈值比较麻烦.所以想利用图像界面中的滑动条人工控制二值化阈值. 一.主要步骤 1. 在matl ...

  5. 机器学习进阶-阈值与平滑-图像阈值 1. cv2.threshold(进行阈值计算) 2. 参数type cv2.THRESH_BINARY(表示进行二值化阈值计算)...

    1. ret, dst = cv2.thresh(src, thresh, maxval, type) 参数说明, src表示输入的图片, thresh表示阈值, maxval表示最大值, type表 ...

  6. python阈值计算_机器学习进阶-阈值与平滑-图像阈值 1. cv2.threshold(进行阈值计算) 2. 参数type cv2.THRESH_BINARY(表示进行二值化阈值计算)...

    1. ret, dst = cv2.thresh(src, thresh, maxval, type) 参数说明, src表示输入的图片, thresh表示阈值, maxval表示最大值, type表 ...

  7. 1. cv2.threshold(进行阈值计算) 2. 参数type cv2.THRESH_BINARY(表示进行二值化阈值计算)

    1. ret, dst = cv2.thresh(src, thresh, maxval, type) 参数说明, src表示输入的图片, thresh表示阈值, maxval表示最大值, type表 ...

  8. OpenCv之图像二值化(笔记12)

    # 图像处理中,Thresholding中文翻译过来叫二值化或者阈值化.二值化就是把图片转换成只有white赫尔black这俩种颜色.通过Thresholding,可以让图片中感兴趣 # 的颜色编程主 ...

  9. Opencv教程-图像二值化

    图像二值化的概念 图像二值化是指将指将256阶的灰度图通过合适的阈值,转换为黑白二值图.即像素或0和255.其目的通常为将图像的前后景进行分割,使图像变得简单,数据量减小,能凸显出感兴趣的目标的轮廓. ...

最新文章

  1. JAVA方法中的参数用final来修饰的效果
  2. 不可不知的软件架构模式
  3. java第三方接口对接_调用多个第三方接口哪一种方案更好?
  4. Mac 环境变量配置
  5. Windows 7下硬盘安装Ubuntu 14.10图文教程【硬盘安装】
  6. python爬虫难度排行榜_无聊写了一个python爬虫程序,用来爬夕阳试炼场排行榜的...
  7. 2022最新开源分销商城小程序源码系统前端+后端+搭建教程
  8. 简单爬虫--爬取百度热点新闻标题
  9. 计算机辅助项目管理实验论文,计算机辅助项目管理课程设计—毕设论文.doc
  10. 用html js制作迷宫,JavaScript生成随机迷宫详解
  11. 网站设计高性能高并发
  12. 未闻花名ED《君がくれたもの》原文+罗马音+中文
  13. java 生成证书图片_java生成自定义证书图片1 - 制作证书word模板
  14. CSR867x — CSR8670平台开发调试经验
  15. Statement和PreStatement的区别 以及 #{}和${}的区别
  16. HTTP 304: Not Modified
  17. 鹿鼎记 / Royal Tramp (1992)
  18. word文件中表格迁移到excel
  19. 【2021-01-29】JS逆向之shu美滑块参数分析
  20. 一款超级实用的车辆总线分析系统—VehicleCAN

热门文章

  1. c语言中char * string,浅析string 与char* char[]之间的转换
  2. IDEA中一直Update indexing问题
  3. Linux中的基础指令
  4. 机器学习平台基础知识
  5. Ural 2037. Richness of binary words (打表+构造)
  6. 雷神3开方算法解析,游戏运行速度提高四倍。
  7. 微信小程序--数据库数据批量导出为excel文件,预览下载
  8. 五问补盲(四)| 好用的补盲激光雷达,得满足哪些条件?
  9. 浅谈全概率公式和贝叶斯公式
  10. 利用Python实现scissors-rock-paper-lizard-Spock小游戏