opencv-python学习(4)--形态学与图像分割

摘要

opencv的python图像处理学习笔记

1.形态学处理

1.1 腐蚀

原理:遍历原图像的每一个像素,然后用核的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最小值,用这个最小值替换当前像素值。

1
2
k = np.ones((3, 3), np.uint8)
dst = cv2.erode(src, k, iterations=3)

iterations是迭代次数,越多腐蚀力度越大

1.2 膨胀

原理与腐蚀相同,改为使用最大值替换当前像素

1
2
k = np.ones((3, 3), np.uint8)
dst = cv2.dilate(src, k, iterations=3)

1.3 开运算与闭运算

先进行腐蚀再进行膨胀就叫做开运算

先膨胀在腐蚀就是闭运算

1
2
k = np.ones((3, 3), np.uint8)
dst = cv2.morphologyEx(src,cv2.MORPH_OPEN,k)

cv2.MORPH_OPEN:指定为开运算

cv2.MORPH_CLOSE:指定为闭运算

cv2.MORPH_GRADIENT 梯度运算(膨胀减去腐蚀)

cv2.MORPH_TOPHAT 礼帽 = 原始-开运算

cv2.MORPH_BLACKHAT 黑帽 = 闭运算-原始

2.图像分割

2.1 基于阈值的分割方法

  1. 固定阈值分割 >这是最简单的分割方法,大于某一阈值就提取出来,但该方法使用范围也非常的窄。
  2. 直方图双峰法 >灰度直方图通常由双峰属性,两个峰值之间的最小值通常可以认为是最优的二值化分界点。
  3. 迭代阈值图像分割 >1. 选取终止步长dt >2. 选取初始阈值T0 >3. 使用T分割图像分为G1、G2两组 >4. 统计G1、G2的平均灰度m1、m2 >5. 新阈值为\(T=(m1+m2)/2\) >6. 重复iii-v直到新阈值变动值小于dt
  4. OTSU法(最大类间方差法/大津法) >通过计算分割阈值的最大类间方差得到最合适的分割阈值,公式参考【图像分割】自适应阈值图像分割方法(最大类间差法与最大熵法)
  5. 最大熵法 >同上,基于最大熵选取阈值

2.2 基于边缘检测的分割方法

锐化空间滤波器内容见上一篇博客,使用锐化算子可以检测出边缘并进行分割。

2.3 基于区域的分割方法

  1. 区域生长法 >根据统一物体区域的像素相似性来聚集像素点达到区域生长的方法。
  2. 区域分裂合并法 >将图像任意分成若干互不相交的区域,按准则对这些区域进行分裂合并。差不多是生长法的逆过程。
  3. 分水岭法 >分水岭是用三维方法具象化二维图片,将灰度看着是海拔。模拟水淹没地形的过程,通过修建水坝的方式分割区域。

2.4 基于深度学习的分割方法

K-Means Clustering(k聚类)是一种非监督学习算法,对于给定样本集,按照距离大小划分为k个簇。

opencv提供的api

1
compactness, labels, (centers) = cv2.kmeans(data, K, bestLabels, criteria, attempts, centers)

参数:

  • data:输入的样本数据,必须是按行组织样本,每一行为一个样本数据,列表示样本的维度。
  • K:最终的簇的数目。
  • bestLabels:预设的分类标签或者None。
  • criteria:迭代停止的模式选择,这是一个含有三个元素的元组型数。格式为(type, max_iter, epsilon)
1
2
3
4
其中type有如下模式:
cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon,则停止。
cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter,则停止。
cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER:两者结合,满足任意一个结束。
  • attempts:重复试验kmeans算法次数,将会返回最好的一次结果。
  • centers:初始中心选择:
    1
    cv2.KMEANS_RANDOM_CENTERS:每次随机选择初始中心

返回值:

  • compactness:密度,返回每个点到相应重心的距离的平方和。
  • labels:结果标记,每个成员被标记为分组的序号,如 0,1,2,3,4…等。
  • centers:由聚类的中心的描述信息(可能是坐标,也可能是色彩值)组成的数组。
1
2
3
4
5
6
7
8
9
#K-means均值聚类
Z = img.reshape((-1, 3))
Z = np.float32(Z) #转化数据类型
c = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
k = 4 # 聚类个数
ret, label, center = cv2.kmeans(Z, k, None, c, 10, cv2.KMEANS_RANDOM_CENTERS)
center = np.uint8(center)
res = center[label.flatten()]
output_img = res.reshape((img.shape))

3. opencv的人脸检测

既然都提到图像分割和机器学习,这就不得不试一试人脸检测了。opencv有自带的训练好的数据,调一下库还是很快就能实现出来。

主要是使用分类器和检测多脸

1
2
3
4
5
6
7
8
9
10
# 加载人脸特征,该文件在 python安装目录\Lib\site-packages\cv2\data 下
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(img, scaleFactor, minNeighbors, minSize,maxSize)

# image表示的是要检测的输入图像
# scaleFactor表示每次图像尺寸减小的比例
# minNeighbors表示检测到多少次才算是目标
# minSize为目标的最小尺寸 元组
# maxSize为目标最大尺寸 元组
# 除了image其他都可以不输入

工程实例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 人脸检测
def facefind(self):
# 读入图片并转换为灰度
img = self.image
gray = UIFunctions.trun_gray(self,img)
# 加载人脸特征,该文件在 python安装目录\Lib\site-packages\cv2\data 下
face_cascade = cv2.CascadeClassifier(r'modules\haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4, minSize=(20, 20))
# 绘制矩形框
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
win_name = "face"
UIFunctions.wait_key(self,img,win_name)

参考资料

[1] python-opencv图像处理-腐蚀和膨胀

[2] 【深度学习】基于区域生长的图像分割算法!

[3] https://blog.csdn.net/weixin_53598445/article/details/123730985