图像处理里的阈值

2018-10-30 22:19:36 Eastmount 阅读数 8396

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~

该系列在github所有源代码:https://github.com/eastmountyxz/ImageProcessing-Python
PS:请求帮忙点个Star,哈哈,第一次使用Github,以后会分享更多代码,一起加油。

同时推荐作者的C++图像系列知识:
[数字图像处理] 一.MFC详解显示BMP格式图片
[数字图像处理] 二.MFC单文档分割窗口显示图片
[数字图像处理] 三.MFC实现图像灰度、采样和量化功能详解
[数字图像处理] 四.MFC对话框绘制灰度直方图
[数字图像处理] 五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理详解
[数字图像处理] 六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解
[数字图像处理] 七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

前文参考:
[Python图像处理] 一.图像处理基础知识及OpenCV入门函数
[Python图像处理] 二.OpenCV+Numpy库读取与修改像素
[Python图像处理] 三.获取图像属性、兴趣ROI区域及通道处理
[Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
[Python图像处理] 五.图像融合、加法运算及图像类型转换
[Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移

本篇文章主要讲解Python调用OpenCV实现图像阈值化处理操作,包括二进制阈值化、反二进制阈值化、截断阈值化、反阈值化为0、阈值化为0。全文均是基础知识,希望对您有所帮助。
1.阈值化
2.二进制阈值化
3.反二进制阈值化
4.截断阈值化
5.反阈值化为0
6.阈值化为0

PS:文章参考自己以前系列图像处理文章及OpenCV库函数,同时部分参考网易云视频,推荐大家去学习。同时,本篇文章涉及到《计算机图形学》基础知识,请大家下来补充。

PSS:2019年1~2月作者参加了CSDN2018年博客评选,希望您能投出宝贵的一票。我是59号,Eastmount,杨秀璋。投票地址:https://bss.csdn.net/m/topic/blog_star2018/index

五年来写了314篇博客,12个专栏,是真的热爱分享,热爱CSDN这个平台,也想帮助更多的人,专栏包括Python、数据挖掘、网络爬虫、图像处理、C#、Android等。现在也当了两年老师,更是觉得有义务教好每一个学生,让贵州学子好好写点代码,学点技术,"师者,传到授业解惑也",提前祝大家新年快乐。2019我们携手共进,为爱而生。

一. 阈值化

(注:该部分参考作者的论文《基于苗族服饰的图像锐化和边缘提取技术研究》)

图像的二值化或阈值化(Binarization)旨在提取图像中的目标物体,将背景以及噪声区分开来。通常会设定一个阈值T,通过T将图像的像素划分为两类:大于T的像素群和小于T的像素群。
灰度转换处理后的图像中,每个像素都只有一个灰度值,其大小表示明暗程度。二值化处理可以将图像中的像素划分为两类颜色,常用的二值化算法如公式1所示:

{Y=0gray<TY=255gray>=T\begin{cases} Y=0,gray<T\\ Y=255,gray>=T\\ \end{cases}
当灰度Gray小于阈值T时,其像素设置为0,表示黑色;当灰度Gray大于或等于阈值T时,其Y值为255,表示白色。
Python OpenCV中提供了阈值函数threshold()实现二值化处理,其公式及参数如下图所示:
retval, dst = cv2.threshold(src, thresh, maxval, type)

常用的方法如下表所示,其中函数中的参数Gray表示灰度图,参数127表示对像素值进行分类的阈值,参数255表示像素值高于阈值时应该被赋予的新像素值,最后一个参数对应不同的阈值处理方法。
对应OpenCV提供的五张图如下所示,第一张为原图,后面依次为:二进制阈值化、反二进制阈值化、截断阈值化、反阈值化为0、阈值化为0。
二值化处理广泛应用于各行各业,比如生物学中的细胞图分割、交通领域的车牌设别等。在文化应用领域中,通过二值化处理将所需民族文物图像转换为黑白两色图,从而为后面的图像识别提供更好的支撑作用。下图表示图像经过各种二值化处理算法后的结果,其中“BINARY”是最常见的黑白两色处理。


二. 二进制阈值化

该方法先要选定一个特定的阈值量,比如127。新的阈值产生规则如下:
dst(x,y)={maxValifsrc(x,y)>thresh0otherwise dst(x,y) = \begin{cases} maxVal, if src(x,y)>thresh\\ 0,otherwise\\ \end{cases}
(1) 大于等于127的像素点的灰度值设定为最大值(如8位灰度值最大为255)
(2) 灰度值小于127的像素点的灰度值设定为0
例如,163->255,86->0,102->0,201->255。

关键字为 cv2.THRESH_BINARY,完整代码如下:

#encoding:utf-8
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('test.jpg')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#二进制阈值化处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY)
print r

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出为两个返回值,r为127,b为处理结果(大于127设置为255,小于设置为0)。如下图所示:



三. 反二进制阈值化

该方法与二进制阈值化方法相似,先要选定一个特定的灰度值作为阈值,比如127。新的阈值产生规则如下:
dst(x,y)={0ifsrc(x,y)>threshmaxValotherwise dst(x,y) = \begin{cases} 0, if src(x,y)>thresh\\ maxVal,otherwise\\ \end{cases}
(1) 大于127的像素点的灰度值设定为0(以8位灰度图为例)
(2) 小于该阈值的灰度值设定为255
例如,163->0,86->255,102->255,201->0。

关键字为 cv2.THRESH_BINARY_INV,完整代码如下:

#encoding:utf-8
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('test.jpg')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#反二进制阈值化处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY_INV)
print r

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下图所示:

该方法得到的结果正好与二进制阈值化方法相反,亮色元素反而处理为黑色,暗色处理为白色。

四. 截断阈值化

该方法需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变,比如127。新的阈值产生规则如下:
dst(x,y)={thresholdifsrc(x,y)>threshsrc(x,y)otherwise dst(x,y) = \begin{cases} threshold, if src(x,y)>thresh\\ src(x,y),otherwise\\ \end{cases}
(1) 大于等于127的像素点的灰度值设定为该阈值127
(2) 小于该阈值的灰度值不改变
例如,163->127,86->86,102->102,201->127。

关键字为 cv2.THRESH_TRUNC,完整代码如下:

#encoding:utf-8
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('test.jpg')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#截断阈值化处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TRUNC)
print r

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下图所示::

该处理方法相当于把图像中比较亮(大于127,偏向于白色)的像素值处理为阈值。

五. 反阈值化为0

该方法先选定一个阈值,比如127,接着对图像的灰度值进行如下处理:
dst(x,y)={0ifsrc(x,y)>threshsrc(x,y)otherwise dst(x,y) = \begin{cases} 0, if src(x,y)>thresh\\ src(x,y),otherwise\\ \end{cases}
(1) 大于等于阈值127的像素点变为0
(2) 小于该阈值的像素点值保持不变
例如,163->0,86->86,102->102,201->0。

关键字为 cv2.THRESH_TOZERO_INV,完整代码如下:

#encoding:utf-8
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('test.jpg')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#反阈值化为0处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO_INV)
print r

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下图所示:



六. 阈值化为0

该方法先选定一个阈值,比如127,接着对图像的灰度值进行如下处理:
dst(x,y)={src(x,y)ifsrc(x,y)>thresh0otherwise dst(x,y) = \begin{cases} src(x,y), if src(x,y)>thresh\\ 0,otherwise\\ \end{cases}
(1) 大于等于阈值127的像素点,值保持不变
(2) 小于该阈值的像素点值设置为0
例如,163->163,86->0,102->0,201->201。

关键字为 cv2.THRESH_TOZERO,完整代码如下:

#encoding:utf-8
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('test.jpg')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#阈值化为0处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO)
print r

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下图所示:

该算法把比较亮的部分不变,比较暗的部分处理为0。

完整五个算法的对比代码如下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取图像
img=cv2.imread('test.jpg')
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  

#阈值化处理
ret,thresh1=cv2.threshold(GrayImage,127,255,cv2.THRESH_BINARY)  
ret,thresh2=cv2.threshold(GrayImage,127,255,cv2.THRESH_BINARY_INV)  
ret,thresh3=cv2.threshold(GrayImage,127,255,cv2.THRESH_TRUNC)  
ret,thresh4=cv2.threshold(GrayImage,127,255,cv2.THRESH_TOZERO)  
ret,thresh5=cv2.threshold(GrayImage,127,255,cv2.THRESH_TOZERO_INV)

#显示结果
titles = ['Gray Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']  
images = [GrayImage, thresh1, thresh2, thresh3, thresh4, thresh5]  
for i in xrange(6):  
   plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()

输出结果如下图所示:

希望文章对大家有所帮助,如果有错误或不足之处,还请海涵。最近经历的事情太多,有喜有悲,关闭了朋友圈,希望通过不断学习和写文章来忘记烦劳,将忧郁转换为动力。哎,总感觉自己在感动这个世界,帮助所有人,而自己却…谁有关心秀璋?晚安。
(By:Eastmount 2018-10-30 晚上10点 https://blog.csdn.net/Eastmount/)

2018-12-02 10:55:25 shanwenkang 阅读数 3274

阈值

我们将图像分块最简单的方法就是设定一个阈值对图像进行二值化处理,那么这个阈值我们应该如何选择呢

对于图像的直方图存在明显边界的图像,我们可以很容易找到这个阈值,但是如果图像直方图分界不明显,那么这个阈值的寻找将变得十分困难。因此我们存在全局阈值与局部阈值两种

全局阈值

全局阈值就是在整幅图像中我们只有一个阈值来对图像进行二值化,但是其存在其局限性,例如图像中存在高斯噪声的情况下,我们无法找到一个很好的阈值将图像的边界分开

另外如果图像的边界是在局部对比下出现的,即不同位置阈值不同,那么全局阈值的效果也非常不好

我们先不管全局阈值的缺点,我们来看看我们如何通过计算来获得这个全局阈值T呢?我们又OTSU'S算法

下面是一些数学概念在图像上的体现

OTSU算法就是想把图像分为两个块,然后使得这两个块之间的方差最大,也就是最大化两个块的均值与全局均值的差的平方

由于只存在这么一个阈值,那么我们在计算的时候可以简单地让这个值遍历0-255,然后找到σB最大的值,这个值就是我们要的阈值。我们可以理解为这个值把图像分为了相距最远的两块。我们在matlab中有graythresh这个函数来实现这个过程

下图就显示了一个OTSU算法不是很理想的例子

为了克服以上缺点我们有两点解决方法:1.先通过低通滤波器去噪再用OTSU 2.只在考虑边缘部分的像素来计算阈值,这样可以大大减少其他不重要部分对阈值计算过程的影响

局部阈值

下面让我们来看看局部阈值/自适应阈值。它的原理就是将图像分块,对于不同的部分应用不同的阈值,在matlab中我们有blockproc这个函数来实现这个过程

我们看到相比于之前,效果确实有很大的提升,但是缺点也特别明显,就是图像会出现分块化

我们可以调小块的大小,但是这样的话会出现如果块内像素值变化不大的话,块内像素被全部分作黑或白而缺失了边界(例如右上角窗户的上方黑色的窗框内有白色的像素块)。因此块的选择是十分重要的

更好的方式是我们在每个像素周围的一个区域内来计算阈值,根据这个块内的均值方差来计算这个像素的值是1还是0

RGB图阈值

除了将阈值在灰度图上应用,我们还可以将其应用在RGB图中,我们可以设定一种颜色,来得到与这种颜色相近颜色的物体

例如我们取下图丝带的颜色可以得到如右图的结果

 

 

2018-12-23 13:18:06 lx_xin 阅读数 1980

基本概念

图像阈值分割是图像处理中最基本也是最常用的方法之一,主要用于将图像中的像素点划分为两个或者多个类别,从而得到便于处理的目标对象。

类别划分

按照阈值作用范围分:全局阈值分割,局部阈值分割;
按照阈值选取准则函数分:最大熵法,类间方差法,交叉熵法,最小误差法,模糊熵法;
按照阈值个数分:单阈值法和多阈值法;

2018-03-29 14:18:43 bjbz_cxy 阅读数 17245
的意思是界限,故阈值又叫临界值,是指一个效应能够产生的最低值或最高值。
在图像处理中它的意思是颜色转换的临界点,该方法只用于二值化的图像中
列如在自然中每一种颜色都有一个值,通常由RGB(即红、绿、蓝三原色)按比例混合就会得到各种不同的颜色。阈值处理图片是对颜色进行特殊处理的一种方法。
详细说,阈值是一个转换临界点,不管你的图片是什么样的彩色,它最终都会把图片当黑白图片处理,也就是说你设定了一个阈值之后,它会以此值作标准,凡是比该值大的颜色就会转换成白色,低于该值的颜色就转换成黑色,所以最后的结果是,你得到一张黑白的图片。

用阈值的作用:得到一张对比度不同的黑白图片

阈值可以是最小值:某一性能特征不能低于该值。
2019-05-22 17:39:49 weixin_44403952 阅读数 898

全局阈值

全局阈值就是在整个图像中将灰度阈值设置成一个常数,全局阈值适合如下场景:图像背景的灰度值在整个图像中可合理的看作恒定,而且所有物体和背景都具有几乎相同的对比度,反应在直方图上就是 具有明显的双峰。在此种情况下,只要选择合适的阈值,使用固定的全局阈值往往会有比较好的效果。全局阈值选择的主要方法有:人工选择法、直方图选择法、迭代式阈值选择法、最大类间方差阈值(Otsu)。
在OpenCV中图像的二值化分割采用的是 cv2.threshold(src, thresh, maxval, type, dst=None)

  • 第一个参数src: 原图像
  • 第二个参数thresh: 分类的阈值
  • 第三个参数 maxval:高于阈值时选取的新的值
  • 第四个参数maxval: 就是 上述介绍的几个方法选择参数
    常用的有:• cv2.THRESH_BINARY(黑白二值)
    • cv2.THRESH_BINARY_INV(黑白二值反转)
    • cv2.THRESH_TRUNC (得到的图像为多像素值)
    • cv2.THRESH_TOZERO
    • cv2.THRESH_TOZERO_INV
  • 返回值(2个):第一个 retVal: 得到的阈值,第二个 就是阈值化后的图像
import cv2
import numpy as np
img = cv2.imread("sources/lena_1.tiff",0)
from matplotlib import pyplot as plt

ret , thresh = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV )
#ret , thresh = cv2.threshold(img,127,255,cv2.THRESH_OTSU )
cv2.imshow("1",thresh)
cv2.waitKey(0)

自适应阈值

在很多情况下,背景的灰度值并不是常数,物体和背景的对比度在图像中是变化的,此时一个图像中某个区域效果良好的阈值在其他区域可能会效果很差。在这种情况下,需要把灰度阈值取为一个随图像中位置缓慢变化的函数值,也就是自适应阈值。
自适应阈值主要的方法就是将图像进一步划分为子图像,并对不同的子图像使用不同的阈值进行分割。此方法的关键问题就是如何将图像进行细分和如何为得到的子图像估计阈值。
自适应阈值的经典算法是: 分水岭算法,详情参考博文:https://blog.csdn.net/dcrmg/article/details/52498440
OpenCV的自适应阈值函数为:
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)

  • 第一个参数src: 原图像
  • 第二个参数maxVal: 像素的最大值
  • 第三个参数 adaptiveMethod(有两种方法):
    cv2.ADAPTIVE_THRESH_MEAN_C:邻域内均值
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C:邻域内像素点加权和,权重为一个高斯窗口
    第四个参数thresholdType:有 cv2.THRESH_BINARY、cv2.THRESH_BINARY_INV两个
    第五个参数Block Size:规定的邻域大小
    第六个参数 C:设置阈值为 (均值 - C) 或者是 (加权值 - C)

返回值: 只有一个,就是二值化后的图像

import cv2
import numpy as np
img = cv2.imread("sources/lena_1.tiff",0)
from matplotlib import pyplot as plt

thresh = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,10)

cv2.imshow("1",thresh)
cv2.waitKey(0)

- 显示效果
------ 全局阈值
图1
-----局部阈值自适应调整
图2

  • 分析
    最后两个参数,是用来调整子图像大小(子图像边长只能为奇数) 以及 局部子图像阈值自适应调整。这两个参数用来改善二值化的图像的质量。当子图像的大小调整到原图像大小时,该方法退化为 全局阈值调整。