20210520:人脸识别-口罩mask快速抠取

本文介绍了如何从图像中快速抠取口罩,主要针对口罩数据稀缺的问题。提出了两种解决方案:一是使用Photoshop工具,二是利用标注工具进行多边形标注并配合代码实现。通过标注工具生成的xml文件,可以结合代码实现口罩的精确抠取。
摘要由CSDN通过智能技术生成

上篇文章讲述如何快速将口罩mask与人脸face贴合问题。但通常人脸数据较好收集,口罩数据较少,所以比较可行的方案就是:爬取带有口罩的图像,将口罩分割出来。

目前有两种方法:

1:使用PS工具,将口罩抠下来,前提是得会ps...对于不会ps的我,就得另想办法啦,ps无非就是后台使用代码帮你抠而已,自己实现不香嘛

2:使用标注工具【19年博文有介绍】,选择多边形进行标注,会将shape/landmark信息自动保存在xml文件中。然后配合下面的代码,就可以得到文中开头的口罩抠取效果图了。

代码过于简单,就不再进行注解了...

#!/usr/bin/python
# -*- coding:utf-8 -*-

import os
import cv2
import numpy as np
import xml.etree.ElementTree as ET

# define map between mask and bg
class_map = {
    '_background_': 0,
    'mask': 1,
}


# search file by suffix
def file_search(path, allfile):
    filelist = os.listdir(path)

    for filename in filelist:
        filepath = os.path.join(path, filename)
        if os.path.isdir(filepath):
            file_search(filepath, allfile)
        else:
            if filepath.split(".")[-1] in img_ext:
                # if filepath.endswith('_label_landmark.png'):
                allfile.append(filepath)
    return allfile


# parse box info
def parse_box_info(xml):
    tree = ET.parse(xml)
    # root = tree.getroot()
    nodes = tree.findall('object')
    bndboxes = []
    for child in nodes:
        bndbox = []
        tmp = child.find('bndbox')
        xmin = tmp.find('xmin').text
        ymin = tmp.find('ymin').text
        xmax = tmp.find('xmax').text
        ymax = tmp.find('ymax').text
        bndbox.append(xmin)
        bndbox.append(ymin)
        bndbox.append(xmax)
        bndbox.append(ymax)
        bndbox = np.array(bndbox, np.int32)
        bndboxes.append(bndbox)
    return bndboxes


# parse shape info
def parse_shape_info(xml):
    tree = ET.parse(xml)
    # root = tree.getroot()
    nodes = tree.findall('object')
    shapes = []
    for child in nodes:
        shape = []
        tmp = child.find('shape')
        tmp_shape = tmp.find('points')
        count  = 0
        coor_x = 0
        coor_y = 0
        for n in range(0, len(tmp_shape)):
            count += 1
            if n%2 == 0:
                value_x = int(tmp_shape[n].text)
            else:
                value_y = int(tmp_shape[n].text)
            if count == 2:
                count = 0      
                shape.append([value_x, value_y])
        shapes.append([shape])
    return shapes


# get mask area
def get_mask(img, mask_shape):
    b_channel, g_channel, r_channel = cv2.split(img)  
    alpha_channel = np.zeros(b_channel.shape, dtype=b_channel.dtype)
    cv2.fillPoly(alpha_channel, [np.array(mask_shape[0])] ,(255))    
    img_BGRA = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
    
    img_fill = img.copy()
    cv2.fillPoly(img_fill, [np.array(mask_shape[0])] ,(0,0,255))    
    return img_BGRA, img_fill

def labelcolormap(N):
    cmap = np.zeros((N, 3), dtype=np.uint8)
    for i in range(N):
        r = 0
        g = 0
        b = 0
        id = i
        for j in range(7):
            str_id = uint82bin(id)
            r = r ^ (np.uint8(str_id[-1]) << (7 - j))
            g = g ^ (np.uint8(str_id[-2]) << (7 - j))
            b = b ^ (np.uint8(str_id[-3]) << (7 - j))
            id = id >> 3
        cmap[i, 0] = r
        cmap[i, 1] = g
        cmap[i, 2] = b
    return cmap


if __name__ == '__main__':
    flag_show = True
    img_ext = ['jpg','png','bmp']
    folder_face = '/home/lilasi/sshfs/Code/face_mask_seg/imgs'
    
    # search image
    imgs_list = []
    file_search(folder_face, imgs_list)
    
    # loop
    for idx, img_file in enumerate(imgs_list):
        xml_file = img_file[:-4] + ".xml"
        
        # load image
        image = cv2.imread(img_file)
        im_h = image.shape[0]
        im_w = image.shape[1]
        
        # load mask shape point
        mask_shape = parse_shape_info(xml_file)
        
        # get mask area
        img_mask, img_fill = get_mask(image, mask_shape)
        name_img_mask = folder_face + '/' + os.path.basename(img_file)[:-4] + "_mask.png"
        name_img_fill = folder_face + '/' + os.path.basename(img_file)[:-4] + "_fill.png"
        cv2.imwrite(name_img_mask, img_mask)
        cv2.imwrite(name_img_fill, img_fill)
        if flag_show:
            cv2.imshow("mask", img_mask)
            cv2.imshow("fill", img_fill)
            cv2.waitKey(0)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微风❤水墨

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值