OpenCV4图像处理--阈值分割之二值图

二值图与灰度图概念

PS:opencv 中二值图像是基于背景是黑色!!!!
在这里插入图片描述

阈值分割之二值分割

  • 五种阈值分割方法 : 输入图像 + 阈值T
    在这里插入图片描述
  • C++ API:threshold 注意这个 API 只能支持灰度图
CV_EXPORTS_W double threshold( InputArray src, OutputArray dst,
                               double thresh, double maxval, int type );
	//阈值分割(五种方式)
	Mat gray, binary;
	cvtColor(src, gray, COLOR_BGR2GRAY);//得到灰度图
	imshow("gray", gray);

	threshold(gray, binary, 127, 255, THRESH_BINARY);//这个 T = 127 暂时给定 不一定合理 后面分析怎么确定
	imshow("binary", binary);//二值分割

	threshold(gray, binary, 127, 255, THRESH_BINARY_INV);
	imshow("threshold binary invert", binary);

	threshold(gray, binary, 127, 255, THRESH_TRUNC);
	imshow("threshold TRUNC", binary);

	threshold(gray, binary, 127, 255, THRESH_TOZERO);
	imshow("threshold to zero", binary);

	threshold(gray, binary, 127, 255, THRESH_TOZERO_INV);
	imshow("threshold to zero invert", binary);

在这里插入图片描述

  • python API:cv2.threshold , 同样注意这个 API 输入图像为灰度图
    参数说明:第一个是原图像矩阵,第二个是进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数(分割方法),常用的有:
阈值模式有以下几种类型
0: THRESH_BINARY         -当前点值大于阈值时,取Maxval,否则设置为0
1: THRESH_BINARY_INV     -当前点值大于阈值时,设置为0,否则设置为Maxval
2: THRESH_TRUNC          -当前点值大于阈值时,设置为阈值,否则不改变
3: THRESH_TOZERO         -当前点值大于阈值时,不改变,否则设置为0
4: THRESH_TOZERO_INV     -当前点值大于阈值时,设置为0,否则不改变

这个函数返回两个值,第一个值为阈值,第二个就是阈值处理后的图像矩阵

import cv2

#读入图像并转为灰度图
img = cv2.imread('.\\images\\keji.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(img.shape)
cv2.imshow('img', img)

ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('binary', thresh1)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('binary_inv', thresh2)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
cv2.imshow('trunc', thresh3)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
cv2.imshow('tozero', thresh4)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow('tozero_inv', thresh5)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

  • 很明显,二值分割就是阈值分割中的一种,即THRESH_BINARY

获取阈值算法

前面对于阈值的设定上,我们选择的阈值都是127,在实际情况中,有的图像阈值不是127得到的图像效果更好。那么这里就需要算法自己去寻找一个阈值,那么怎么确定较好的阈值T呢,有很多计算阈值的算法!主要分为全局阈值自适应阈值

全局阈值

  • 全局阈值概念
    全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化!
  • 全局阈值分割方法: 均值法、 OTSU、 三角法(Triangle)

均值法:
在这里插入图片描述

	//C++ 实现 均值法全局阈值
	Scalar m = mean(gray);
	printf("means:%.2f\n", m[0]);//计算得到均值为120.88
	threshold(gray, binary, m[0], 255, THRESH_BINARY);
	imshow("binary", binary);

OTSU:

  • 相关概念:
    灰度直方图:将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。其实就是每个值(0~255)的像素点个数统计,如下图。
    在这里插入图片描述
    Otsu算法假设这副图片由前景色和背景色组成,通过最大类间方差选取一个阈值,将前景和背景尽可能分开。下图说明中,以2作为分割点计算类内方差,然后计算其他点作为分割点的方差,选择方差最小的作为阈值分割点。数学思想是:相当于对数据进行分类,分成两类,那么相似的东西他们之间的差异肯定小,那么基于类内最小方差之和作为分割点就很科学。基本上双峰图片的阈值T在两峰之间的谷底。
    在这里插入图片描述

三角法: 三角法介绍
在这里插入图片描述

  • c++ API:
    在这里插入图片描述
	//OTSU
	double t1 = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);//t1为otsu分割阈值
	printf("otsu threshold T:%.2f\n", t1);
	imshow("otsu binary", binary);

	//三角法 triangle
	double t2 = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);//t2为triangle分割阈值
	printf("triangle threshold T:%.2f\n", t2);
	imshow("triangle binary", binary);

在这里插入图片描述

  • python API
ret, thresh6 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # Otsu 滤波
print('T:', ret)
cv2.imshow('otsu', thresh6)

ret, thresh7 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)  # triangle 滤波
print('T:', ret)
cv2.imshow('triangle', thresh7)

在这里插入图片描述
PS:可以看出均值、otsu、triangle的各自效果,各自的阈值分别可以获取,其中 otsu 效果最好,因为otsu可以有效对抗多个峰的直方图阈值查找,三角法只有对单峰的图像效果较好!因此需要根据图像直方图的分布情况选择合适的方法,一般优先选择otsu,三角法主要应用于医学和生物中的比较单调的图像分割!

自适应阈值

  • 自适应阈值概念
    自适应阈值可以看成一种局部性的阈值,通过设定一个区域大小,比较这个点与区域大小里面像素点 的平均值(或者其他特征)的大小关系确定这个像素点的情况!全局阈值的局限就是对光照不均匀的图像容易错误分割,而自适应阈值可以改善这种缺点!
    在这里插入图片描述
  • 自适应阈值分割原理
    它的思想不是计算全局图像的阈值,而是根据图像不同区域亮度分布,计算其局部阈值,所以对于图像不同区域,能够自适应计算不同的阈值,因此被称为自适应阈值法。如何确定局部阈值呢?可以计算某个邻域(局部)的均值、中值、高斯加权平均(高斯滤波)来确定阈值。
    在这里插入图片描述
  • C++ API:adaptiveThreshold
CV_EXPORTS_W void adaptiveThreshold( InputArray src, OutputArray dst,
                                     double maxValue, int adaptiveMethod,
                                     int thresholdType, int blockSize, double C );
	//自适应阈值
	
	adaptiveThreshold(gray, binary, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 25, 10);
	imshow("ada-gaussian binary", binary);

	adaptiveThreshold(gray, binary, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 25, 10);
	imshow("ada-mean binary", binary);

在这里插入图片描述

  • python API

1 第一个参数为原始图像矩阵;
2 第二个参数为像素值上限;
3 第三个是自适应方法(adaptive method):
#                                              -----cv2.ADAPTIVE_THRESH_MEAN_C:领域内均值
#                                              -----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:领域内像素点加权和,权重为一个高斯窗口
4 第四个值的赋值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV
5 第五个Block size:设定领域大小(一个正方形的领域)
6 第六个参数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值,就是求得领域内均值或者加权值)
thresh8 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 25, 2)
cv2.imshow('addp mean', thresh8)

thresh9 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 2)
cv2.imshow('addp gauss', thresh9)

在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值