赞
踩
》》点赞,收藏+关注,理财&技术不迷路《《
目录:
9.1 二值化概念与原理
二值化 —— 图像只有两种色,黑白。0-1,0=黑,1=白
灰度:0-255
彩色:255,255,255
定义:图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(Binarization)。
其实图像二值化的方法有不下二十种。一般分为Global和Local两类,区别就是寻找那个阈值的时候使用到了哪里的信息。
一般是为了将感兴趣目标和背景分离。
图像的二值化是最简单的图像处理技术,它一般都跟具体算法联系在一起,很多算法的输入需要是二值数据。比如你把图像文字转换为PDF文字,PDF上只能是黑白两种颜色。比如你给二维码解码,你需要知道哪块黑哪块白。
去掉图像两个字,二值化在视觉里面应用场景多一些。比如早期的人脸检测很多手势识别的方法,第一步要找到皮肤块,所以需要把图像分为皮肤区域和非皮肤区域,这也算是一种二值化,但通常在方法上用的可能不是基于直方图的了(可能是ID3, 随机森林,SVM,甚至神经网络)。比如Haar特征,以及后来的BRIEF和FAST等,还有LBP实际上都是用到二值的思想。
图像二值化可以看作是聚类,可以看作是分类……这些其实不重要,重要的是它快。它最明显的意义就是简化后期的处理,提高处理的速度。`
但是单一的图像二值化方法(指基于直方图的二值化)往往比不过其他的方法,因为,毕竟你信息丢了太多。但是二值化快啊……你可以进行一百次不同的二值化,然后再得到一个更好的结果……
上面右图中下面两个图是还可以对二值图像进行编码。编码后就更好压缩了,那么我们就可以高度节省内存。
图像二值化方法:
全局阈值
局部阈值
9.2 OpenCV中图像二值化方法:
评判某个算法是否好,就看二值化图像信息是否丢失了很多。
threshold(gray_src, dst, threshold_value, threshold_max,THRESH_BINARY);
//原图,目标图,已知阈值,阈值最大值,阈值类型
返回阈值的值和图像。
阈值:简单点说是把图像分割的标尺。这个标尺是根据什么产生的,可以用阈值产生算法(opencv有两个算法)或者是自己指定一个阈值来进行分割。
如下分苹果,大于某一像素的变为黑色,小于某一像素的变为白色,即可通过阈值把图像分割了。
可以根据有5种阈值类型来分割(Binary segmentation二值分割)。
printf("%d", THRESH_BINARY); //0,二值化
printf("%d", THRESH_BINARY_INV); //1,反二值化
printf("%d", THRESH_TRUNC); //2,截断
printf("%d", THRESH_TOZERO); //3,取零
printf("%d\n", THRESH_TOZERO_INV); //4,反取零
9.2.1 5种阈值处理类型(手动)
9.2.1.1 阈值二值化(threshold binary)
THRESH_BINARY
threshold(gray_src, dst, threshold_value, threshold_max, THRESH_BINARY);
//阈值二值化
左下方直方图表示图像像素点Src(x,y)值的分布情况,蓝色水平线表示阈值,大于阈值的取最大值255,小于阈值的取最小值0:
9.2.1.2 阈值反二值化(threshold binary Inverted)
THRESH_BINARY_INV
左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值,大于阈值的取最小值0,小于阈值的取最大值255:
9.2.1.3 截断 (truncate)
THRESH_TRUNC
左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值 ,大于阈值的跟阈值相等,小于阈值的不变:
9.2.1.4 阈值取零 (threshold to zero)
THRESH_TOZERO
左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值,大于阈值的不变,小于阈值的取最小值0:
9.2.1.5 阈值反取零 (threshold to zero inverted)
THRESH_TOZERO_INV
左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值,大于阈值的取最小值0,小于阈值的不变:
9.2.2 2种阈值寻找方法(自动/全局; 基于直方图)
threshold(gray_src, dst, 0, 255, THRESH_OTSU | type_value);
//自动计算二值化otsu阈值,忽略输入的阈值
9.2.2.1 Triangle三角阈值法(基于直方图)
该方法是使用直方图数据,基于纯几何方法来寻找最佳阈值,它的成立条件是假设直方图最大波峰在靠近最亮的一侧,然后通过三角形求得最大直线距离,根据最大直线距离对应的直方图灰度等级即为分割阈值,图示如下:
在直方图上从最高峰处bmx到最暗对应直方图bmin(p=0)%构造一条直线,从bmin处开始计算每个对应的直方图b到直线的垂直距离,知道bmax为止,其中最大距离对应的直方图位置即为图像二值化对应的阈值T。
有时候最大波峰对应位置不在直方图最亮一侧,而在暗的一侧,这样就需要翻转直方图,翻转之后求得值,用255减去即得到为阈值T。扩展情况的直方图表示如下:
所以triangle 非常适合用在只有单个波峰时候!!!!多个波峰的话,应用起来会很差。所以做医学图像处理会很好,因为细胞图片的直方图最多都只有三个波峰,这个方法是从生物医学衍生出的。
算法步骤
1. 图像转灰度
2. 计算图像灰度直方图
3. 寻找直方图中两侧边界
4. 寻找直方图最大值
5. 检测是否最大波峰在亮的一侧,否则翻转
6. 计算阈值得到阈值T,如果翻转则255-T
左边为原图,通过直方图来看像素值分布,通过阈值保留,我们看右图发现前景被保留下来了所以为白色,背景就为黑色了。好的二值化方法就应该如右图一样。
二值化方法中的三角二值化:通过直方图来对图像进行三角二值化,连接波峰波谷然后做垂直线。
9.2.2.2 OTSU阈值法(基于直方图)
直方图统计学
otsu 大津算法介绍:
OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。
利用阈值将原图像分成前景,背景两个图象。
前景:用n1,csum,m1来表示在当前阈值下的前景的点数,质量矩,平均灰度
背景:用n2, sum-csum,m2来表示在当前阈值下的背景的点数,质量矩,平均灰度
当取最佳阈值时,背景应该与前景差别最大,关键在于如何选择衡量差别的标准,而在otsu算法中这个衡量差别的标准就是最大类间方差,在本程序中类间方差用sb表示,最大类间方差用fmax
这段引用自百度百科,不是很好懂。
otsu 大津算法原理
otsu 大津算法是一种图像二值化算法,作用是确定将图像分成黑白两个部分的阈值。
将图像背景和前景分成黑白两类很好理解,但是如何确定背景和前景的二值化界限(阈值)呢?
对于不同的图像,这个阈值可能不同,这就需要有一种算法来根据图像的信息自适应地确定这个阈值。
首先,需要将图像转换成灰度图像,255个灰度等级。
可以将图像理解成255个图层,每一层分布了不同的像素,这些像素垂直叠加合成了一张完整的灰度图。
我们的目的就是找到一个合适的灰度值,大于这个值的我们将它称之为背景(灰度值越大像素越黑),小于这个值的我们将它称之为前景(灰度值越小像素越白)。
怎么确定这个值就是我们想要的值呢?
这里引入方差的概念,方差越大,相关性越低,黑白越分明。
我们将每一个灰度值之上下之间的像素的方差求出来不就行了吗?找到方差最大的那个灰度值,那个就是我们想要的二值化分隔阈值。
先定义几个符号代表的意义:
h:图像的宽度
w:图像的高度(h*w 得到图像的像素数量)
t :灰度阈值(我们要求的值,大于这个值的像素我们将它的灰度设置为255,小于的设置为0)
n0:小于阈值的像素,前景
n1:大于等于阈值的像素,背景
n0 + n1 == h * w
w0:前景像素数量占总像素数量的比例
w0 = n0 / (h * w)
w1:背景像素数量占总像素数量的比例
w1 = n1 / (h * w)
w0 + w1 == 1
u0:前景平均灰度
u0 = n0灰度累加和 / n0
u1:背景平均灰度
u1 = n1灰度累加和 / n1
u:平均灰度
u = (n0灰度累加和 + n1灰度累加和) / (h * w) 根据上面的关系
u = w0 * u0 + w1 * u1
g:类间方差(那个灰度的g最大,哪个灰度就是需要的阈值t)
g = w0 * (u0 - u)^2 + w1 * (u1 - u)^2
根据上面的关系,可以推出:(这个一步一步推导就可以得到)
g = w0 * w1 * (u0 - u1) ^ 2
然后,遍历每一个灰度值,找到这个灰度值对应的 g
找到最大的 g 对应的 t
9.2.3 自适应阈值(局部阈值)
可以想象为把矩阵分成模块化,然后各个模块求平均和阈值比较。(所以又有两种平均方法,还有模块大小选择,比较方法是直接单独比较?还是相差在某个范围内?后者好,因为可以考虑到误差,误差 = 像素值中混杂了噪音)
这个方法只返回binary图像,不返回set阈值的值。
C++: void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
InputArray src:源图像
OutputArray dst:输出图像,与源图像大小一致
int adaptiveMethod:在一个邻域内计算阈值所采用的算法,有两个取值,分别为ADAPTIVE_THRESH_MEAN_C 和 ADAPTIVE_THRESH_GAUSSIAN_C 。
ADAPTIVE_THRESH_MEAN_C的计算方法是计算出领域的平均值再减去第七个参数double C的值
ADAPTIVE_THRESH_GAUSSIAN_C的计算方法是计算出领域的高斯均值再减去第七个参数double C的值
int thresholdType:这是阈值类型,只有两个取值,分别为 THRESH_BINARY 和THRESH_BINARY_INV 具体的请看官方的说明,这里不多做解释
int blockSize:adaptiveThreshold的计算单位是像素的邻域块,邻域块取多大,就由这个值作决定
double C:在对参数int adaptiveMethod的说明中,我已经说了这个参数的作用,从中可以看出,这个参数实际上是一个偏移值调整量
从上面的说明中可以看出,使用函数adaptiveThreshold的关键是确定blockSize和C的值,明白了这两个值的意义之后,在实际项目中,应该可以根据试验法选出较为合适的值吧!
我们改为高斯阈值:
9.2.4 自定义分割
这里我们定义全局平均数来作为阈值分割图像。
上面这一大步是为了将数组矩阵拉直然后求出平均数。一定要先转为 灰度图,因为rgb有三个通道。
9.3 超大图像二值化
# 将大图片拆分成小图片后再用自适应局部阈值比较好
# 因为超大图像一般都是几千万或者几亿像素。1000*1000像素也才100万像素。
# 对于超大像素而言,一个窗口根本显示不了那么多像素。要么就压缩才能显示。
9.3.1 全局阈值(无法排除噪声影响)
本来应该是白色的地方,处理后灰度图中出现了雪花格子,这是噪声引起的,因为我们的OTSU有这个缺点。所以全局阈值有缺点。
9.3.2 全局阈值优化(手动过滤)
全局阈值的上述问题可以通过下面这个方法解决,也可以通过局部阈值解决。以下方法就是把方差小于 某个数 然后直接覆盖为255或0. 这样就排除了噪声干扰(当然也有可能影响到一点点原图像)但肯定比原来要好很多。
9.3.3 局部阈值(可以解决噪声问题)
局部阈值方法中我们考虑了噪声的影响,下面方法我们设立的噪声范围在+-20内,但是全局阈值就没有考虑噪声,所以直接二值化会出现很多错误。
我们还输出了均值和方差,方差为0,均值都为255,说明这一块是空白图像。我们也可以当方差或者mean小于某个数时,直接把它给赋值为0. 这样就可以消除一些噪声产生的误差。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。