OpenCV3入门(五)图像的阈值
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类型如下:
enum cv::ThresholdTypes {
cv::THRESH_BINARY = ,
cv::THRESH_BINARY_INV = ,
cv::THRESH_TRUNC = ,
cv::THRESH_TOZERO = ,
cv::THRESH_TOZERO_INV = ,
cv::THRESH_MASK = ,
cv::THRESH_OTSU = ,
cv::THRESH_TRIANGLE =
}
不同的阈值方法生成关系如下图。

Mat img = Mat::zeros(, , CV_8UC1);
randu(img, , ); int th = ;
Mat threshold1, threshold2, threshold3, threshold4, threshold5, threshold6, threshold7, threshold8;
threshold(img, threshold1, th, , THRESH_BINARY);
threshold(img, threshold2, th, , THRESH_BINARY_INV);
threshold(img, threshold3, th, , THRESH_TRUNC); cout << "raw=\r\n"<<img << "\r\n" << endl;
cout << "THRESH_BINARY=\r\n" << threshold1 << "\r\n" << endl;
cout << "THRESH_BINARY_INV=\r\n" << threshold2 << "\r\n" << endl;
cout << "THRESH_TRUNC=\r\n" << threshold3 << "\r\n" << endl;
上面代码中randu(img, 0, 255)作用是产出随机数填充img矩阵。输出结果如下。
raw=
[ , , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ] THRESH_BINARY=
[ , , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ] THRESH_BINARY_INV=
[, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ] THRESH_TRUNC=
[ , , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ;
, , , , , ]
THRESH_BINARY,thresh=100,maxval=200,大于阈值限定为200,小于阈值清零。
THRESH_BINARY_INV的作用和THRESH_BINARY 相反,小于阈值置200,大于阈值清。
THRESH_TRUNC的作用是对大于阈值的数据进行截断,其余值保留原值不变。
图像阈值例子如下。
Mat img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic6.bmp", IMREAD_GRAYSCALE);
int th = ;
Mat threshold1, threshold2, threshold3, threshold4, threshold5, threshold6, threshold7, threshold8;
threshold(img, threshold1, th, , THRESH_BINARY);
threshold(img, threshold2, th, , THRESH_BINARY_INV);
threshold(img, threshold3, th, , THRESH_TRUNC);
imshow("raw pic",img);
imshow("THRESH_BINARY", threshold1);
imshow("THRESH_BINARY_INV", threshold2);
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算法。
Mat img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp", IMREAD_GRAYSCALE);
int th = ;
Mat threshold1, threshold2, threshold3;
threshold(img, threshold1, th, , THRESH_BINARY);
threshold(img, threshold2, th, , THRESH_TRUNC);
threshold(img, threshold3, th, , THRESH_OTSU); // 阈值随意设置即可
imshow("raw pic",img);
imshow("THRESH_BINARY", threshold1);
imshow("THRESH_TRUNC", threshold2);
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
尊重原创技术文章,转载请注明。
OpenCV3入门(五)图像的阈值的更多相关文章
- 第十四节,OpenCV学习(三)图像的阈值分割
图像的阈值处理 图像的阈值分割:图像的二值化(Binarization) 阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且总可以得到封闭且连通区域的边界 ...
- Python 图像处理 OpenCV (6):图像的阈值处理
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- openresty 前端开发入门五之Mysql篇
openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...
- Thinkphp入门 五 —模型 (49)
原文:Thinkphp入门 五 -模型 (49) [数据库操作model模型] model 模型 数据库操作 tp框架主要设计模式:MVC C:controller 控制器 shop/Li ...
- DevExpress XtraReports 入门五 创建交叉表报表
原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...
- 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?
本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言 老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...
- 基于Otsu算法的图像自适应阈值切割
在图像处理实践中,将灰度图转化为二值图是非经常见的一种预处理手段. 在Matlab中,能够使用函数BW = im2bw(I, level)来将一幅灰度图 I.转化为二值图. 当中.參数level是一个 ...
- C#基础入门 五
C#基础入门 五 递归 递归调用:一个方法直接或间接地调用了它本身,就称为方法的递归调用. 递归方法:在方法体内调用该方法本身. 递归示例 public long Fib(int n) { if(n= ...
- Python爬虫入门五之URLError异常处理
大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...
- Python爬虫教程——入门五之URLError异常处理
大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...
随机推荐
- Java异常处理原则与技巧总结
一 处理原则 Java异常代码中我们使用异常的目的是让异常的异常类型来提示“什么”被抛出了--- 即出了什么问题:用异常的栈打印信息来跟踪异常在“哪里”抛出 --- 即哪里出了问题: 异常提示信息来 ...
- 洛谷P1037 产生数 题解 搜索
题目链接:https://www.luogu.com.cn/problem/P1037 题目描述 给出一个整数 \(n(n<10^{30})\) 和 \(k\) 个变换规则 \((k \le 1 ...
- Shiro权限管理框架(五):自定义Filter实现及其问题排查记录
明确需求 在使用Shiro的时候,鉴权失败一般都是返回一个错误页或者登录页给前端,特别是后台系统,这种模式用的特别多.但是现在的项目越来越多的趋向于使用前后端分离的方式开发,这时候就需要响应Json数 ...
- Go中的Package和Module分析
Package 所谓package(包)其实就是代码的一种组织管理方式,代码多了就需要放入文件,文件多了就需要归类放入文件夹,就好比我们在给电脑装软件时会进行归类安装,其实也是有意无意对电脑软件安装的 ...
- Linux之shell编程的基本使用
1.Shell shell是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的系统级程序 2.shell编程打印hello world 2.1 代码部分 #!/bin/ba ...
- Zookeeeper的安装与集群搭建
简介 Zookeeper下载 官网地址:点我直达 百度云盘:点我直达 踩坑录 官网下载一定要下载带bin的 要不然zookeeper起不起来,找不到加载类,原来从版本3.5.5开始,带有bin名称的包 ...
- 数字金字塔 动态规划(优化版) USACO 一维dp压缩版
1016: 1.5.1 Number Triangles 数字金字塔 时间限制: 1 Sec 内存限制: 128 MB提交: 9 解决: 8[提交] [状态] [讨论版] [命题人:外部导入] 题 ...
- Tarjan算法伪代码
伪代码: 栈:当前dfs路径上的点low[x]:x能到达的点中最小的dfn dfs(x,t) 将x入栈 dfn[x]=t low[x]=t for(x,y) i ...
- 解决a 标签 和 div 标签高度超出的问题
当a,或div标签里面有内容时,有时候a 或div的高度会超出,此时可以设置a或div的font-size:0:
- hdu 5139 数据的离线处理
所谓的数据离线处理,就是将所有的输入数据全部读入后,在进行统一的操作,这样当然有好处,比如让你算好多数的阶层,但是输入的每个数是没有顺序的,其实跟可以线性的解决,但是由于没有顺序的输入,这样处理的话复 ...