掩码实现图片抠图
1 掩码
1.1 概念
掩码(Mask)是一种用于指定图像处理操作区域的工具。掩码通常是一个与图像尺寸雷同的二值图像,此中像素值为0表示不处理,像素值为255(或1)表示处理。掩码可以用于多种操作,如图像滤波、图像合成、图像分割等。掩码的尺寸必须与图像的尺寸雷同。掩码的像素值通常为0或255(或1),但也可以是其他值,详细取决于应用场景。通过使用掩码,可以更精确地控制图像处理操作的范围,从而实现更复杂的结果。
1.2 创建掩码
- mask = np.zeros((height, width), dtype=np.uint8),创建一个全黑的掩码
- (height, width), 高宽
- dtype=np.uint8 ,数据类型
- cv2.rectangle(mask, (x1, y1), (x2, y2), 255, -1),在掩码上绘制矩形
- (x1, y1), (x2, y2)起点和对角线坐标 ,
- 255颜色, -1表全添补
- import cv2
- import numpy as np
- # 创建一个全黑的掩码
- mask = np.zeros((300, 300), dtype=np.uint8)
- # 在掩码上绘制一个白色矩形
- cv2.rectangle(mask, (50, 50), (100, 100), 255, -1)
- cv2.imshow('mask',mask)
- cv2.waitKey(0)
复制代码 运行如下
1.3抠图思绪
- 图像读取与预处理
读取图像并转换为灰度图,举行高斯滤波以减少噪声。
- 边缘检测
使用Canny算法检测图像中的边缘。
- 轮廓检测与排序
查找图像中的轮廓,并根据面积举行排序。
- 二值化处理
对灰度图举行二值化处理,确定阈值。
- 轮廓筛选
根据轮廓的宽度、高度和宽高比筛选出符合条件的轮廓。
- 掩码操作
在掩码上绘制筛选后的轮廓,并对原图像和掩码举行与操作,以提取区域。
2 代码测试
原图

代码展示:
- import numpy as np
- import cv2
- # 定义一个函数用于显示图像,并等待用户按下任意键关闭窗口
- def cv_chow(name, img):
- cv2.imshow(name, img)
- cv2.waitKey(0)
- # 定义一个函数用于对四个点进行排序,返回一个有序的矩形顶点列表
- def order_points(pts):
- rect = np.zeros((4, 2), dtype="float32")
- s = pts.sum(axis=1) # 计算每个点的x和y坐标之和
- rect[0] = pts[np.argmin(s)] # 最小的和为左上角
- rect[2] = pts[np.argmax(s)] # 最大的和为右下角
- diff = np.diff(pts, axis=1) # 计算每个点的x和y坐标之差
- rect[1] = pts[np.argmin(diff)] # 最小的差为右上角
- rect[3] = pts[np.argmax(diff)] # 最大的差为左下角
- return rect
- # 定义一个函数用于对轮廓进行排序,支持从左到右、从右到左、从上到下、从下到上四种排序方式
- def sort_contours(cons, method='left-to-right'):
- reverse = False
- i = 0
- if method == 'right-to-left' or method == 'bottom-to-top':
- reverse = True
- if method == 'top-to-bottom' or method == 'bottom-to-top':
- i = 1
- boundingBoxes = [cv2.boundingRect(c) for c in cons] # 获取每个轮廓的边界框
- (cons, boundingBoxes) = zip(*sorted(zip(cons, boundingBoxes),
- key=lambda b: b[1][i], reverse=reverse))
- return cons, boundingBoxes
- # 读取图像
- img = cv2.imread('img_3.png')
- # 复制图像用于绘制轮廓
- cont_img = img.copy()
- # 将图像转换为灰度图
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- # 对灰度图进行高斯滤波,以减少噪声
- blurred = cv2.GaussianBlur(gray, (5, 5), 0)
- cv_chow('blurred', blurred)
- # 使用Canny边缘检测算法检测图像中的边缘
- edg = cv2.Canny(blurred, 75, 200)
- cv_chow('edg', edg)
- # 查找图像中的轮廓
- cnts = cv2.findContours(edg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
- # 在图像上绘制所有轮廓
- cv2.drawContours(cont_img, cnts, -1, (0, 0, 255), 3)
- cv_chow('cont_img', cont_img)
- # 根据轮廓面积对轮廓进行排序,从大到小
- cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
- # 对灰度图进行二值化处理,使用Otsu's方法自动确定阈值
- thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
- cv_chow('thresh', thresh)
- # 在二值化图像中查找轮廓
- thresh_cnt = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
- # 初始化一个列表用于存储符合条件的轮廓
- qus_cnts = []
- # 初始化一个列表用于存储所有的掩码
- mask_all = []
- # 创建一个与二值化图像大小相同的黑色掩码
- mask = np.zeros(thresh.shape, dtype='uint8')
- # 遍历所有轮廓,筛选出符合条件的轮廓
- for c in thresh_cnt:
- (x, y, w, h) = cv2.boundingRect(c) # 获取轮廓的边界框
- ar = w / float(h) # 计算边界框的宽高比
- if w >= 8 and h >= 10 and 0.5 <= ar <= 2: # 根据宽度、高度和宽高比筛选轮廓
- qus_cnts.append(c)
- # 遍历筛选后的轮廓,绘制掩码并进行与操作
- for i in qus_cnts:
- cv2.drawContours(mask, [i], -1, 255, -1) # 在掩码上绘制轮廓
- cv_chow('mask', mask)
- img_mask_and = cv2.bitwise_and(img, img, mask=mask) # 对原图像和掩码进行与操作
- cv_chow('img_mask_and', img_mask_and)
复制代码 运行结果:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |