首页 > 编程语言 >一键抠图1:Python实现人像抠图 (Portrait Matting)

一键抠图1:Python实现人像抠图 (Portrait Matting)

时间:2023-12-28 14:33:16浏览次数:39  
标签:MODNet 人像 Python 图像 bg alpha Portrait Matting


一键抠图1:Python实现人像抠图 (Portrait Matting)

目录

一键抠图1:Python实现人像抠图 (Portrait Matting)

1. 项目介绍

2. 抠图算法

3. Matting数据集

4. MODNet模型

 (1) 项目安装

 (2) 数据集说明

 (3) MODNet模型

5. Demo测试效果 

6. 源码下载(Python)

7.人像抠图C++版本

8.人像抠图Android版本


1. 项目介绍

抠图算法(英文中,一般称为Matting)有多种实现方式,一种是基于辅助信息输入的,加入一些先验信息(如Trimap,背景图,用户交互信息,深度等信息)提供抠图效果,如比较经典的Deep Image Matting和Semantic Image Matting这些算法加入Trimap; Background Matting算法需要提供背景图等;另一种是无需辅助信息,输入RGB图像,直接预测matte的方法,其效果相对第一种方法,会差很多。而对Portrait Matting(人像抠图),现在有很多方案在无需Trimap条件下,也可以获得不错的抠图效果,比如MODNet,Fast Deep Matting等算法,真正实现一健抠图的效果。

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像分割

本篇博客是一键抠图项目系列之《Python实现人像抠图 (Portrait Matting)》,项目将在MODNet人像抠图算法基础上进行模型压缩和优化,开发一个效果相当不错的Matting算法,可以达到头发细致级别的人像抠图效果,为了方便后续模型工程化和Android平台部署,项目提供高精度版本人像抠图和轻量化快速版人像抠图,并提供Python/C++/Android多个版本;

尊重原创,转载请注明出处

Android Demo APP下载地址:

先展示一下一键人像抠图效果:

一键抠图1:Python实现人像抠图 (Portrait Matting)_一键抠图_02


更多项目《一键抠图》系列文章请参考:

  1. 一键抠图1:Python实现人像抠图 (Portrait Matting)
  2. 一键抠图2:C/C++实现人像抠图 (Portrait Matting)
  3. 一键抠图3:Android实现人像抠图 (Portrait Matting)

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像抠图_03


2. 抠图算法

基于深度学习的Matting分为两大类:

  • 一种是基于辅助信息输入。即除了原图和标注图像外,还需要输入其他的信息辅助预测。最常见的辅助信息是Trimap,即将图片划分为前景,背景及过度区域三部分。另外也有以背景或交互点作为辅助信息。
  • 一种是不依赖任何辅助信息,直接对Alpha进行预测。如本博客复现的MODNet

第一种方法,需要加入辅助信息,而辅助信息一般较难获取,这也限制其应用,为了提升Matting的应用性,针对Portrait Matting领域MODNet摒弃了辅助信息,直接实现Alpha预测,实现了实时Matting,极大提升了基于深度学习Matting的应用价值。

更多抠图算法(Matting),请参考我的一篇博客《图像抠图Image Matting算法调研》:

搞不清楚分割(segmentation)和抠图(matting)有什么区别,我这里简单说明一下:

  •  分割(segmentation):从深度学习的角度来说,分割本质是像素级别的分类任务,其损失函数最简单的莫过于是交叉熵CrossEntropyLoss(当然也可以是Focal Loss,IOU Loss,Dice Loss等);对于前景和背景分割任务,输出Mask的每个像素要么是0,要么是1。如果拿去直接做图像融合,就很不自然,Mask边界很生硬,这时就需要使用抠图算法了
  •  抠图(matting): 而抠图本质是一种回归任务,其损失函数可以是MSE Loss,L1 Loss,L2 Loss等,对于前景和背景抠图任务,输出Mask的每个像素是0~1之间的连续值,可看作是对图像透明通道(Alpha)的回归预测。可以用公式表示为C = αF + (1-α)B ,其中α(不透明度)、F(前景色)和B(背景色),alpha是[0, 1]之间的连续值,可以理解为像素属于前景的概率。在人像分割任务中,alpha只能取0或1,而抠图任务中,alpha可取[0, 1]之间的连续值,
  • 本质上就是一句话:分割是分类任务,而抠图是回归任务。

3. Matting数据集

一些开源的matting数据集

数据集

说明

matting_human_datasets

  • 本数据集为目前已知最大的人像matting数据集,包含34427张图像和对应的matting结果图。
  • 数据集由北京玩星汇聚科技有限公司高质量标注,使用该数据集所训练的人像软分割模型已商用。
  • 数据集中的原始图片来源于Flickr、百度、淘宝。经过人脸检测和区域裁剪后生成了600*800的半身人像。
  • GitHub - aisegmentcn/matting_human_datasets: 人像matting数据集,包含34427张图像和对应的matting结果图。
  • PS:Matting比较粗糙,没有达到头发细致抠图;不过数据比较大,可以作为pretrained数据集使用

Deep Image Matting

PPM-100

  • PPM-100 是论文 MODNet (Github | Arxiv) 中提出的一个人像抠图基准,它包含了100张来自Flickr的人像图片,具有以下特点:
  • 精细标注 - 所有图像都被仔细标注并检查。
  • 丰富多样 - 图像涵盖全身/半身人像和各种姿态。
  • 高分辨率 - 图像的分辨率介于1080P和4K之间。
  • 自然背景 - 所有图像都包含原始无替换的背景。
  • 项目地址:GitHub - ZHKKKe/PPM: A High-Quality Photograpy Portrait Matting Benchmark

PPM-100下载:https://github.com/PaddlePaddle/PaddleSeg/tree/release/2.3/contrib/Matting

RealWorldPortrait-636

 Compsition-1k

HAttMatting

 AM-2k

BG-20k

VideoMatte240K

PhotoMatte85

其他的:

4. MODNet模型

 (1) 项目安装

 整套工程项目基本结构如下:

一键抠图1:Python实现人像抠图 (Portrait Matting)_Matting_04

推荐使用Python3.8或Python3.7,更高版本可能存在版本差异问题, 项目依赖python包请参考requirements.txt,使用pip安装即可:

numpy==1.21.6
matplotlib==3.2.2
Pillow==8.4.0
bcolz==1.2.1
easydict==1.9
onnx==1.8.1
onnx-simplifier==0.2.28
onnxoptimizer==0.2.0
onnxruntime==1.6.0
opencv-contrib-python==4.5.2.52
opencv-python==4.5.1.48
pandas==1.1.5
PyYAML==5.3.1
scikit-image==0.17.2
scikit-learn==0.24.0
scipy==1.5.4
seaborn==0.11.2
sklearn==0.0
tensorboard==2.5.0
tensorboardX==2.1
torch==1.7.1+cu110
torchvision==0.8.2+cu110
tqdm==4.55.1
xmltodict==0.12.0
pycocotools==2.0.2
pybaseutils==0.9.4
basetrainer

项目安装教程请参考(初学者入门,麻烦先看完下面教程,配置好开发环境):

  • 项目开发使用教程和常见问题和解决方法
  • 视频教程:1 手把手教你安装CUDA和cuDNN(1)
  • 视频教程:2 手把手教你安装CUDA和cuDNN(2)
  • 视频教程:3 如何用Anaconda创建pycharm环境
  • 视频教程:4 如何在pycharm中使用Anaconda创建的python环境
  • 推荐使用Python3.8或Python3.7,更高版本可能存在版本差异问题

 (2) 数据集说明

关于训练数据如何生成的问题:

  • 原论文MODNet使用了PPM-100数据集+私有的数据集,并合成了大部分训练数据
  • 鄙人复现时,先使用matting_human_datasets数据集训练base-model当作pretrained模型;然后合并多个数据集(PPM-100 + RealWorldPortrait-636 + Deep Image Matting),采用背景图来自VOC+COCO+BG-20k ,一共合成了5W+的训练数据和500+的测试数据
  • 合成的方法有两种:方法1:利用公式:合成图 = 前景*alpha+背景*(1-alpha) ;方法二:前景+mask+背景通过GAN生成;

这是Python实现的背景合成,需要提供原始图像image,以及image的前景图像alpha,和需要合成的背景图像bg_img:

def image_fusion(image: np.ndarray, alpha: np.ndarray, bg_img=(219, 142, 67)):
        """
        图像融合:合成图 = 前景*alpha+背景*(1-alpha)
        :param image: RGB图像(uint8)
        :param alpha: 单通道的alpha图像(uint8)
        :param bg_img: 背景图像,可以是任意的分辨率图像,也可以指定指定纯色的背景
        :return: 返回与背景合成的图像
        """
        if isinstance(bg_img, tuple) or isinstance(bg_img, list):
            bg = np.zeros_like(image, dtype=np.uint8)
            bg_img = np.asarray(bg[:, :, 0:3] + bg_img, dtype=np.uint8)
        if len(alpha.shape) == 2:
            # alpha = cv2.cvtColor(alpha, cv2.COLOR_GRAY2BGR)
            alpha = alpha[:, :, np.newaxis]
        if alpha.dtype == np.uint8:
            alpha = np.asarray(alpha / 255.0, dtype=np.float32)
        sh, sw, d = image.shape
        bh, bw, d = bg_img.shape
        ratio = [sw / bw, sh / bh]
        ratio = max(ratio)
        if ratio > 1:
            bg_img = cv2.resize(bg_img, dsize=(math.ceil(bw * ratio), math.ceil(bh * ratio)))
        bg_img = bg_img[0: sh, 0: sw]
        image = image * alpha + bg_img * (1 - alpha)
        image = np.asarray(np.clip(image, 0, 255), dtype=np.uint8)
        return image

当然,为了方便JNI调用,我这里还实现C++版本图像合成算法,这部分图像处理的基本工具,都放在我的base-utils

/***
 * 实现图像融合:out = imgBGR * matte + bg * (1 - matte)
 * Fix a Bug: 1-alpha实质上仅有B通道参与计算,多通道时(B,G,R),需改Scalar(1.0, 1.0, 1.0)-alpha
 * @param imgBGR 输入原始图像
 * @param matte  输入原始图像的Mask,或者alpha,matte
 * @param out    输出融合图像
 * @param bg     输入背景图像Mat(可任意大小),也可以通过Scalar指定纯色的背景
 */
void image_fusion(cv::Mat &imgBGR, cv::Mat matte, cv::Mat &out, cv::Mat bg) {
    assert(matte.channels() == 1);
    out.create(imgBGR.size(), CV_8UC3);
    vector<float> ratio{(float) imgBGR.cols / bg.cols, (float) imgBGR.rows / bg.rows};
    float max_ratio = *max_element(ratio.begin(), ratio.end());
    if (max_ratio > 1.0) {
        cv::resize(bg, bg, cv::Size(int(bg.cols * max_ratio), int(bg.rows * max_ratio)));
    }
    bg = image_center_crop(bg, imgBGR.cols, imgBGR.rows);
    int n = imgBGR.channels();
    int h = imgBGR.rows;
    int w = imgBGR.cols * n;
    // 循环体外进行乘法和除法运算
    matte.convertTo(matte, CV_32FC1, 1.0 / 255, 0);
    for (int i = 0; i < h; ++i) {
        uchar *sptr = imgBGR.ptr<uchar>(i);
        uchar *dptr = out.ptr<uchar>(i);
        float *mptr = matte.ptr<float>(i);
        uchar *bptr = bg.ptr<uchar>(i);
        for (int j = 0; j < w; j += n) {
            //float alpha = mptr[j] / 255; //循环体尽量减少乘法和除法运算
            float alpha = mptr[j / 3];
            float _alpha = 1.f - alpha;
            dptr[j] = uchar(sptr[j] * alpha + bptr[j] * _alpha);
            dptr[j + 1] = uchar(sptr[j + 1] * alpha + bptr[j + 1] * _alpha);
            dptr[j + 2] = uchar(sptr[j + 2] * alpha + bptr[j + 2] * _alpha);
        }
    }
}

 (3) MODNet模型

本文主要在MODNet人像抠图算法基础上进行模型压缩和优化,关于《MODNet: Trimap-Free Portrait Matting in Real Time》,请参考:

 MODNet模型学习分为三个部分,分别为:语义部分(S),细节部分(D)和融合部分(F)

  • 在语义估计中,对high-level的特征结果进行监督学习,标签使用的是下采样及高斯模糊后的GT,损失函数用的L2-Loss,用L2loss应该可以学到更soft的语义特征;
  • 在细节预测中,结合了输入图像的信息和语义部分的输出特征,通过encoder-decoder对人像边缘进行单独地约束学习,用的是交叉熵损失函数。为了减小计算量,encoder-decoder结构较为shallow,同时处理的是原图下采样后的尺度。
  • 在融合部分,把语义输出和细节输出结果拼起来后得到最终的alpha结果,这部分约束用的是L1损失函数。

一键抠图1:Python实现人像抠图 (Portrait Matting)_一键抠图_05

官方GitHub仅仅放出推理代码,并未提供训练代码和数据处理代码

  • 复现Pytorch版本的MODNet训练过程和数据处理
  • 增加了数据增强方法:如多尺度随机裁剪,Mosaic(拼图),随机背景融合等方法,提高模型泛化性
  • 对MODNet骨干网络backbone进行轻量化,减少计算量
  • 模型压缩,目前提供三个版本:高精度人像抠图modnet+快速人像抠图modnet0.75+超快人像抠图modnet0.5
  • 转写模型推理过程,实现C++版本人像抠图算法
  • 实现Android版本人像抠图算法,支持CPU和GPU
  • 提供高精度版本人像抠图,可以达到精细到发丝级别的抠图效果(Android GPU 150ms,  CPU 500ms左右)
  • 提供轻量化快速版人像抠图,满足基本的人像抠图效果,可以在Android达到实时的抠图效果(Android GPU 60ms,  CPU 140ms左右)

高精度人像抠图modnet+快速人像抠图modnet0.75+超快人像抠图modnet0.5的模型参数量和计算量:

模型

input size

FLOPs and Params

modnet

416×416

Model FLOPs 10210.24M, Params 6.44M

modnet0.75

320×320

Model FLOPs 3486.23M, Params 3.64M

modnet0.5

320×320

Model FLOPs 1559.07M, Params 1.63M

最近发现,百度PaddleSeg团队也复现了MODNet算法(基于PaddlePaddle框架,非Pytorch版本),提供了更丰富的backbone模型选择,如MobileNetV2,ResNet50,HRNet_W18,可适用边缘端、服务端等多种任务场景,有兴趣的可以看看:

 PaddlePaddle版本:https://github.com/PaddlePaddle/PaddleSeg/tree/release/2.3/contrib/Matting


5. Demo测试效果 

项目环境配置好后,运动demo.py即可测试抠图效果,方法

  • 测试图片
# 测试图片
python demo.py --model_type "modnet" --model_file "work_space/modnet_416/model/best_model.pth" --image_dir "data/test_images"
  • 测试视频文件
# 测试视频文件
python demo.py --model_type "modnet" --model_file "work_space/modnet_416/model/best_model.pth" --video_file "data/video/video-test1.mp4"
  • 测试摄像头
# 测试摄像头
python demo.py --model_type "modnet" --model_file "work_space/modnet_416/model/best_model.pth" --video_file 0

下图GIF是Python版本的视频抠图效果

一键抠图1:Python实现人像抠图 (Portrait Matting)_Portrait_06

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像抠图_07

一键抠图1:Python实现人像抠图 (Portrait Matting)_Portrait_08

实际使用中,建议你:

  • 背景越单一,抠图的效果越好,背景越复杂,抠图效果越差;建议你实际使用中,找一比较单一的背景,如墙面,天空等
  • 上半身抠图的效果越好,下半身或者全身抠图效果较差;本质上这是数据的问题,因为训练数据70%都是只有上半身的
  • 白种人抠图的效果越好,黑人和黄种人抠图效果较差;这也是数据的问题,因为训练数据大部分都是隔壁的老外

下图是高精度版本人像抠图和快速人像抠图的测试效果,相对而言,高精度版本人像抠图可以精细到发丝级别的抠图效果;而快速人像构图目前仅能实现基本的抠图效果

高精度版本人像抠图

快速人像抠图

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像分割_09

一键抠图1:Python实现人像抠图 (Portrait Matting)_Matting_10

一键抠图1:Python实现人像抠图 (Portrait Matting)_Matting_11

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像分割_12

一键抠图1:Python实现人像抠图 (Portrait Matting)_人像抠图_13

一键抠图1:Python实现人像抠图 (Portrait Matting)_一键抠图_14


6. 源码下载(Python)

项目源码下载地址:Python实现人像抠图 (Portrait Matting)

项目源码内容包含:

  • 提供Python的推理代码(不含训练代码和不含数据集)
  • 提供高精度版本人像抠图模型(modnet_416),可以达到精细到发丝级别的抠图效果
  • 提供轻量化快速版人像抠图模型(modnet0.75_320和modnet0.5_320),满足基本的人像抠图效果,
  • Demo支持图片抠图,视频抠图,摄像头抠图

7.人像抠图C++版本

一键抠图2:C/C++实现人像抠图 (Portrait Matting)


8.人像抠图Android版本

一键抠图3:Android实现人像抠图 (Portrait Matting)

一键抠图1:Python实现人像抠图 (Portrait Matting)_Matting_15


标签:MODNet,人像,Python,图像,bg,alpha,Portrait,Matting
From: https://blog.51cto.com/u_15764210/9014802

相关文章

  • python之秀人网图片下载
    importrequestsfromlxmlimportetreecookies={'_pk_ref.2.90a9':'%5B%22%22%2C%22%22%2C1703739850%2C%22https%3A%2F%2Fwww.google.com.hk%2F%22%5D','_pk_id.2.90a9':'b87f72074fff4914.1703739850.',......
  • mrml python 以及webassembly 实现简单说明
    简单说明下mrmlpython以及webassembly的实现pythonpython是基于了pyo3,利用pyo3提供的能力,暴露了python模块参考处理//暴露的mrml模块#[pymodule]#[pyo3(name="mrml")]fnregister(_py:Python<'_>,m:&PyModule)->PyResult<()>{......
  • 简单记录下python视频提取语音,语音转文字(web版本)
    一、直接贴代码,有些离线文件需要下载,python依赖包也需要下载。#coding=utf-8fromflaskimportFlask,render_template_string,jsonify,requestfromflask_corsimportCORSfromtkinterimportfiledialogfrompydubimportAudioSegmentfromnoisereduceimportredu......
  • vs code 运行python 项目问题
    1. 安装python、vscode;2. anaconda配置运行项目的虚拟环境;3. vscode打开运行项目文件夹;4 vscode安装python插件;   打开VScode编辑器,按下快捷键“Ctrl+Shift+P”,或者左下角图标 ,选择“CommandPalette”         调出全局设置搜索窗......
  • Boto3按名字搜索AWS Image并返回Image的相关参数 (Python)
    文章目录小结问题及解决参考小结本文记录使用Python脚本和Boto3按名字搜索AWSImage并返回AWSImage的相关参数。问题及解决记得操作之前拿到相应的权限:exportAWS_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxxxxxxxxxxx"exportAWS_SECRET_ACCESS_KEY="yyyyyyyyyyyyyyyyyyyyyyyyyyyy"e......
  • 一键抠图2:C/C++实现人像抠图 (Portrait Matting)OpenCV库使用opencv-4.3.0版本,opencv_
    一键抠图2:C/C++实现人像抠图(PortraitMatting)目录一键抠图2:C/C++实现人像抠图(PortraitMatting)1.前言2.抠图算法3.人像抠图算法MODNet(1)模型训练(2)将Pytorch模型转换ONNX模型(3)将ONNX模型转换为TNN模型4.模型C++部署(1)项目结构(2)配置开发环境(OpenCV+OpenCL+base-utils+TNN)(3)......
  • 如何使用Python爬虫爬取电视剧数据
    要使用爬虫爬取电视剧数据,可以按照以下步骤进行:导入所需的库:使用Python的requests库进行网络请求,使用BeautifulSoup库进行HTML解析。importrequestsfrombs4importBeautifulSouphttp://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP获取;发送网络请求并获取HTML页面:使用re......
  • python从网络摄像头获取rstp视频流并截取图片保存
    def get_img_from_camera_net(folder_path):    cap = cv2.VideoCapture("rtsp://admin:[email protected]/ch1/stream1")#获取网络摄像机        i = 1    while i<3:        ret,frame = cap.read()        cv2.imshow("capture......
  • Python消息队列之Huey
    缘起:之前在Python中使用最多的就是Celery,同样的在这次项目中使用了Celery+eventlet的方式,但是由于具体执行的逻辑是使用的异步编写的,当时就出现了一个问题,当使用httpx的AsyncClient发送一个网络请求的时候,发生了阻塞,导致整个程序无法完整执行.于是就找替代方案,于是......
  • 【python爬虫课程设计】实习僧——数据分析与可视化
    实习僧数据分析与可视化选题背景随着中国经济的不断发展,实习市场也变得日益重要。学生们在求学期间通过实习获取工作经验,而企业则通过实习生计划发现并培养潜在的人才。实习僧作为一家专注于实习和校园招聘的在线平台,收集了大量的实习相关数据。通过对实习僧的数据进行爬取和......