1、图像阈值与二值化

阈值是一种简单的图像分割方法,一幅图像包括目标物体(前景)、背景还有噪声,要想从数字图像中直接提取出目标物体,可以设定一个像素值即阈值,然后用图像的每一个像素点和阈值做比较,给出判定结果。

二值化是特殊的阈值分割方法,把图像分为两部分,以阈值T为分割线,大于T的像素群和小于T的像素群,这样图像就变为黑白二色图像。通过设定一个标准如果大于这个标准就设为白,如果小于这个标准就设为黑,而这个标准就是阈值。

2、OpenCV阈值threshold

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

(1)第一个参数,InputArray 类型的 src,源图像。单通道,8 或 32位浮点数类型的深度。

(2)第二个参数,OutputArray 类型的 dst,输出图像。

(3)第三个参数,double 类型的 thresh,选取的阈值。

(4)第四个参数,double 类型的 maxval。

(5)第五个参数,int 类型的 type。阈值类型。如下所示:

type类型如下:

  1. enum cv::ThresholdTypes {
  2. cv::THRESH_BINARY = ,
  3. cv::THRESH_BINARY_INV = ,
  4. cv::THRESH_TRUNC = ,
  5. cv::THRESH_TOZERO = ,
  6. cv::THRESH_TOZERO_INV = ,
  7. cv::THRESH_MASK = ,
  8. cv::THRESH_OTSU = ,
  9. cv::THRESH_TRIANGLE =
  10. }

不同的阈值方法生成关系如下图。

  1. Mat img = Mat::zeros(, , CV_8UC1);
  2. randu(img, , );
  3.  
  4. int th = ;
  5. Mat threshold1, threshold2, threshold3, threshold4, threshold5, threshold6, threshold7, threshold8;
  6. threshold(img, threshold1, th, , THRESH_BINARY);
  7. threshold(img, threshold2, th, , THRESH_BINARY_INV);
  8. threshold(img, threshold3, th, , THRESH_TRUNC);
  9.  
  10. cout << "raw=\r\n"<<img << "\r\n" << endl;
  11. cout << "THRESH_BINARY=\r\n" << threshold1 << "\r\n" << endl;
  12. cout << "THRESH_BINARY_INV=\r\n" << threshold2 << "\r\n" << endl;
  13. cout << "THRESH_TRUNC=\r\n" << threshold3 << "\r\n" << endl;

上面代码中randu(img, 0, 255)作用是产出随机数填充img矩阵。输出结果如下。

  1. raw=
  2. [ , , , , , ;
  3. , , , , , ;
  4. , , , , , ;
  5. , , , , , ;
  6. , , , , , ;
  7. , , , , , ]
  8.  
  9. THRESH_BINARY=
  10. [ , , , , , ;
  11. , , , , , ;
  12. , , , , , ;
  13. , , , , , ;
  14. , , , , , ;
  15. , , , , , ]
  16.  
  17. THRESH_BINARY_INV=
  18. [, , , , , ;
  19. , , , , , ;
  20. , , , , , ;
  21. , , , , , ;
  22. , , , , , ;
  23. , , , , , ]
  24.  
  25. THRESH_TRUNC=
  26. [ , , , , , ;
  27. , , , , , ;
  28. , , , , , ;
  29. , , , , , ;
  30. , , , , , ;
  31. , , , , , ]

THRESH_BINARY,thresh=100,maxval=200,大于阈值限定为200,小于阈值清零。

THRESH_BINARY_INV的作用和THRESH_BINARY 相反,小于阈值置200,大于阈值清。

THRESH_TRUNC的作用是对大于阈值的数据进行截断,其余值保留原值不变。

图像阈值例子如下。

  1. Mat img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic6.bmp", IMREAD_GRAYSCALE);
  2. int th = ;
  3. Mat threshold1, threshold2, threshold3, threshold4, threshold5, threshold6, threshold7, threshold8;
  4. threshold(img, threshold1, th, , THRESH_BINARY);
  5. threshold(img, threshold2, th, , THRESH_BINARY_INV);
  6. threshold(img, threshold3, th, , THRESH_TRUNC);
  7.  
  8. imshow("raw pic",img);
  9. imshow("THRESH_BINARY", threshold1);
  10. imshow("THRESH_BINARY_INV", threshold2);
  11. imshow("THRESH_TRUNC", threshold3);

3、自动阈值—大津法OTSU

最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出,是一种自适应的阈值确定方法。算法假设图像像素能够根据阈值,被分成背景[background]和目标[objects]两部分。然后,计算该最佳阈值来区分这两类像素,使得两类像素区分度最大。

算法原理为:

设图像Img长宽尺寸为M*N, T为二值化的阈值;

N0为灰度小于T的像素的个数,N0的平均灰度为μ0。

N1 为灰度大于T的像素的个数,N1的平均灰度为μ1。

ω0=N0/ M×N                   (1)   //落在N0的概率

ω1=N1/ M×N                   (2)  //落在N1的概率

N0+N1=M×N                    (3)  

ω0+ω1=1                        (4)       

μ=ω0*μ0+ω1*μ1              (5)  //平均灰度乘以概率 再相加

g=ω0(μ0-μ)^2+ω1(μ1-μ)^2     (6)   //类间方差

将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2    (7)

OpenCV自带了OSTU算法。

  1. Mat img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp", IMREAD_GRAYSCALE);
  2. int th = ;
  3. Mat threshold1, threshold2, threshold3;
  4. threshold(img, threshold1, th, , THRESH_BINARY);
  5. threshold(img, threshold2, th, , THRESH_TRUNC);
  6. threshold(img, threshold3, th, , THRESH_OTSU); // 阈值随意设置即可
  7.  
  8. imshow("raw pic",img);
  9. imshow("THRESH_BINARY", threshold1);
  10. imshow("THRESH_TRUNC", threshold2);
  11. imshow("THRESH_OTSU", threshold3);

使用大津法时阈值可以不设置或随意设置,函数会自动计算最合适的阈值,输出图像如下。

大津法相比其他二值化方法,能很好的筛选出前景图和背景图,让图像分类后黑白区分度最大。

4、参考文献

1、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著

2、Miscellaneous Image Transformations

https://docs.opencv.org/3.1.0/d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57

3、OpenCV threshold函数详解

https://blog.csdn.net/weixin_42296411/article/details/80901080

4、详细及易读懂的 大津法(OTSU)原理 和 算法实现

https://blog.csdn.net/u012198575/article/details/81128799

尊重原创技术文章,转载请注明。

https://www.cnblogs.com/pingwen/p/12300590.html

OpenCV3入门(五)图像的阈值的更多相关文章

  1. 第十四节,OpenCV学习(三)图像的阈值分割

    图像的阈值处理 图像的阈值分割:图像的二值化(Binarization) 阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且总可以得到封闭且连通区域的边界 ...

  2. Python 图像处理 OpenCV (6):图像的阈值处理

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  3. openresty 前端开发入门五之Mysql篇

    openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...

  4. Thinkphp入门 五 —模型 (49)

    原文:Thinkphp入门 五 -模型 (49) [数据库操作model模型] model  模型  数据库操作 tp框架主要设计模式:MVC C:controller   控制器   shop/Li ...

  5. DevExpress XtraReports 入门五 创建交叉表报表

    原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...

  6. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

  7. 基于Otsu算法的图像自适应阈值切割

    在图像处理实践中,将灰度图转化为二值图是非经常见的一种预处理手段. 在Matlab中,能够使用函数BW = im2bw(I, level)来将一幅灰度图 I.转化为二值图. 当中.參数level是一个 ...

  8. C#基础入门 五

    C#基础入门 五 递归 递归调用:一个方法直接或间接地调用了它本身,就称为方法的递归调用. 递归方法:在方法体内调用该方法本身. 递归示例 public long Fib(int n) { if(n= ...

  9. Python爬虫入门五之URLError异常处理

    大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...

  10. Python爬虫教程——入门五之URLError异常处理

    大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...

随机推荐

  1. 洛谷$P$2123 皇后游戏 贪心

    正解:贪心 解题报告: 传送门! 心血来潮打算把$luogu$提高历练地及其之前的所有专题都打通关,,,$so$可能会写一些比较水的题目的题解$QAQ$ 这种题,显然就套路地考虑交换相邻两个人的次序的 ...

  2. HDU4734 F(x) 题解 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 题目大意: 对于一个 \(n\) 位十进制数 \(x\) (\(A_nA_{n-1}A_{n-2 ...

  3. structs2的048漏洞复现 2.3.32版本

    S2-048 远程代码执行漏洞 影响版本: 2.0.0 - 2.3.32 之前在网上说只要时2.3.*的版本都有这个漏洞,自己装了个2.3.34的试了几次都没有执行 然后下载了找到了这篇文章才知道影响 ...

  4. asp.net core系列 74 Exceptionless服务端安装

    一.   Docker安装 Docker   要求版本Docker 18.09.0+以上 安装地址:https://www.runoob.com/docker/windows-docker-insta ...

  5. 如何对N个接口按比例压测

    随着微服务盛行,公司的服务端项目也越来越多.单一的接口性能测试并不能准确反映某个服务的总体处理能力,在服务功能划分比较清晰的架构下,对于某一服务的总体性能测试也相对变得简单.下面分享一个对于某个模块对 ...

  6. 微信授权流程和JSSDK调用流程

    概念理解 业务域名:当前业务使用的是哪个网站,好处:设置业务域名后,在微信内访问该域名下页面时,不会被重新排版.不出现“防欺诈盗号,请误支付或输入qq密码”的提示,微信认为该域名是安全的,客户也不觉得 ...

  7. 自媒体工具OpenWrite

    自媒体工具OpenWrite  本篇主要介绍一款自媒体工具OpenWrite,如果你平时喜欢写写文章又或者写写笔记 你可以使用OpenWrite 统一将你写的文章发布到各个平台 包括 CSDN . S ...

  8. BigDecimal的加减乘除,比较,小数保留

    关于BigDecimal的一些常用基本操作记录 1        BigDecimal b1 = new BigDecimal("1.124"); 2        BigDeci ...

  9. 继承Exception⭐⭐

    public class ECOrderException : Exception { //第一种类型: throw new ECOrderException { ErrorCode = " ...

  10. C# 调用word进程操作文档关闭进程

    C# 调用word进程操作文档关闭进程 作者:Jesai 时间:2018-02-12 20:36:23 前言: office办公软件作为现在主流的一款办公软件,在我们的日常生活和日常工作里面几乎每天都 ...