二值图像

news/2024/11/16 15:03:29/文章来源:https://www.cnblogs.com/Gaowaly/p/18327814

一、 二值图像概念

1. 二值图像含义
二值图像(Binary Image)是指将图像上的每一个像素只有两种可能的取值或灰度等级状态,人们经常用黑白、B&W、单色图像表示二值图像。

二值图像是指在图像中,灰度等级只有两种,也就是说,图像中的任何像素点的灰度值均为0或者255,分别代表黑色和白色。

2. 二值图像特点
1)数据量小;
2)处理速度快,成本低,实用性强;
3)能定义几何学的各种概念。
3. 二值图像优缺点
二值图像一般用来描述字符图像。
优点:占用空间少
缺点:当表示人物,风景的图像时,二值图像只能展示其边缘信息,图像内部的纹理特征表现不明显。这时候要使用纹理特征更为丰富的灰度图像。

4. 二值图像处理流程

二、二值图像的连接性和距离

1、邻域

对于任意像素(x,y),把像素的集合{(x+p,y+q)}(p、q是一对适当的整数)叫做像素(x,y)的邻域。即像素(x,y)附近的像素形成的区域。

邻域是指某像素p的周围像素,p与他们间的欧式距离不超过“根号2”即对角线的距离。如果q在p的某种邻域中,则p,q为某种邻接。

  • 1.1、 4-邻域

    即对于像素(x,y),上下左右4个像素称为4-邻域,即以下元素:(x-1,y)(x,y-1)(x+1,y)(x,y+1)。

  • 2.2、 D-邻域

    即对于像素(x,y),其中(max-1>x>1,max-1>y>1)。其D-邻域为以下元素:(x-1,y-1)(x+1,y-1)(x-1,y+1)(x+1,y+1)。

  • 3、 8-邻域

    即对于像素(x,y),其中(max-1>x>1,max-1>y>1),上下左右4个元素以及4个对角线像素,称为8-邻域。为以下元素:(x-1,y-1)(x-1,y)(x-1,y+1)(x,y-1)(x,y+1)(x+1,y-1)(x+1,y)(x+1,y+1)

2、 二值图像的邻接


4-邻接:如果q点在p点的4-邻域集合中,则p,q为4-邻接。即互为4-邻域的两个像素叫4-邻接。


8-邻接:如果q点在p点的8-邻域集合中,则p,q为8-邻接。即互为8-邻域的两个像素叫8-邻接。


D-邻接:如果q点在p点的D-邻域集合中,则p,q为D-邻接


m-邻接:如果q在p的4-邻域中,或者q在p的D-邻域中,且q的4-邻域与p的4-邻域交集为空,则p,q为m-邻接。


ლ(′◉❥◉`ლ)
m邻域的目的是消除8-邻域的二义性。

二义性


在某种情况下,如果邻域中存在多种通路。

某点1到点3存在两种通路,1->p->3,1->p->2->3。所以点1和点3关系不明确。如果使用m邻接,点3将不会是点p的m-邻接,因为点p和点3的4-邻域存在交集点2。

3、连通性

对于集合S存在一条通路的条件是,通路的像素的某种排列,相邻像素满足某种邻接关系。例如点p到点q之间有A1,A2,A3…An个像素点,且相邻像素点都满足某种邻接。则p和q之间存在通路。如果通路首尾相连,则称闭合通路。S集合中的一点p只存在一条通路,则称为一个连通分量,如果S只有一个连通分量,则称为一个连通集。

对于R为一个图像子集,如果R连通的,则称R为一个区域。对于所有不连接的K个区域,其并集Rk构成了图像的前景,Rk的补集称为背景。

4、像素的连接

在二值图像中,具有两个相同数值的像素a 1 a_1a1a 2 a_2a2,若所有与它们具有相同值的像素,能够在4-/8-邻域内构成一个从a 1 a_1a1a 2 a_2a2的邻接的像素序列,则我们把像素a 1 a_1a1a 2 a_2a2叫做4-/8-连接。其像素序列叫4-/8-路径。

5、连接成分

 

 

在研究一个二值图像连接成分的场合,若1像素的连接成分用4-/8-连接,而0像素连接成分 ,不用相反的8-/4-连接就会产生矛盾。在下图中,如果假设各个1像素用8一连接,因此0像素和1像素应采用互反的连接形式。

 

三、差异

  1. 二值图像(binary image),即图像上的每一个像素只有两种可能的取值或灰度等级状态,人们经常用黑白、B&W、单色图像表示二值图像。
  2. 灰度图像(gray image) 是每个像素只有一个采样颜色的图像,这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;但是,灰度图像在黑色与白色之间还有许多级的颜色深度。灰度图像经常是在单个电磁波频谱如可见光内测量每个像素的亮度得到的,用于显示的灰度图像通常用每个采样像素8位的非线性尺度来保存,这样可以有256级灰度(如果用16位,则有65536级)。
  3. 彩色图像 ,每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,分量介于(0,255)。 (cmyk:分别是由兰、洋红、黄和黑色四个分量来表示的)

四、图像二值化

图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

要得到二值化图像,首先要把图像灰度化,然后将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。

2. 图像二值化方法及Python实现

比较常用的二值化方法有:简单二值法,平均值法,双峰法和OTSU法等。

2.1 简单二值法

将图像灰度化后,我们选择127(灰度值范围的一半)作为阈值,即将像素值大于127的像素值全部设为255,小于127的全部设为0。

def Easy_Binarization(srcImg_path):img = cv.imread(srcImg_path)img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)img_gray[img_gray>127] = 255img_gray[img_gray<=127] = 0plt.imshow(img_gray, cmap='gray')plt.title('Easy_Binarization')plt.show()

 

2.2 平均值法

为了应对每张图片的灰度值大不相同,阈值取为图像本身的平均值。

def Mean_Binarization(srcImg_path):img = cv.imread(srcImg_path)img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)threshold = np.mean(img_gray)print(threshold)img_gray[img_gray>threshold] = 255img_gray[img_gray<=threshold] = 0plt.imshow(img_gray, cmap='gray')plt.title('Mean_Binarization')plt.show()

 实验中该方法计算的阈值为123。

2.3 双峰法

直方图是图像的重要特质,它可以帮助我们分析图像中的灰度变化。因此,如果物体与背景的灰度值对比明显,直方图就会包含双峰,它们分别为图像的前景和背景,而它们之间的谷底即为边缘附近相对较少数目的像素点,一般来讲,这个最小值就为最优二值化的分界点,通过这个点可以把前景和背景很好地分开。

def Hist_Binarization(srcImg_path):img = cv.imread(srcImg_path)img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)hist = img_gray.flatten()plt.subplot(121)plt.hist(hist,256)cnt_hist = Counter(hist)print(cnt_hist)begin,end = cnt_hist.most_common(2)[0][0],cnt_hist.most_common(2)[1][0]if begin > end:begin, end = end, beginprint(f'{begin}: {end}')cnt = np.iinfo(np.int16).maxthreshold = 0for i in range(begin,end+1):if cnt_hist[i]<cnt:cnt = cnt_hist[i]threshold = iprint(f'{threshold}: {cnt}')img_gray[img_gray>threshold] = 255img_gray[img_gray<=threshold] = 0plt.subplot(122)plt.imshow(img_gray, cmap='gray')plt.show()

 

实验中该方法得到的双峰为(145,154),阈值为150。

2.4 OTSU法

双峰法具有明显的缺陷,因为直方图是不连续的,有非常多尖峰和抖动,要找到准确的极值点十分困难。日本工程师大津展之为这个波谷找到了一个合适的数学表达,并于1979年发表。这个二值化方法称为大津算法(Otsu’s method)。

OTSU法也称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致类间差别变小。因此,使类间方差最大的分割意味着错分概率最小。

具体计算阈值方法如下:
设阈值为t, 将原图转化成灰度图后,将其高与宽存于h,w,并将小于阈值的灰度值存储在前景front中,大于等于阈值的存在背景back中。如下所示:

# 阈值:t
h, w = img.shape[:2]
front = img[img < t]
back = img[img >= t]

显然,前景与背景的长度和应与h, w的乘积相等,即:

len(front) + len(back) == h * w.

设前景像素数量占总像素数量的比重为frontP,背景像素数量占总像素数量的比重为backP,前景和背景的灰度平均值分别为frontMean和backMean,总平均灰度值为m,则方差公式可写成:

 又因为:

 上式可化简为:

 实验代码如下:

def Otsu(srcImg_path):img = cv.imread(srcImg_path)img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)h, w = img.shape[:2]threshold_t = 0max_g = 0for t in range(255):front = img[img < t]back = img[img >= t]front_p = len(front) / (h * w)back_p = len(back) / (h * w)front_mean = np.mean(front) if len(front) > 0 else 0.back_mean = np.mean(back) if len(back) > 0 else 0.g = front_p * back_p * ((front_mean - back_mean)**2)if g > max_g:max_g = gthreshold_t = tprint(f"threshold = {threshold_t}")img[img < threshold_t] = 0img[img >= threshold_t] = 255plt.imshow(img, cmap='gray')plt.title('Otsu')plt.show()

二值化图像如下:

 

对比以上四种方法可以发现,Otsu方法得到的二值化图像细节更多,图像更细腻。

3. opencv-python中二值化方法的应用

在OpenCV中,分为简单的阈值分割与自适应阈值分割。

3.1 简单阈值分割(Simple Thresholding)

函数原型如下:

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

参数说明:
第一个参数src为原图,需要注意的是输入的图像需为灰度图。
第二个参数thresh即为阈值,用于对像素值的分类(一般定义为127)。
第三个参数maxval是最大值,即超过阈值后所定义的值(255)。
第四个参数type,在Simple Thresholding中一共有五种不同的方式: cv.THRESH_BINARY、cv.THRESH_BINARY_INV 、cv.THRESH_TRUNC 、cv.THRESH_TOZERO、cv.THRESH_TOZERO_INV

测试代码如下:

img = cv.imread('lenna.jpg')
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
ret,thresh1 = cv.threshold(img_gray,127,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img_gray,127,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img_gray,127,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img_gray,127,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img_gray,127,255,cv.THRESH_TOZERO_INV)titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]for i in range(6):plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')plt.title(titles[i])plt.axis('off')
plt.show()

下图是5种方式的实际效果:

3.2 自适应阈值分割(Adaptive Thresholding)

函数原型如下:

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

其中src, maxValue和thresholdType与Simple Thresholding相同。

在自适应阈值分割中,adaptive method(阈值的计算方式)有两种:

  • cv.ADAPTIVE_THRESH_MEAN_C: 邻域面积(blockSize * blockSize)的平均值并减去C.
  • cv.ADAPTIVE_THRESH_GAUSSIAN_C: 邻域面积的高斯加权总和然后减去C.

下面是它们的实际效果(对于thresholdType在这里选择cv.THRESH_BINARY),测试代码如下:

img = cv.imread('lenna.jpg')
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
ret,th1 = cv.threshold(img_gray,127,255,cv.THRESH_BINARY)
th2 = cv.adaptiveThreshold(img_gray,255,cv.ADAPTIVE_THRESH_MEAN_C,\cv.THRESH_BINARY,11,2)
th3 = cv.adaptiveThreshold(img_gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\cv.THRESH_BINARY,11,2)titles = ['Original Image', 'Simple Thresholding','Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
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])plt.axis('off')
plt.show()

效果如下:

 

发现没有像之前otsu那样输出一张类似的图片,但是,它将图像中的边框描绘了出来,实际应用中这样的方式更适合处理文字形式的图片。

4. 源码仓库地址

🌼图像处理、机器学习的常用算法汇总

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

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

相关文章

17、flask-图书简单馆项目

为了掌握模型可以练一下、以下是代码: app.py from App import create_appapp = create_app()if __name__ == __main__:app.run(debug=True)views.py from flask import Blueprint, render_template from datetime import datetime from .models import *#创建蓝图(路由) bl…

全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型

本文主要介绍了在使用Python面向对象编程时,如何使用type函数、isinstance函数和正则表达式三种方法判断用户输入数据类型,并对相关语法进行介绍。全网最适合入门的面向对象编程教程:25 类和对象的 Python 实现-Python 判断输入数据类型摘要: 本文主要介绍了在使用 Python …

[数据结构] 堆与堆排序

本文介绍了堆这种数据结构的性质,以及堆排序算法,最后介绍了堆的相关应用场景。这篇文章使用 JavaScript 语言进行相关代码的编写。数据结构——堆 heap 基本概念与性质 堆是一颗完全二叉树,根据父子节点之间值的大小关系可以分为:大根堆:每一个节点的值 大于或等于 其子节…

详解 Hough 变换(基本原理与直线检测)

Hough 变换原理与应用前言: 详细介绍了 Hough 变换的基本思想、基本原理和应用等。其中大多都是自己的理解,难免有偏差,仅供参考。文章目录Hough 变换原理与应用1. 基本概述1.1 一些基本问题 1.2 以例子说明1.2.1 例子1:直线 y = k x + b y = kx + by=kx+b​​​​​​​ 到…

致远AnalyticsCloud分析云任意文件读取漏洞复现

产品界面图:FOFA:"AnalyticsCloud分析云"GET请求payload即可读取文件内容paylaod: /.%252e/.%252e/c:/windows/win.ini/a/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252e/.%252…

分形之城 - 题解

分形之城时间限制:C/C++ 1000MS,其他语言 2000MS 内存限制:C/C++ 256MB,其他语言 512MB描述 城市的规划在城市建设中是个大问题。 不幸的是,很多城市在开始建设的时候并没有很好的规划,城市规模扩大之后规划不合理的问题就开始显现。 而这座名为 Fractal 的城市设想了这样…

开天辟地,环境安装(cangjie篇)

cangjie,尝鲜日记需求:安装好环境,输出hello world(程序员金字招牌,哈哈~)开整!1 下载SDK 由于官方关闭了开放下载入口,需要走申请、审核机制。然后gitcode平台,下载安装。我们这里就不方便提供下载地址了。目前,我安装的0.53.4b版本。如图:下载步骤就不赘述了,下一…

pycharm远程调试一直卡着(正在收集数据),查看变量时一直显示collecting data并报错Timeout waiting for response且看不到任何内容

1. 问题描述如题,在用PyCharm进行Python代码调试查看具体变量时,会随机遇到一直显示collecting data,到最后报错Timeout waiting for response,在界面中看不到变量内部的内容,如下图所示:2. 解决办法在PyCharm,打开Setting界面,在如下设置项中勾选“Gevent compatible”…

python错题记录:布尔运算与逻辑值检测

一 前言 环境:python 3.10 win10 二 布尔运算与逻辑值检测 1 案例 案例1如上,在布尔运算时,有些时候代码只会运算前面的一部分,剩下的部分根本不会运算。以前在练习算法代码时,就利用这个规则来减少代码的工作量 案例2如上,之前好长一段时间,上面的布尔运算总是让我感…

霍夫(Hough)直线变换(直线检测)

0 原理霍夫变换在检测各种形状的的技术中非常流行,如果你要检测的形状可以用数学表达式写出,你就可以是使用霍夫变换检测它。及时要检测的形状存在一点破坏或者扭曲也可以使用。我们下面就看看如何使用霍夫变换检测直线。 首先将一条直线用一个点表示,这样用一个点表示直线上…

使用浏览器开发人员工具抓取Windows聚焦桌面壁纸

最近发现Windows聚焦桌面壁纸质量都挺高的,比如下图,无奈图片不给保存。所有只有想办法把他爬下来。没有这个功能的可以在桌面右击鼠标,选择个性化,背景,Windows聚焦这样桌面上就出现一个图标右击这个图标,出现一个弹窗,选择“了解详情”就打开一个网页,我们按F12打开开…

编程语言之泛型困境

困境泛型不可能三角 泛型困境的本质是,关于泛型,你想要缓慢的程序员、缓慢的编译器和臃肿的二进制文件,还是缓慢的执行时间。简单来说就是:要么苦了程序员,要么苦了编绎器,要么降低运行时效率。 不同语言对泛型的考量 以C、C++和Java为例,它们在泛型的设计上有着不同考量…