本文的基础是OpenCV的函数threshold(),关于函数threshold()的详细介绍,大家可以参考下面这篇博文:
https://www.hhai.cc/thread-162-1-1.html
一、图像的OTSU阈值化
在阈值化处理中,OTSU是一种常用的算法,中文译为大津法或最大类间方差法。
它是1979年由日本学者大津展之提出的一种对图像进行二值化的高效算法,是在判别与最小二乘法原理的基础上推导出来的。
它的基本思路是把直方图在某一阈值处分割成两组,当被分成的两组间方差为最大时,这一阈值为“决定阈值”。
OTSU的算法步骤如下:
⑴统计灰度级中每个像素在整幅图像中的个数。
⑵计算每个像素在整幅图像的概率分布。
⑶对灰度级进行遍历搜索,计算当前灰度值下前景背景类间概率。
⑷通过目标函数计算出类内与类间方差下对应的阈值。
更具体的原理介绍大家可以参考下面这篇博文:
https://blog.csdn.net/weixin_44227356/article/details/116031602
图像的OTSU阈值化可以直接由函数threshold()实现,具体实现的代码我已经写在下面这篇博文中了:
https://www.hhai.cc/thread-162-1-1.html【打开页面后搜索“当type取值为THRESH_OTSU 、THRESH_TRIANGLE时的示例代码”】
在上面链接的博文中我已经说了,函数threshold()的Python版才会返回进行阈值化时所使用的阈值,C++版本则不会,所以在OpenCV-C++环境下,函数threshold()使用OTSU算法进行阈值化处理时用的阈值我们是不知道的。如果想知道OTSU算法的阈值是多少,只有自己根据OTSU算法的原理写出代码进行计算。
这里昊虹君根据OTSU算法的原理写了一个计算OTSU阈值计算的函数,
具体的代码请大家访问本博文的原文获取,
本博文原文链接如下:
https://www.hhai.cc/thread-165-1-1.html
运行结果如下:
上面的阈值与我们在Python-OpenCV环境下使用函数threshold()得到的OTSU阈值是一样的:
上面这张截图来源于下面这篇博文:
https://www.hhai.cc/thread-162-1-1.html
二、图像的双阈值化
有时候图像中有明显的双分界特征,我们考虑用双阈值法进行阈值化操作。
所谓双阈值化是指对于两个阈值thresh1<thresh2,将大于thresh1且小于thresh2的灰度值设定为maxval,其余的灰度值设为0。
其数学表达式如下:
d
s
t
(
x
,
y
)
=
{
m
a
x
v
a
l
t
h
r
e
s
h
2
>
s
r
c
(
x
,
y
)
>
t
h
r
e
s
h
1
0
其
它
dst(x,y)=\left\{\begin{matrix} maxval & thresh2>src(x,y)>thresh1 \\0 & 其它 \end{matrix}\right.
dst(x,y)={maxval0thresh2>src(x,y)>thresh1其它
可以用函数threshold()实现图像的双阈值化,其C++代码如下:
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术
//OpenCV版本 OpenCV3.0
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
cv::Mat A1 = (cv::Mat_<uchar>(2, 3) << 0, 10, 50,
80, 150, 255);
cout << "A1中的数据为:\n" << A1 << endl << endl;
double low_threshold = 70;
double high_threshold = 180;
double maxval1 = 222;
Mat B1, B2, B3, B4, B5;
// 小阈值对图像或矩阵进行阈值化操作
threshold(A1, B1, low_threshold, maxval1, THRESH_BINARY);
cout << "B1中的数据为:\n" << B1 << endl << endl;
// 大阈值对图像或矩阵进行阈值化操作
threshold(A1, B2, high_threshold, maxval1, THRESH_BINARY_INV);
cout << "B2中的数据为:\n" << B2 << endl << endl;
// 矩阵与运算得到阈值化结果
cv::bitwise_and(B1, B2, B3);
cout << "B3中的数据为:\n" << B3 << endl << endl;
return(0);
}
运行结果如下图所示:
从上面的运行结果我们可以看出,原矩阵中介于阈值70到180之间的灰度值被置为了222,其它灰度值被置为了0。
二、图像的半阈值化
如果图像中有明显的目标与背景的差异特征,那么进行阈值化操作时,可以使用半阈值化进行操作。
半阈值化操作时,大于thresh的灰度值不变,其余灰度值置为0。
半阈值化的数学表达式如下:
函数threshold(),当参数type取值为“THRESH_TOZERO”时,实际上就是作的图像的半阈值化操作。
示例代码之前在博文https://www.hhai.cc/thread-162-1-1.html中就已经给出了,这里就不再给了。