OpenCV与图像处理学习七——传统图像分割之阈值法(固定阈值、自适应阈值、大津阈值)

OpenCV与图像处理学习七——传统图像分割之阈值法(固定阈值、自适应阈值、大津阈值)

  • 一、固定阈值图像分割
    • 1.1 直方图双峰法
    • 1.2 OpenCV中的固定阈值分割
  • 二、自动阈值图像分割
    • 2.1 自适应阈值法
    • 2.2 迭代法阈值分割
    • 2.3 Otsu大津阈值法

前面的笔记介绍了一些OpenCV基本的图像处理,后面将学习使用OpenCV的传统的图像分割方法,这次笔记的内容是阈值法进行图像分割。

图像分割是指将图像分成若干具有相似性质的区域的过程,主要有基于阈值、基于区域、基于边缘、基于聚类、基于图论和基于深度学习的图像分割方法等。图像分割分为语义分割实例分割。下图是一个实例分割的例子,与语义分割不同的地方在于,它能将同类别的物体的每个个体都区分开,如下图中每个人的轮廓都被分割开:

在这里插入图片描述
分割的原则就是使划分后的子图在内部保持相似度最大,而子图之间的相似度最小,将G = (V, E) 分成两个子集A,B,使得:
在这里插入图片描述
在这里插入图片描述

一、固定阈值图像分割

即设定一个固定的阈值,整张图片的每个像素的像素值都与该值进行比较,若小于该阈值则将像素值改为一个固定的值(常用0),若大于该阈值则将像素值改为另一个固定的值(常用255),则可以将图像进行二值分割,得到一张二值图。

1.1 直方图双峰法

六十年代中期提出的直方图双峰法(也称mode法)是典型的全局单阈值分割方法。
在这里插入图片描述
基本思想:假设图像中有明显的目标和背景,则其灰度直方图呈双峰分布,当灰度级直方图具有双峰特性时选取两峰之间的谷对应的灰度级作为阈值,大于阈值的作为前景,小于的作为背景。

缺点:对图像的要求太高,很多图像的直方图并不满足双峰的分布。

1.2 OpenCV中的固定阈值分割

在OpenCV中的函数:

retval, dst	= cv2.threshold( src, thresh, maxval, type[, dst] )

参数:

  1. src:输入图像,单通道或四通道图像。
  2. thresh:设定的固定阈值。
  3. maxval:当type参数设置为THRESH_BINARY时,表示像素值大于阈值时设置的值,或设置为THRESH_BINARY_INV时,表示像素值小于阈值时设置的值。
  4. type:阈值类型,如下图所示,前五种类型是基本类型,最后两种(大津阈值和三角形阈值)与前面的基本类型结合可以实现特殊的阈值分割:在这里插入图片描述

这里也需要注意一下这个函数的输出:

  1. retval:第一个参数返回的是阈值,在使用五种基本类型时就等于你设置的阈值,而在使用大津阈值法和三角形阈值法时将会得到它计算出来的阈值,一般用的不多。
  2. dst:第二个参数返回的才是分割之后的图像。

下面看几个例子:

# 加载opencv和matplotlib
import cv2
import matplotlib.pyplot as plt# 灰度图读入
img = cv2.imread('./image/thresh.png', 0)
threshold = 127
# 阈值分割
ret, th = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
print(ret)cv2.imshow('Original', img)
cv2.imshow('thresh', th)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:
在这里插入图片描述
返回的第一个参数就是设置的阈值:

127.0

即像素值低于127的都被赋予0,高于的都被赋予255,得到一张二值化的图像。

再来看一下五种基本的阈值分割方法的区别

# 导入第三方包
import cv2
from matplotlib import pyplot as plt
# opencv读取图像
img = cv2.imread('./image/person.png',0)
# 5种阈值法图像分割
ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret2, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret3, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret4, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret5, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
# 使用for循环进行遍历,matplotlib进行显示
for i in range(6):plt.subplot(2, 3, i+1)plt.imshow(images[i], cmap='gray')plt.xticks([])plt.yticks([])plt.suptitle('fixed threshold')
plt.show()

结果为:
在这里插入图片描述
注意:除了前两种方法是二值化图像,后三种并不是,因为它们会保留一部分的原像素值。

如果这个图不够直观,将输入图像换成上一个例子里的渐变灰度图,结果如下:
在这里插入图片描述

二、自动阈值图像分割

2.1 自适应阈值法

很明显,设置一个固定阈值对全局像素进行分割是不合理的,如果这张图片的光照角度不好,一边比较亮一边比较暗,但是我们想分割图里的细节,只用一个固定阈值的话很可能会出现下面的结果:
在这里插入图片描述
而自适应阈值分割则将图像分成很多个小块(region),对每个小块单独计算其阈值,然后用这个计算得到的阈值对该小块进行分割,这样的好处是,即使受到光照影响,某一块较暗或较亮,但是可以单独计算这一块的合理阈值来进行分割而不用使用全局的固定阈值,换句话说,亮的小块对应的阈值较大,暗的小块对应的阈值较小,从而可以达到很好的分割效果。

函数:

dst	= cv2.adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]	)

参数:

  1. src:输入图像,只能是单通道灰度图。
  2. maxValue:最大阈值,即小块计算的阈值不能超过这个值,一般设置为255.
  3. adaptiveMethod:计算小块阈值的方法,包括cv2.ADAPTIVE_THRESH_MEAN_Ccv.ADAPTIVE_THRESH_GAUSSIAN_C,即求小块内的均值或高斯加权求和:在这里插入图片描述
  4. thresholdType:阈值方法,这里只能是THRESH_BINARYTHRESH_BINARY_INV,即在这里插入图片描述
  5. blockSize:小块的尺寸,如11就是11×11。
  6. C:最终阈值等于小区域计算出的阈值再减去这个常数。

看一下刚刚用固定阈值分割效果很差的那个图用自适应阈值来分割的效果:

# 自适应阈值与固定阈值对比
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('./image/paper2.png', 0)# 固定阈值
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 4)
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 4)
# 全局阈值,均值自适应,高斯加权自适应对比
titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, th1, th2, th3]
for i in range(4):plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')plt.title(titles[i], fontsize=8)plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
可以看出效果还是很好的,相比之下,高斯方法的自适应阈值能获得更好的效果,其噪点更少。

2.2 迭代法阈值分割

步骤:

  1. 求出图像的最大灰度值和最小灰度值,分别记为Zmax和Zmin,另初始阈值为T0 = (Zmax + Zmin) / 2。
  2. 根据阈值Tk将图像分割为前景和背景,分别求出两者的平均灰度值Zo和Zb。
  3. 求出新的阈值Tk+1 = (Zo + Zb) / 2。
  4. 若Tk == Tk+1,则即为所求的阈值,否则转到步骤2继续迭代。
  5. 使用计算后的阈值进行阈值分割。

其实迭代法就是将固定阈值分割里手动给定阈值改为了迭代计算阈值,可以适用的范围更多一些,但是本质还是固定阈值变换

看个例子:

import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cmdef best_thresh(img):# step 1: 设置初始阈值img_array = np.array(img).astype(np.float32)    # 转化成数组I = img_arrayzmax = np.max(I)zmin = np.min(I)tk = (zmax+zmin)/2# step 2: 根据阈值将图像进行分割为前景和背景,分别求出两者的平均灰度zo和zbb = 1m, n = I.shape;while b == 0:ifg = 0ibg = 0fnum = 0bnum = 0for i in range(1, m):for j in range(1, n):tmp = I(i, j)if tmp >= tk:ifg = ifg + 1fnum = fnum + int(tmp)  # 前景像素的个数以及像素值的总和else:ibg = ibg+1bnum = bnum + int(tmp)  # 背景像素的个数以及像素值的总和# step 3: 计算前景和背景的新平均值zo = int(fnum / ifg)zb = int(bnum / ibg)# step 4: 比较tk是否等于新平均值if tk == int((zo+zb) / 2):b = 0else:tk = int((zo+zb)/2)# step 5: 返回的就是迭代计算后的阈值return tkimg = cv2.imread("./image/bird.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img = cv2.resize(gray, (200, 200))  # 大小
yvzhi = best_thresh(img)
ret1, th1 = cv2.threshold(img, yvzhi, 255, cv2.THRESH_BINARY)
print(ret1)
plt.imshow(th1, cmap=cm.gray)
plt.show()

结果为:
在这里插入图片描述

2.3 Otsu大津阈值法

大津法:也叫最大类间方差法,1979年日本学者大津提出,是一种基于全局阈值的自适应方法。

图像分为前景和背景,当取最佳阈值时,两部分之间的差别应该是最大的,衡量差别的方法为最大类间方差。

直方图有两个峰值的图像,用大津法求得的阈值近似为谷底,如下图所示,即代替了手动输入阈值。
在这里插入图片描述
大津法中类间方差是需要最大化的目标函数,那么它的定义如下图所示:
在这里插入图片描述
在OpenCV中大津阈值法只是在固定阈值法的函数cv2.threshold的阈值方法type这个参数后加上cv2.THRESH_OTSU,同时将参数2thresh忽视(设置多少无所谓,一般使用0),例如:

ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

看一个例子:

import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./image/noisy.png', 0)
# 固定阈值法
ret1, th1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
# Otsu阈值法
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 先进行高斯滤波,再使用Otsu阈值法
blur = cv2.GaussianBlur(img, (5, 5), 0)
ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
images = [img, 0, th1, img, 0, th2, blur, 0, th3]
titles = ['Original', 'Histogram', 'Global(v=100)','Original', 'Histogram', "Otsu's",'Gaussian filtered Image', 'Histogram', "Otsu's"]for i in range(3):# 绘制原图plt.subplot(3, 3, i * 3 + 1)plt.imshow(images[i * 3], 'gray')plt.title(titles[i * 3], fontsize=8)plt.xticks([]), plt.yticks([])# 绘制直方图plt.hist, ravel函数将数组降成一维plt.subplot(3, 3, i * 3 + 2)plt.hist(images[i * 3].ravel(), 256)plt.title(titles[i * 3 + 1], fontsize=8)plt.xticks([]), plt.yticks([])# 绘制阈值图plt.subplot(3, 3, i * 3 + 3)plt.imshow(images[i * 3 + 2], 'gray')plt.title(titles[i * 3 + 2], fontsize=8)plt.xticks([]), plt.yticks([])
plt.show()

这里比较了固定阈值法、大津阈值法和加上高斯滤波的大津阈值法,效果如下所示:
在这里插入图片描述
相比之下,高斯滤波加大津阈值法的效果是最好的,也是实际使用中最常用的。

以上就是基于阈值的传统图像分割中常用的几种阈值分割方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491625.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Foxmail 绑定企业邮箱

转载于:https://www.cnblogs.com/wu628/p/4955017.html

边缘计算将吞掉云计算!

来源:CSDN以下为译文:边缘计算已成为物联网的重要趋势。高德纳咨询公司认为边缘计算是2019年的一项技术趋势。各个物联网公司发现在将数据发送到云之前,通过边缘计算处理数据有很大的好处。最近Micron/Forrester的调查证实了这一趋势&#xf…

OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)

OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)一、图像梯度1.1 梯度1.2 图像梯度二、梯度图与梯度算子2.1模板卷积2.2 梯度图2.3 梯度算子2.3.1 Roberts交叉算子2.3.2 Prewitt算子2.3.3 Sobel算子三、Canny边缘检测算法(代码实现&a…

面向人工智能的计算机体系结构

来源:计算机研究与发展前 言近几年来人工智能技术的飞速发展使得其应用迅猛扩大,而传统的计算机体系结构对于面向人工智能的应用在处理速度、能耗、使用的方便性等方面有着诸多不足。随着人工智能应用的发展,面向人工智能的体系结构成为体系结…

OpenCV与图像处理学习九——连通区域分析算法(含代码)

OpenCV与图像处理学习九——连通区域分析算法(含代码)一、连通区域概要二、Two-Pass算法三、代码实现一、连通区域概要 连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域&#x…

(180页PPT)|清华大学孙富春教授深度讲解: 人工智能技术与产业发展

来源:精智工厂[导读】本文是清华大学孙富春教授在机械工业出版社讲座交流PPT,孙教授从背景与历史、深度学习、脑认知、产业(装备)发展、发展趋势等五个方面详细解读了人工智能技术与产业发展。未来智能实验室是人工智能学家与科学…

OpenCV与图像处理学习十——区域生长算法(含代码)

OpenCV与图像处理学习十——区域生长算法(含代码)一、区域生长算法概要二、区域生长算法原理三、代码应用一、区域生长算法概要 区域生长是一种串行区域分割的图像分割方法。区域生长是指从某个像素出发,按照一定的准则,逐步加入…

FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated

使用scipy模块时出现警告:FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use arr[tuple(seq)] instead of arr[seq]. In the future this will be interpreted as an array index, arr[np.array(seq)], which will resu…

一文看懂中国MEMS传感器产业链

来源:通信产业网物联网对促进我国经济发展、优化产业结构具有重大的战略意义。而在整个物联网生态中,MEMS传感器扮演着越来越重要的角色,在即将到来的智能物联网时代中将起到核心作用,为新科技产品提供更智能、更敏锐的感知能力。…

OpenCV与图像处理学习十一——分水岭算法(含代码)

OpenCV与图像处理学习十一——分水岭算法(含代码)一、分水岭算法概要二、分水岭算法步骤三、代码应用一、分水岭算法概要 任意的灰度图像可以被看做是地质学表面,高亮度的地方是山峰,低亮度的地方是山谷。 给每个孤立的山谷&…

10件5G能实现但4G不能做的事情

来源:雷锋网 5G的一些最佳用途可能还没有被发现,但下面是我们已经知道的十个令人兴奋的用途。雷锋网按;2019年6月6日,工信部正式向中国电信、中国移动、中国联通、中国广电发放5G商用牌照,这表明中国正式进入了5G商用的…

OpenCV与图像处理学习十二——图像形状特征之HOG特征

OpenCV与图像处理学习十二——图像形状特征之HOG特征一、图像特征理解1.1 颜色特征1.2 纹理特征1.3 形状特征1.4 空间关系特征二、形状特征描述2.1 HOG特征2.1.1 基本概念2.1.2 HOG实现过程2.1.3 代码实现前面介绍了图像的基础知识、基本处理方法以及传统图像分割的应用&#x…

深度解读:5G正式发牌,国内通信市场冷暖预判

来源:ICT解读者2019年6月6日,工业和信息化部向中国电信、中国移动、中国联通和中国广电正式颁发5G牌照,批准四家企业经营“第五代数字蜂窝移动通信业务”。这标志着我国正式进入5G商用元年。一石激起千层浪,相较于此前各运营商官方…

OpenCV与图像处理学习十三——Harris角点检测(含代码)

OpenCV与图像处理学习十三——Harris角点检测(含代码)一、角点的概念二、Harris角点检测的实现过程三、Harris代码应用一、角点的概念 角点: 在现实世界中, 角点对应于物体的拐角, 道路的十字路口、 丁字路口等。 从…

德勤发布《中国智能制造分析报告》

来源:CIO俱乐部亚洲正受到自动化、智能化大潮冲击。国际劳工组织调研发现,越南、柬埔寨、菲律宾和印度尼西亚的工人的失业风险最高,据估计这几个区域约50%的工人工作可能在未来20年被自动化取代。亚洲尤其是中国作为制造业的重要区域&#xf…

OpenCV与图像处理学习十四——SIFT特征(含代码)

OpenCV与图像处理学习十四——SIFT特征(含代码)一、SIFT算法二、SIFT实现过程三、代码实现一、SIFT算法 SIFT, 即尺度不变特征变换算法(Scale-invariant feature transform,SIFT) , 是用于图像…

液态大脑与固态大脑——圣塔菲最新群体智能文集

来源:The Royal society撰文 | Ricard Sol, Melanie Moses, and Stephanie Forrest大脑,神经元构成的器官根植于许多生物体内。这是一种固态的大脑,且组成它们的元素在空间中相对固定。但是相对的,大脑是否可以拥有流动不定的存在…

OpenCV与图像处理学习十五——LBP纹理特征(含代码)

OpenCV与图像处理学习十五——LBP纹理特征(含代码)一、LBP介绍二、LBP原理三、代码应用一、LBP介绍 LBP(Local Binary Pattern, 局部二值模式) , 是一种用来描述图像局部纹理特征的算子; 它具有…

pycharm运行程序时看不到任何结果显示

原因是用程序选择了console来运行,取消console方法如下: Run->Edit Configurations 取消run with python console的勾

iOS 的 XMPPFramework 简介

XMPPFramework是一个OS X/iOS平台的开源项目,使用Objective-C实现了XMPP协议(RFC-3920),同时还提供了用于读写XML的工具,大大简化了基于XMPP的通信应用的开发。 1. 登录和好友上下线 1.1XMPP中常用对象们 XMPPStream&a…