这是需要抠图的原图像,文件名为 “messi5.jpg”
使用矩形方式处理:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('messi5.jpg')
# 返回一个和图片等尺寸、且全为0的矩阵
mask = np.zeros(img.shape[:2],np.uint8)
# 返回1*65、且全为0的矩阵
# grabCut 算法用到,无需关心
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
# 前景在矩形框以内
rect = (64,67,467,355)
# 函数的返回值是更新的 mask, bgdModel, fgdModel
# https://blog.csdn.net/github_39611196/article/details/81143026
# mask 掩码图像,用于确定哪些可能是前景/背景
# rect 前景矩形,格式为 (x1,y1,x2,y2)
# 5 算法迭代次数
# cv2.GC_INIT_WITH_?? 前景提取模式是矩形形式还是掩码的形式
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
# 根据是否条件满足,返回元素为0/1的数组
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
# np.newaxis 增加一个维度,
# 将二维2*3的矩阵 [[0 0 0] [0 0 0]] 变成
# 三维2*3*1的矩阵 [ [ [0] [0] [0] ] [ [0] [0] [0] ] ]
# print(mask2)
# print('\nwaxis\n',mask2[:,:,np.newaxis].shape)
# 数组相乘,得到每个元素的乘积
img = img*mask2[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
使用矩形模式 图像处理结果:
使用掩模方式处理:
打开网址 :https://www.tuyitu.com/photoshop/
将原图像上传,新建图层,绘制前景-背景掩模图像:
绘制方式为:一定是前景-白色;一定是背景-黑色;可能是背景-灰色(144色值)
保存掩模图层,命名为 “newmask.png”
执行下列程序:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('messi5.jpg')
# 返回一个和图片等尺寸、且全为0的矩阵
mask = np.zeros(img.shape[:2],np.uint8)
# 返回1*65、且全为0的矩阵
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (64,67,467,355)
# newmask is the mask image I manually labelled
newmask = cv2.imread('newmask.png',0)
# whereever it is marked white (sure foreground), change mask=1
# whereever it is marked black (sure background), change mask=0
# 黑色一定是背景
mask[newmask == 0] = 0
# 白色一定是前景
mask[newmask == 255] = 1
# 灰色可能是背景
mask[newmask == 145] = 2
# 打印看看灰色色值
print(newmask[:,100])
# 注意 newmask 一定是按要求的图层保存,否则函数会错误
# 建议使用Photoshop或在线PS工具:https://www.tuyitu.com/photoshop/
# 函数的返回值是更新的 mask, bgdModel, fgdModel
# mask 掩码图像,用于确定哪些可能是前景/背景
# None 前景矩形,未用到
# 5 算法迭代次数
# GC_INIT_WITH_MASK 掩码的形式提取
mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
处理图像结果:
直接使用掩模方式,只需在图像中画上几笔,就可以将前景人物完美提取出来,可见 grabCut 函数非常强大。
参考资料:OpenCV官方教程中文版(For Python).pdf