掩膜

作者: 原上的小木屋 | 来源:发表于2020-06-06 15:15 被阅读0次

    通过使用黑白二值图像将对应于黑色部分的原始图像的像素改变为黑色的操作被称为掩膜。

    • 举个例子,比如说要提取蓝色部分,就先创建这样的二进制图像,使得HSV色彩空间中180≤H≤260的位置的像素值设为1,并将其0和1反转之后与原始图像相乘。
    • 这使得可以在某种程度上将图像主体(从背景上)分离出来。
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt#照例导入三个基本库
    # BGR -> HSV
    def BGR2HSV(_img):#图像转BGR模式转HSV模式
        img = _img.copy() / 255.
        hsv = np.zeros_like(img, dtype=np.float32)
        # get max and min
        max_v = np.max(img, axis=2).copy()
        min_v = np.min(img, axis=2).copy()
        min_arg = np.argmin(img, axis=2)
        # H
        hsv[..., 0][np.where(max_v == min_v)]= 0
        ## if min == B
        ind = np.where(min_arg == 0)
        hsv[..., 0][ind] = 60 * (img[..., 1][ind] - img[..., 2][ind]) / (max_v[ind] - min_v[ind]) + 60
        ## if min == R
        ind = np.where(min_arg == 2)
        hsv[..., 0][ind] = 60 * (img[..., 0][ind] - img[..., 1][ind]) / (max_v[ind] - min_v[ind]) + 180
        ## if min == G
        ind = np.where(min_arg == 1)
        hsv[..., 0][ind] = 60 * (img[..., 2][ind] - img[..., 0][ind]) / (max_v[ind] - min_v[ind]) + 300
        # S
        hsv[..., 1] = max_v.copy() - min_v.copy()
        # V
        hsv[..., 2] = max_v.copy()
        return hsv
    # make mask
    def get_mask(hsv):#得到掩膜
        mask = np.zeros_like(hsv[..., 0])
        #mask[np.where((hsv > 180) & (hsv[0] < 260))] = 255
        mask[np.logical_and((hsv[..., 0] > 180), (hsv[..., 0] < 260))] = 1#提取蓝色区域
        return mask#返回掩膜图像
    # masking
    def masking(img, mask):
        mask = 1 - mask#反转
        out = img.copy()
        # mask [h, w] -> [h, w, channel]
        mask = np.tile(mask, [3, 1, 1]).transpose([1, 2, 0])#将单通道掩膜图像扩展到三通道掩膜图像
        out *= mask#原图与掩膜图像相乘,提取的蓝色区域变黑被隐藏
        return out
    # Read image
    img = cv2.imread("123.jpg").astype(np.float32)#读取原始图片
    # RGB > HSV BGR转HSV
    hsv = BGR2HSV(img)
    # color tracking颜色追踪
    mask = get_mask(hsv)#得到掩膜图像
    # masking
    out = masking(img, mask)#将掩模图像和原图一并传入
    out = out.astype(np.uint8)
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    掩膜(色彩追踪+形态学处理)

    • 上述代码处理的结果不够精细,背景也有部分的残留,可以在掩膜图像上运用开运算和闭运算,使得掩膜图片更加准确
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt#导入三个必要的库
    # BGR -> HSV
    def BGR2HSV(_img):#图像BGR转HSV模式
        img = _img.copy() / 255.
        hsv = np.zeros_like(img, dtype=np.float32)
        # get max and min
        max_v = np.max(img, axis=2).copy()
        min_v = np.min(img, axis=2).copy()
        min_arg = np.argmin(img, axis=2)
        # H
        hsv[..., 0][np.where(max_v == min_v)]= 0
        ## if min == B
        ind = np.where(min_arg == 0)
        hsv[..., 0][ind] = 60 * (img[..., 1][ind] - img[..., 2][ind]) / (max_v[ind] - min_v[ind]) + 60
        ## if min == R
        ind = np.where(min_arg == 2)
        hsv[..., 0][ind] = 60 * (img[..., 0][ind] - img[..., 1][ind]) / (max_v[ind] - min_v[ind]) + 180
        ## if min == G
        ind = np.where(min_arg == 1)
        hsv[..., 0][ind] = 60 * (img[..., 2][ind] - img[..., 0][ind]) / (max_v[ind] - min_v[ind]) + 300 
        # S
        hsv[..., 1] = max_v.copy() - min_v.copy()
        # V
        hsv[..., 2] = max_v.copy()
        return hsv
    # make mask
    def get_mask(hsv):#得到掩膜图像
        mask = np.zeros_like(hsv[..., 0])
        #mask[np.where((hsv > 180) & (hsv[0] < 260))] = 255
        mask[np.logical_and((hsv[..., 0] > 180), (hsv[..., 0] < 260))] = 1
        return mask
    # masking
    def masking(img, mask):#将掩膜图像叠加到原图中
        mask = 1 - mask
        out = img.copy()
        # mask [h, w] -> [h, w, channel]
        mask = np.tile(mask, [3, 1, 1]).transpose([1, 2, 0])
        out *= mask
        return out
    # Erosion图片腐蚀
    def Erode(img, Erode_time=1):
        H, W = img.shape
        out = img.copy()
        # kernel腐蚀核
        MF = np.array(((0, 1, 0),
                    (1, 0, 1),
                    (0, 1, 0)), dtype=np.int)
        # each erode
        for i in range(Erode_time):
            tmp = np.pad(out, (1, 1), 'edge')#扩充边缘
            # erode
            for y in range(1, H + 1):
                for x in range(1, W + 1):
                    if np.sum(MF * tmp[y - 1 : y + 2 , x - 1 : x + 2]) < 1 * 4:#只有四邻域全为白,中央点才不会被改变,否则将中央点置0即黑
                        out[y - 1, x - 1] = 0#解释一下为啥这里是[y-1,x-1],还是因为tmp比out大一圈,tmp中央为[y,x],则out中央为[y-1,x-1]
        return out
    # Dilation
    def Dilate(img, Dil_time=1):
        H, W = img.shape
        # kernel
        MF = np.array(((0, 1, 0),
                    (1, 0, 1),
                    (0, 1, 0)), dtype=np.int)
        # each dilate time
        out = img.copy()
        for i in range(Dil_time):
            tmp = np.pad(out, (1, 1), 'edge')
            for y in range(1, H + 1):
                for x in range(1, W + 1):
                    if np.sum(MF * tmp[y - 1 : y + 2, x - 1 : x + 2]) >= 1:
                        out[y - 1, x - 1] = 1
        return out
    # Opening morphology一般形态学运算针对二值图像,刚好可以对应掩膜图像
    def Morphology_Opening(img, time=1):#开运算,先腐蚀再膨胀
        out = Erode(img, Erode_time=time)
        out = Dilate(out, Dil_time=time)
        return out
    # Closing morphology
    def Morphology_Closing(img, time=1):#闭运算,先膨胀再腐蚀
        out = Dilate(img, Dil_time=time)
        out = Erode(out, Erode_time=time)
        return out
    # Read image
    img = cv2.imread("imori.jpg").astype(np.float32)
    # RGB > HSV
    hsv = BGR2HSV(img / 255.)
    # color tracking
    mask = get_mask(hsv)
    # closing对掩膜图像先执行5次闭运算
    mask = Morphology_Closing(mask, time=5)
    # opening再对掩膜图像执行5次开运算
    mask = Morphology_Opening(mask, time=5)
    # masking
    out = masking(img, mask)
    out = out.astype(np.uint8)
    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    图像缩小与放大,其实这个我们在前面已经写过了,普适性会更强,下面这个代码只适用于方形图片

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt#导入三个常用的库
    # Grayscale转灰度
    def BGR2GRAY(img):
        # Grayscale
        gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
        return gray
    # Bi-Linear interpolation双线性插值
    def bl_interpolate(img, ax=1., ay=1.):
        if len(img.shape) > 2:
            H, W, C = img.shape
        else:
            H, W = img.shape
            C = 1
        aH = int(ay * H)#获取缩放之后的高度
        aW = int(ax * W)#获取缩放之后的宽度
        # get position of resized image获取调整大小后图像的位置
        y = np.arange(aH).repeat(aW).reshape(aW, -1)#沿着y方向
        x = np.tile(np.arange(aW), (aH, 1))#沿着x方向展开
        # get position of original position获取原始坐标位置
        y = (y / ay)
        x = (x / ax)
        ix = np.floor(x).astype(np.int)
        iy = np.floor(y).astype(np.int)
        ix = np.minimum(ix, W-2)#起始坐标
        iy = np.minimum(iy, H-2)#起始坐标
        # get distance
        dx = x - ix
        dy = y - iy
        if C > 1:
            dx = np.repeat(np.expand_dims(dx, axis=-1), C, axis=-1)
            dy = np.repeat(np.expand_dims(dy, axis=-1), C, axis=-1)
        # interpolation
        out = (1-dx) * (1-dy) * img[iy, ix] + dx * (1 - dy) * img[iy, ix+1] + (1 - dx) * dy * img[iy+1, ix] + dx * dy * img[iy+1, ix+1]
        out = np.clip(out, 0, 255)
        out = out.astype(np.uint8)
        return out
    # Read image
    img = cv2.imread("img11.png").astype(np.float)
    gray = BGR2GRAY(img)
    # Bilinear interpolation
    out = bl_interpolate(gray.astype(np.float32), ax=0.1, ay=0.1)
    # Bilinear interpolation
    out = bl_interpolate(out, ax=10., ay=10.)
    out = out.astype(np.uint8)
    # Save result
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.imwrite("out.jpg", out)
    

    相关文章

      网友评论

          本文标题:掩膜

          本文链接:https://www.haomeiwen.com/subject/pkuazhtx.html