分水岭分割和GrabCut前景提取

										分水岭分割和GrabCut前景提取

文章目录

  • 1.分水岭算法图像分割
  • 2.使用GrabCut算法进行交互式前景提取

准备工作:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

1.分水岭算法图像分割

# 分水岭算法图像分割
'''
任何一副图像都可以被看成拓扑平面,灰度值高的区域可以被看成是山峰,
灰度值低的区域可以被看成是山谷。
'''
img = cv2.imread('coins.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Otsu's 二值化
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv_show('coins', thresh)

kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

sure_bg = cv2.dilate(opening, kernel, iterations=3)

'''
距离变换的基本含义是计算一个图像中非零像素点到最近的像素点的距离。也就是到零像素点
的最短距离。
最常见的距离变换算法就是通过连续的腐蚀操作来实现,腐蚀操作的停止条件是所有
前景像素都被完全腐蚀。这样根据腐蚀的先后顺序,我们就得到各个前景像素点到前景中心
骨架像素点的距离。根据像素点距离值,设置不同的灰度值。
'''
dist_tranform = cv2.distanceTransform(opening, 1, 5)
ret, sure_fg = cv2.threshold(dist_tranform, 0.7 * dist_tranform.max(), 255, 0)

# 寻找未知的区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 显示前景
cv_show('name', sure_fg)

输出结果:
分水岭分割和GrabCut前景提取_第1张图片

2.使用GrabCut算法进行交互式前景提取

# 使用GrabCut算法进行交互式前景提取
'''
开始时用户需要用一个矩形将前景区域框住(前景区域应该被完全包括在矩形框内部)
然后算法进行迭代式分割直到达到最好结果。
'''
img = cv2.imread('people.png')
mask = np.zeros(img.shape[:2], np.uint8)

bgdmodel = np.zeros((1, 65), np.float64)
fgdmodel = np.zeros((1, 65), np.float64)

rect = (50, 0, 480, 290)

# cv2.rectangle(img, (50, 0), (480, 290), (0, 255, 0), 3)
# cv_show('rectangle', img)
img1 = img.copy()
# 函数的返回值是更新的  mask  bgdmodel fgdmodel
cv2.grabCut(img1, mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_RECT)
'''
img:输入图像
mask:掩模图像,用来确定哪些是背景,前景,可能是前景/背景等
     可以设置为: cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,
     或者直接输入 0,1,2,3 也行。
rect:包括前景的矩形
bgdmodel:算法内部使用的数组,你只需要创建两个大小为(1,65)
fgdmodel: 数据类型为np.float64类型的数组
5:  算法的迭代次数
cv2.GC_INIT_WITH_RECT: 确定修改的方式,矩形或者掩模
       cv2.GC_INIT_WITH_RECT
       cv2.GC_INIT_WITH_MASK
'''
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')

img1 = img1 * mask2[:, :, np.newaxis]

res = np.hstack((img, img1))
cv_show('res', res)

输出结果:
分水岭分割和GrabCut前景提取_第2张图片
进一步处理结果:

# 进一步处理
'''
我们使用图像编辑软件打开输入图像,添加一个图层,使用笔刷工具在需要的
地方使用白色绘制(头发,鞋子,球等),使用黑色笔刷在不需要的地方绘制
,然后将其他地方用灰色填充,保存成新的掩码图像
'''
img2 = img.copy()
people_handle = cv2.imread('people_handle.png')
newmask = cv2.imread('people_handle.png', 0)

mask[newmask == 0] = 0
mask[newmask == 255] = 1

mask, bgdmodel, fgdmodel = cv2.grabCut(img2, mask, None, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_MASK)

mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img2 = img2 * mask[:, :, np.newaxis]

res = np.hstack((people_handle, img2))
cv_show('res', res)

# 前后两次处理结果对比
res = np.hstack((img1, img2))
cv_show('res', res)

输出结果:
分水岭分割和GrabCut前景提取_第3张图片

你可能感兴趣的:(OpenCV)