目录
二值化
二值化是将图像转换为只包含两个灰度值的图像,通常是将图像中的像素值限定为两个固定的值,例如0和255,用于表示黑色和白色。
在二值化过程中,根据像素的灰度值与设定的阈值进行比较,将像素分为两个类别:低于阈值的像素被设为黑色,高于阈值的像素被设为白色。一方面用于减少数据的维度,另一方面通过排除原图中的噪声带来的干扰,可以凸出轮廓结构。这种转换可以突出图像中的物体轮廓,简化图像,并提取出感兴趣的目标。
固定阈值二值化
根据整个图像的灰度特性,选择一个固定的阈值将图像分成两个部分。所有低于阈值的像素点被设置为黑色,高于阈值的像素点被设置为白色;以下是固定二值化代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图像
img = cv2.imread('22.jpg')
# 应用全局阈值二值化
_, binary_image = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 显示二值化后的图像
cv2.imshow('Binary Image',binary_image )
# 显示原图
cv2.imshow(' Image',img )
cv2.waitKey(0)
cv2.destroyAllWindows()
上图是代码执行后的结果图
自适应阈值二值化
自适应阈值二值化(Adaptive Thresholding)是一种将图像转换为黑白(二值化)图像的方法,其中阈值是根据图像局部区域的亮度来确定的,而不是全局应用一个固定的阈值。
这种方法可以帮助解决在图像中存在不均匀照明条件下的二值化问题。在自适应阈值二值化中,图像被分割成许多小的局部区域,然后针对每个局部区域计算适用的阈值,从而使得不同区域的阈值能够适应其局部特征。
以下是自适应阈值二值化的基本步骤:
-
将图像转换为灰度图像(如果原始图像不是灰度图像)。
-
指定一个合适的局部区域大小(通常为奇数),比如3x3、5x5等。
-
对于图像中的每个像素,计算该像素周围局部区域的平均灰度值或者高斯权重平均灰度值。
-
通过将该像素的灰度值与计算得到的局部阈值进行比较,将像素值设为0(黑色)或255(白色),以实现二值化。
自适应阈值二值化可以通过多种算法实现,其中两个常用的方法是:
- 平均阈值算法(Mean Thresholding):使用局部区域的平均灰度值作为阈值。
- 高斯加权平均阈值算法(Gaussian Weighted Mean Thresholding):使用局部区域的高斯加权平均灰度值作为阈值,使得具有更大权重的像素对阈值的贡献更大。
这些算法可以根据具体应用的需求进行选择。自适应阈值二值化有助于在具有不均匀照明条件的图像中提取目标对象的特征或轮廓。代码案例如下:
import cv2
# 读取图像并转换为灰度图像
image = cv2.imread('22.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 自适应阈值二值化
threshold = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
# 显示结果
cv2.imshow('Thresholded Image', threshold)
# 显示原图
cv2.imshow(' Image',img )
cv2.waitKey(0)
cv2.destroyAllWindows()
以上是代码执行后结果
Otsu's 二值化
Otsu's 二值化是一种自动确定图像全局阈值的方法,它可以将图像转换为黑白(二值化)图像。这种方法通过最小化类间方差来确定最佳阈值,从而实现对图像的自适应二值化。
以下是Otsu's 二值化的基本步骤:
-
将图像转换为灰度图像(如果原始图像不是灰度图像)。
-
计算图像的直方图,统计每个灰度级别下像素的数量。
-
遍历所有可能的阈值(0到255),计算使用当前阈值分割图像时的类间方差。
-
根据类间方差的值选择最佳阈值,使得分割后的两个类别之间的方差最小化。
-
将图像中大于或等于最佳阈值的像素设为255(白色),小于最佳阈值的像素设为0(黑色),以实现二值化。
使用Otsu's 二值化可以有效地将图像二值化,同时考虑到了图像整体的特征。在处理具有双峰直方图的图像时,Otsu's 方法尤其有效,因为它可以找到两个峰之间的最佳阈值。
import cv2
from matplotlib import pyplot as plt
image = cv2.imread('22.jpg')
# 将输入图像转化成灰度图
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 绘制灰度图
plt.figure(figsize=(15, 15))
plt.subplot(311)
plt.imshow(gray,"gray")
plt.title("input image")
plt.xticks([])
plt.yticks([])
# 对灰度图使用Ostu法
ret1,th1 = cv2.threshold(gray,0,255,cv2.THRESH_OTSU)
# 绘制灰度直方图
plt.subplot(312)
plt.hist(gray.ravel(),256)
# 标注Ostu阀值所在直线
plt.axvline(x=ret1,color='red',label='otsu')
plt.legend(loc='upper right')
plt.title("Histogram")
plt.xticks([])
plt.yticks([])
# 绘制二值化图片
plt.subplot(313)
plt.imshow(th1,'gray')
plt.title("Output image")
plt.xticks([])
plt.yticks([])
plt.show()
对于灰度直方图呈现的两个峰值的图像,Ostu算法得到的阀值为峰值间低谷的位置,二值化的效果也是比较好的;但是当目标物与背景大小比例悬殊或灰度级接近,导致直方图呈现三峰或者双峰峰值差距极大时,Ostu算法是得不到满意结果的。因为单用灰度分布设置阀值的依据,不仅使结果对噪声极其敏感,而且容易丢失图像中重要的空间结构关系。实际应用中,一般配合其他方法一起组合使用。
腐蚀、膨胀、开运算、闭运算
对于灰度图像而言,腐蚀、膨胀运算都类似于卷积操作,将结构元素在原图上,平移,而结构元素上的原点就相当于卷积核的核中心。开、闭运算即二者的组合,开运算是先腐蚀再膨胀、闭运算是先膨胀再腐蚀。一般来说,开运算可以使图像的轮廓变的光滑,断开狭窄的连接并消除细毛刺;闭运算同样可以平滑轮廓,但具体的作用是排除小型空洞,弥合狭窄的间断点、沟壑以及填补断裂的轮廓线。
import cv2
import numpy as np
img = cv2.imread('22.jpg')
# 使用getStructuringElement 定义结构元素,shape 为结构元素形状,0表示矩形,1表示+字
k = cv2.getStructuringElement(shape=1,ksize=(3,3),anchor=(-1,-1))
# erode 腐蚀运算、src 输入图像、iterations 腐蚀操作次数
erosion = cv2.erode(src=img,kernel=k,iterations=1)
cv2.imshow('Eroded image',erosion)
# dilate 膨胀运算
dilation = cv2.dilate(img,k,iterations=1)
cv2.imshow('Dilated image',dilation)
# morphologyEx 实现开闭运算,op 运算类型,cv2.MORPH_OPEN 开运算 ,cv2.MORPH_CLOSE 闭运算
opening = cv2.morphologyEx(src=img,op=cv2.MORPH_OPEN,kernel=k)
closing = cv2.morphologyEx(src=img,op=cv2.MORPH_CLOSE,kernel=k)
cv2.imshow('Opening image',opening)
cv2.imshow('Closing image',closing)
cv2.imshow(' Image',img )
cv2.waitKey(0)
cv2.destroyAllWindows()