Opencv之掩码实现图片抠图

打印 上一主题 下一主题

主题 997|帖子 997|积分 2991

掩码实现图片抠图


  
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表全添补

  1. import cv2
  2. import numpy as np
  3. # 创建一个全黑的掩码
  4. mask = np.zeros((300, 300), dtype=np.uint8)
  5. # 在掩码上绘制一个白色矩形
  6. cv2.rectangle(mask, (50, 50), (100, 100), 255, -1)
  7. cv2.imshow('mask',mask)
  8. cv2.waitKey(0)
复制代码
运行如下

1.3抠图思绪



  • 图像读取与预处理
    读取图像并转换为灰度图,举行高斯滤波以减少噪声。
  • 边缘检测
    使用Canny算法检测图像中的边缘。
  • 轮廓检测与排序
    查找图像中的轮廓,并根据面积举行排序
  • 二值化处理
    对灰度图举行二值化处理,确定阈值。
  • 轮廓筛选
    根据轮廓的宽度、高度和宽高比筛选出符合条件的轮廓。
  • 掩码操作
    在掩码上绘制筛选后的轮廓,并对原图像和掩码举行与操作,以提取区域。
2 代码测试

原图

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


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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

络腮胡菲菲

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表