From da0650ec2131d5047acc63b708df2ba97fc1d3d3 Mon Sep 17 00:00:00 2001
From: wuyefeilin <30919197+wuyefeilin@users.noreply.github.com>
Date: Mon, 11 May 2020 23:22:50 +0800
Subject: [PATCH] reorganize HumanSeg contrib folder (#237)
---
contrib/HumanSeg/README.md | 147 ++++++-
contrib/HumanSeg/__init__.py | 25 --
contrib/HumanSeg/data/download_data.py | 33 ++
contrib/HumanSeg/datasets/dataset.py | 2 +-
contrib/HumanSeg/deploy/README.md | 13 +-
contrib/HumanSeg/deploy/python/README.md | 2 +-
.../deploy/python/infer_resizebylong.py | 365 ------------------
contrib/HumanSeg/export.py | 28 ++
contrib/HumanSeg/{human_infer.py => infer.py} | 36 +-
contrib/HumanSeg/main.py | 57 ---
contrib/HumanSeg/models/__init__.py | 1 -
contrib/HumanSeg/models/humanseg.py | 176 ++++-----
contrib/HumanSeg/models/load_model.py | 12 +-
contrib/HumanSeg/nets/backbone/xception.py | 8 +-
.../download_pretrained_weights.py | 38 ++
contrib/HumanSeg/quant_offline.py | 73 ++++
contrib/HumanSeg/quant_online.py | 135 +++++++
contrib/HumanSeg/requirements.txt | 10 +
contrib/HumanSeg/setup.py | 28 --
contrib/HumanSeg/train.py | 148 +++++++
contrib/HumanSeg/tutorial/export_demo.py | 3 -
contrib/HumanSeg/tutorial/infer_demo.py | 7 -
contrib/HumanSeg/tutorial/train_demo.py | 51 ---
contrib/HumanSeg/tutorial/val_demo.py | 22 --
contrib/HumanSeg/utils/__init__.py | 2 +-
.../HumanSeg/utils/humanseg_postprocess.py | 163 ++++++++
contrib/HumanSeg/utils/logging.py | 4 +-
contrib/HumanSeg/utils/post_quantization.py | 2 +-
contrib/HumanSeg/utils/utils.py | 4 +-
contrib/HumanSeg/val.py | 56 +++
contrib/HumanSeg/video_infer.py | 87 +++++
contrib/RealTimeHumanSeg/README.md | 28 --
contrib/RealTimeHumanSeg/cpp/CMakeLists.txt | 221 -----------
.../RealTimeHumanSeg/cpp/CMakeSettings.json | 42 --
contrib/RealTimeHumanSeg/cpp/README.md | 15 -
.../RealTimeHumanSeg/cpp/docs/linux_build.md | 86 -----
.../cpp/docs/windows_build.md | 83 ----
contrib/RealTimeHumanSeg/cpp/humanseg.cc | 132 -------
contrib/RealTimeHumanSeg/cpp/humanseg.h | 66 ----
.../cpp/humanseg_postprocess.cc | 282 --------------
.../cpp/humanseg_postprocess.h | 34 --
contrib/RealTimeHumanSeg/cpp/linux_build.sh | 31 --
contrib/RealTimeHumanSeg/cpp/main.cc | 92 -----
contrib/RealTimeHumanSeg/python/README.md | 61 ---
contrib/RealTimeHumanSeg/python/infer.py | 345 -----------------
.../RealTimeHumanSeg/python/requirements.txt | 2 -
46 files changed, 1036 insertions(+), 2222 deletions(-)
delete mode 100644 contrib/HumanSeg/__init__.py
create mode 100644 contrib/HumanSeg/data/download_data.py
delete mode 100644 contrib/HumanSeg/deploy/python/infer_resizebylong.py
create mode 100644 contrib/HumanSeg/export.py
rename contrib/HumanSeg/{human_infer.py => infer.py} (70%)
delete mode 100644 contrib/HumanSeg/main.py
create mode 100644 contrib/HumanSeg/pretrained_weights/download_pretrained_weights.py
create mode 100644 contrib/HumanSeg/quant_offline.py
create mode 100644 contrib/HumanSeg/quant_online.py
create mode 100644 contrib/HumanSeg/requirements.txt
delete mode 100644 contrib/HumanSeg/setup.py
create mode 100644 contrib/HumanSeg/train.py
delete mode 100644 contrib/HumanSeg/tutorial/export_demo.py
delete mode 100644 contrib/HumanSeg/tutorial/infer_demo.py
delete mode 100644 contrib/HumanSeg/tutorial/train_demo.py
delete mode 100644 contrib/HumanSeg/tutorial/val_demo.py
create mode 100644 contrib/HumanSeg/utils/humanseg_postprocess.py
create mode 100644 contrib/HumanSeg/val.py
create mode 100644 contrib/HumanSeg/video_infer.py
delete mode 100644 contrib/RealTimeHumanSeg/README.md
delete mode 100644 contrib/RealTimeHumanSeg/cpp/CMakeLists.txt
delete mode 100644 contrib/RealTimeHumanSeg/cpp/CMakeSettings.json
delete mode 100644 contrib/RealTimeHumanSeg/cpp/README.md
delete mode 100644 contrib/RealTimeHumanSeg/cpp/docs/linux_build.md
delete mode 100644 contrib/RealTimeHumanSeg/cpp/docs/windows_build.md
delete mode 100644 contrib/RealTimeHumanSeg/cpp/humanseg.cc
delete mode 100644 contrib/RealTimeHumanSeg/cpp/humanseg.h
delete mode 100644 contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.cc
delete mode 100644 contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.h
delete mode 100644 contrib/RealTimeHumanSeg/cpp/linux_build.sh
delete mode 100644 contrib/RealTimeHumanSeg/cpp/main.cc
delete mode 100644 contrib/RealTimeHumanSeg/python/README.md
delete mode 100644 contrib/RealTimeHumanSeg/python/infer.py
delete mode 100644 contrib/RealTimeHumanSeg/python/requirements.txt
diff --git a/contrib/HumanSeg/README.md b/contrib/HumanSeg/README.md
index 0e1fd3b1..6539b9f9 100644
--- a/contrib/HumanSeg/README.md
+++ b/contrib/HumanSeg/README.md
@@ -1,6 +1,147 @@
# HumanSeg
-## 环境
-将contrib目录加入环境变量PYTHONPATH
+本教程旨在通过paddlepaddle框架实现人像分割从训练到部署的流程。
-## 训练、验证、预测、模型导出参见[turtorial](./turtorial)
+HumanSeg从复杂到简单提供三种人像分割模型:HumanSegServer、HumanSegMobile、HumanSegLite,
+HumanSegServer适用于服务端,HumanSegMobile和HumanSegLite适用于移动端。
+
+## 环境依赖
+
+* PaddlePaddle >= 1.7.0 或develop版本
+* Python 3.5+
+
+通过以下命令安装python包依赖,请确保在该分支上至少执行过一次以下命令
+```shell
+$ pip install -r requirements.txt
+```
+
+## 模型
+| 模型类型 | 预训练模型 | 导出模型 | 量化模型 | 说明 |
+| --- | --- | --- | --- | --- |
+| HumanSegServer | [humanseg_server]() | [humanseg_server_export]() | [humanseg_server_quant]() | 服务端GPU环境 |
+| HumanSegMobile | [humanseg_mobile]() | [humanseg_mobile_export]() | [humanseg_mobile_quant]() | 小模型, 适合轻量级计算环境 |
+| HumanSegLite | [humanseg_lite]() | [humanseg_lite_export]() | [humanseg_lite_quant]() | 小模型, 适合轻量级计算环境 |
+
+## 视频流分割
+```bash
+python video_infer.py --model_dir path/to/model_dir
+```
+
+## 准备训练数据
+我们提供了一份demo数据集,通过运行以下代码进行下载,该数据集是从supervise.ly抽取的一个小数据集。
+
+```bash
+python data/download_data.py
+```
+
+## 下载预训练模型
+运行以下代码进行预训练模型的下载
+```bash
+python pretrained_weights/download_pretrained_weights.py
+```
+
+## 训练
+使用下述命令进行训练
+```bash
+CUDA_VISIBLE_DEVICES=0 && python train.py --model_type HumanSegMobile \
+--save_dir output/ \
+--data_dir data/mini_supervisely \
+--train_list data/mini_supervisely/train.txt \
+--val_list data/mini_supervisely/val.txt \
+--pretrained_weights pretrained_weights/humanseg_Mobile \
+--batch_size 8 \
+--learning_rate 0.001 \
+--num_epochs 10 \
+--save_interval_epochs 2
+```
+其中参数含义如下:
+* `--model_type`: 模型类型,可选项为:HumanSegServer、HumanSegMobile和HumanSegLite
+* `--save_dir`: 模型保存路径
+* `--data_dir`: 数据集路径
+* `--train_list`: 训练集列表路径
+* `--val_list`: 验证集列表路径
+* `--pretrained_weights`: 预训练模型路径
+* `--batch_size`: 批大小
+* `--learning_rate`: 初始学习率
+* `--num_epochs`: 训练轮数
+* `--save_interval_epochs`: 模型保存间隔
+
+更多参数请运行下述命令进行参看:
+```bash
+python train.py --help
+```
+
+## 评估
+使用下述命令进行评估
+```bash
+python val.py --model_dir output/best_model \
+--data_dir data/mini_supervisely \
+--val_list data/mini_supervisely/val.txt \
+--batch_size 2
+```
+其中参数含义如下:
+* `--model_dir`: 模型路径
+* `--data_dir`: 数据集路径
+* `--val_list`: 验证集列表路径
+* `--batch_size`: 批大小
+
+## 预测
+使用下述命令进行预测
+```bash
+python infer.py --model_dir output/best_model \
+--data_dir data/mini_supervisely \
+--test_list data/mini_supervisely/test.txt
+```
+其中参数含义如下:
+* `--model_dir`: 模型路径
+* `--data_dir`: 数据集路径
+* `--test_list`: 测试集列表路径
+
+## 模型导出
+```bash
+python export.py --model_dir output/best_model \
+--save_dir output/export
+```
+其中参数含义如下:
+* `--model_dir`: 模型路径
+* `--data_dir`: 数据集路径
+* `--save_dir`: 导出模型保存路径
+
+## 离线量化
+```bash
+python quant_offline.py --model_dir output/best_model \
+--data_dir data/mini_supervisely \
+--quant_list data/mini_supervisely/val.txt \
+--save_dir output/quant_offline
+```
+其中参数含义如下:
+* `--model_dir`: 待量化模型路径
+* `--data_dir`: 数据集路径
+* `--quant_list`: 量化数据集列表路径,一般直接选择训练集或验证集
+* `--save_dir`: 量化模型保存路径
+
+## 在线量化
+利用float训练模型进行在线量化。
+```bash
+python quant_online.py --model_type HumanSegMobile \
+--save_dir output/quant_online \
+--data_dir data/mini_supervisely \
+--train_list data/mini_supervisely/train.txt \
+--val_list data/mini_supervisely/val.txt \
+--pretrained_weights output/best_model \
+--batch_size 2 \
+--learning_rate 0.001 \
+--num_epochs 2 \
+--save_interval_epochs 1
+```
+其中参数含义如下:
+* `--model_type`: 模型类型,可选项为:HumanSegServer、HumanSegMobile和HumanSegLite
+* `--save_dir`: 模型保存路径
+* `--data_dir`: 数据集路径
+* `--train_list`: 训练集列表路径
+* `--val_list`: 验证集列表路径
+* `--pretrained_weights`: 预训练模型路径,
+* `--batch_size`: 批大小
+* `--learning_rate`: 初始学习率
+* `--num_epochs`: 训练轮数
+* `--save_interval_epochs`: 模型保存间隔
diff --git a/contrib/HumanSeg/__init__.py b/contrib/HumanSeg/__init__.py
deleted file mode 100644
index c50c9945..00000000
--- a/contrib/HumanSeg/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from . import utils
-from . import nets
-from . import models
-from . import datasets
-from . import transforms
-from .utils import get_environ_info
-
-env_info = get_environ_info()
-
-log_level = 2
-__version__ = '1.0.0.github'
diff --git a/contrib/HumanSeg/data/download_data.py b/contrib/HumanSeg/data/download_data.py
new file mode 100644
index 00000000..cce0e540
--- /dev/null
+++ b/contrib/HumanSeg/data/download_data.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import os
+
+LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
+TEST_PATH = os.path.join(LOCAL_PATH, "../../../", "test")
+sys.path.append(TEST_PATH)
+
+from test_utils import download_file_and_uncompress
+
+
+def download_pet_dataset(savepath, extrapath):
+ url = "https://paddleseg.bj.bcebos.com/dataset/mini_supervisely.zip"
+ download_file_and_uncompress(
+ url=url, savepath=savepath, extrapath=extrapath)
+
+
+if __name__ == "__main__":
+ download_pet_dataset(LOCAL_PATH, LOCAL_PATH)
+ print("Dataset download finish!")
diff --git a/contrib/HumanSeg/datasets/dataset.py b/contrib/HumanSeg/datasets/dataset.py
index 2c707a31..263c7af4 100644
--- a/contrib/HumanSeg/datasets/dataset.py
+++ b/contrib/HumanSeg/datasets/dataset.py
@@ -23,7 +23,7 @@ import copy
import random
import platform
import chardet
-import HumanSeg.utils.logging as logging
+import utils.logging as logging
class EndSignal():
diff --git a/contrib/HumanSeg/deploy/README.md b/contrib/HumanSeg/deploy/README.md
index a36188e2..b5baf00a 100644
--- a/contrib/HumanSeg/deploy/README.md
+++ b/contrib/HumanSeg/deploy/README.md
@@ -1,6 +1,6 @@
-# 实时人像分割预测部署
+# 人像分割预测部署
-本模型基于飞浆开源的人像分割模型,并做了大量的针对视频的光流追踪优化,提供了完整的支持视频流的实时人像分割解决方案,并提供了高性能的`Python`集成部署方案。
+本模型基于飞浆开源的人像分割模型,并做了大量的针对视频的光流追踪优化,提供了完整的支持视频流的人像分割解决方案,并提供了高性能的`Python`集成部署方案。
## 模型下载
@@ -9,9 +9,12 @@
|模型文件 | 说明 |
| --- | --- |
-|[shv75_deeplab_0303_quant](https://paddleseg.bj.bcebos.com/deploy/models/shv75_0303_quant.zip) | 小模型, 适合轻量级计算环境 |
-|[shv75_deeplab_0303](https://paddleseg.bj.bcebos.com/deploy/models/shv75_deeplab_0303.zip)| 小模型,适合轻量级计算环境 |
-|[deeplabv3_xception_humanseg](https://paddleseg.bj.bcebos.com/deploy/models/deeplabv3_xception_humanseg.zip) | 服务端GPU环境 |
+|[humanseg_lite_quant]() | 小模型, 适合轻量级计算环境 |
+|[humanseg_lite]()| 小模型,适合轻量级计算环境 |
+|[humanseg_mobile_quant]() | 小模型, 适合轻量级计算环境 |
+|[humanseg_mobile]()| 小模型,适合轻量级计算环境 |
+|[humanseg_server_quant]() | 服务端GPU环境 |
+|[humanseg_server]() | 服务端GPU环境 |
**注意:下载后解压到合适的路径,后续该路径将做为预测参数用于加载模型。**
diff --git a/contrib/HumanSeg/deploy/python/README.md b/contrib/HumanSeg/deploy/python/README.md
index 5a12ed12..e5aa6f2f 100644
--- a/contrib/HumanSeg/deploy/python/README.md
+++ b/contrib/HumanSeg/deploy/python/README.md
@@ -1,4 +1,4 @@
-# 实时人像分割Python预测部署方案
+# 人像分割Python预测部署方案
本方案基于Python实现,最小化依赖并把所有模型加载、数据预处理、预测、光流处理等后处理都封装在文件`infer.py`中,用户可以直接使用或集成到自己项目中。
diff --git a/contrib/HumanSeg/deploy/python/infer_resizebylong.py b/contrib/HumanSeg/deploy/python/infer_resizebylong.py
deleted file mode 100644
index d4c3a4e8..00000000
--- a/contrib/HumanSeg/deploy/python/infer_resizebylong.py
+++ /dev/null
@@ -1,365 +0,0 @@
-# coding: utf8
-# copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""实时人像分割Python预测部署"""
-
-import os
-import argparse
-import numpy as np
-import cv2
-
-import paddle.fluid as fluid
-
-
-def humanseg_tracking(pre_gray, cur_gray, prev_cfd, dl_weights, disflow):
- """计算光流跟踪匹配点和光流图
- 输入参数:
- pre_gray: 上一帧灰度图
- cur_gray: 当前帧灰度图
- prev_cfd: 上一帧光流图
- dl_weights: 融合权重图
- disflow: 光流数据结构
- 返回值:
- is_track: 光流点跟踪二值图,即是否具有光流点匹配
- track_cfd: 光流跟踪图
- """
- check_thres = 8
- hgt, wdh = pre_gray.shape[:2]
- track_cfd = np.zeros_like(prev_cfd)
- is_track = np.zeros_like(pre_gray)
- # 计算前向光流
- flow_fw = disflow.calc(pre_gray, cur_gray, None)
- # 计算后向光流
- flow_bw = disflow.calc(cur_gray, pre_gray, None)
- get_round = lambda data: (int)(data + 0.5) if data >= 0 else (int)(data -
- 0.5)
- for row in range(hgt):
- for col in range(wdh):
- # 计算光流处理后对应点坐标
- # (row, col) -> (cur_x, cur_y)
- fxy_fw = flow_fw[row, col]
- dx_fw = get_round(fxy_fw[0])
- cur_x = dx_fw + col
- dy_fw = get_round(fxy_fw[1])
- cur_y = dy_fw + row
- if cur_x < 0 or cur_x >= wdh or cur_y < 0 or cur_y >= hgt:
- continue
- fxy_bw = flow_bw[cur_y, cur_x]
- dx_bw = get_round(fxy_bw[0])
- dy_bw = get_round(fxy_bw[1])
- # 光流移动小于阈值
- lmt = ((dy_fw + dy_bw) * (dy_fw + dy_bw) +
- (dx_fw + dx_bw) * (dx_fw + dx_bw))
- if lmt >= check_thres:
- continue
- # 静止点降权
- if abs(dy_fw) <= 0 and abs(dx_fw) <= 0 and abs(dy_bw) <= 0 and abs(
- dx_bw) <= 0:
- dl_weights[cur_y, cur_x] = 0.05
- is_track[cur_y, cur_x] = 1
- track_cfd[cur_y, cur_x] = prev_cfd[row, col]
- return track_cfd, is_track, dl_weights
-
-
-def humanseg_track_fuse(track_cfd, dl_cfd, dl_weights, is_track):
- """光流追踪图和人像分割结构融合
- 输入参数:
- track_cfd: 光流追踪图
- dl_cfd: 当前帧分割结果
- dl_weights: 融合权重图
- is_track: 光流点匹配二值图
- 返回值:
- cur_cfd: 光流跟踪图和人像分割结果融合图
- """
- cur_cfd = dl_cfd.copy()
- idxs = np.where(is_track > 0)
- for i in range(len(idxs)):
- x, y = idxs[0][i], idxs[1][i]
- dl_score = dl_cfd[y, x]
- track_score = track_cfd[y, x]
- if dl_score > 0.9 or dl_score < 0.1:
- if dl_weights[x, y] < 0.1:
- cur_cfd[x, y] = 0.3 * dl_score + 0.7 * track_score
- else:
- cur_cfd[x, y] = 0.4 * dl_score + 0.6 * track_score
- else:
- cur_cfd[x, y] = dl_weights[x, y] * dl_score + (
- 1 - dl_weights[x, y]) * track_score
- return cur_cfd
-
-
-def threshold_mask(img, thresh_bg, thresh_fg):
- """设置背景和前景阈值mask
- 输入参数:
- img : 原始图像, np.uint8 类型.
- thresh_bg : 背景阈值百分比,低于该值置为0.
- thresh_fg : 前景阈值百分比,超过该值置为1.
- 返回值:
- dst : 原始图像设置完前景背景阈值mask结果, np.float32 类型.
- """
- dst = (img / 255.0 - thresh_bg) / (thresh_fg - thresh_bg)
- dst[np.where(dst > 1)] = 1
- dst[np.where(dst < 0)] = 0
- return dst.astype(np.float32)
-
-
-def optflow_handle(cur_gray, scoremap, is_init):
- """光流优化
- Args:
- cur_gray : 当前帧灰度图
- scoremap : 当前帧分割结果
- is_init : 是否第一帧
- Returns:
- dst : 光流追踪图和预测结果融合图, 类型为 np.float32
- """
- width, height = scoremap.shape[0], scoremap.shape[1]
- disflow = cv2.DISOpticalFlow_create(cv2.DISOPTICAL_FLOW_PRESET_ULTRAFAST)
- prev_gray = np.zeros((height, width), np.uint8)
- prev_cfd = np.zeros((height, width), np.float32)
- cur_cfd = scoremap.copy()
- if is_init:
- is_init = False
- if height <= 64 or width <= 64:
- disflow.setFinestScale(1)
- elif height <= 160 or width <= 160:
- disflow.setFinestScale(2)
- else:
- disflow.setFinestScale(3)
- fusion_cfd = cur_cfd
- else:
- weights = np.ones((width, height), np.float32) * 0.3
- track_cfd, is_track, weights = humanseg_tracking(
- prev_gray, cur_gray, prev_cfd, weights, disflow)
- fusion_cfd = humanseg_track_fuse(track_cfd, cur_cfd, weights, is_track)
- fusion_cfd = cv2.GaussianBlur(fusion_cfd, (3, 3), 0)
- return fusion_cfd
-
-
-class HumanSeg:
- """人像分割类
- 封装了人像分割模型的加载,数据预处理,预测,后处理等
- """
-
- def __init__(self, model_dir, mean, scale, long_size, use_gpu=False):
-
- self.mean = np.array(mean).reshape((3, 1, 1))
- self.scale = np.array(scale).reshape((3, 1, 1))
- self.long_size = long_size
- self.load_model(model_dir, use_gpu)
-
- def load_model(self, model_dir, use_gpu):
- """加载模型并创建predictor
- Args:
- model_dir: 预测模型路径, 包含 `__model__` 和 `__params__`
- use_gpu: 是否使用GPU加速
- """
- prog_file = os.path.join(model_dir, '__model__')
- params_file = os.path.join(model_dir, '__params__')
- config = fluid.core.AnalysisConfig(prog_file, params_file)
- if use_gpu:
- config.enable_use_gpu(100, 0)
- config.switch_ir_optim(True)
- else:
- config.disable_gpu()
- config.disable_glog_info()
- config.switch_specify_input_names(True)
- config.enable_memory_optim()
- self.predictor = fluid.core.create_paddle_predictor(config)
-
- def preprocess(self, image):
- """图像预处理
- hwc_rgb 转换为 chw_bgr,并进行归一化
- 输入参数:
- image: 原始图像
- 返回值:
- 经过预处理后的图片结果
- """
- origin_h, origin_w = image.shape[0], image.shape[1]
- scale = float(self.long_size) / max(origin_w, origin_h)
- resize_w = int(round(origin_w * scale))
- resize_h = int(round(origin_h * scale))
- img_mat = cv2.resize(
- image, (resize_w, resize_h), interpolation=cv2.INTER_LINEAR)
- pad_h = self.long_size - resize_h
- pad_w = self.long_size - resize_w
- img_mat = cv2.copyMakeBorder(
- img_mat,
- 0,
- pad_h,
- 0,
- pad_w,
- cv2.BORDER_CONSTANT,
- value=[127.5, 127.5, 127.5])
-
- # HWC -> CHW
- img_mat = img_mat.swapaxes(1, 2)
- img_mat = img_mat.swapaxes(0, 1)
- # Convert to float
- img_mat = img_mat[:, :, :].astype('float32')
- img_mat = (img_mat / 255. - self.mean) / self.scale
- img_mat = img_mat[np.newaxis, :, :, :]
- return img_mat
-
- def postprocess(self, image, output_data):
- """对预测结果进行后处理
- Args:
- image: 原始图,opencv 图片对象
- output_data: Paddle预测结果原始数据
- Returns:
- 原图和预测结果融合并做了光流优化的结果图
- """
- scoremap = output_data[0, 1, :, :]
- scoremap = (scoremap * 255).astype(np.uint8)
- # 光流处理
- cur_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
- origin_h, origin_w = image.shape[0], image.shape[1]
- scale = float(self.long_size) / max(origin_w, origin_h)
- resize_w = int(round(origin_w * scale))
- resize_h = int(round(origin_h * scale))
- cur_gray = cv2.resize(
- cur_gray, (resize_w, resize_h), interpolation=cv2.INTER_LINEAR)
- pad_h = self.long_size - resize_h
- pad_w = self.long_size - resize_w
- cur_gray = cv2.copyMakeBorder(
- cur_gray, 0, pad_h, 0, pad_w, cv2.BORDER_CONSTANT, value=127.5)
- optflow_map = optflow_handle(cur_gray, scoremap, False)
- optflow_map = cv2.GaussianBlur(optflow_map, (3, 3), 0)
- optflow_map = threshold_mask(optflow_map, thresh_bg=0.2, thresh_fg=0.8)
- optflow_map = optflow_map[0:resize_h, 0:resize_w]
- optflow_map = cv2.resize(optflow_map, (origin_w, origin_h))
- optflow_map = np.repeat(optflow_map[:, :, np.newaxis], 3, axis=2)
- bg_im = np.ones_like(optflow_map) * 255
- comb = (optflow_map * image + (1 - optflow_map) * bg_im).astype(
- np.uint8)
- return comb
-
- def run_predict(self, image):
- """运行预测并返回可视化结果图
- 输入参数:
- image: 需要预测的原始图, opencv图片对象
- 返回值:
- 可视化的预测结果图
- """
- im_mat = self.preprocess(image)
- im_tensor = fluid.core.PaddleTensor(im_mat.copy().astype('float32'))
- output_data = self.predictor.run([im_tensor])[1]
- output_data = output_data.as_ndarray()
- return self.postprocess(image, output_data)
-
- def image_segment(self, path):
- """对图片文件进行分割
- 结果保存到`result.jpeg`文件中
- """
- img_mat = cv2.imread(path)
- img_mat = self.run_predict(img_mat)
- cv2.imwrite('result.jpeg', img_mat)
-
- def video_segment(self, path=None):
- """
- 对视屏流进行分割,
- path为None时默认打开摄像头。
- """
- if path is None:
- cap = cv2.VideoCapture(0)
- else:
- cap = cv2.VideoCapture(path)
- if not cap.isOpened():
- raise IOError("Error opening video stream or file")
- return
-
- if path is not None:
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
- fps = cap.get(cv2.CAP_PROP_FPS)
- # 用于保存预测结果视频
- out = cv2.VideoWriter('result.avi',
- cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'),
- fps, (width, height))
- # 开始获取视频帧
- while cap.isOpened():
- ret, frame = cap.read()
- if ret:
- img_mat = self.run_predict(frame)
- out.write(img_mat)
- else:
- break
- cap.release()
- out.release()
-
- else:
- while cap.isOpened():
- ret, frame = cap.read()
- if ret:
- img_mat = self.run_predict(frame)
- cv2.imshow('HumanSegmentation', img_mat)
- if cv2.waitKey(1) & 0xFF == ord('q'):
- break
- else:
- break
- cap.release()
-
-
-def main(args):
- """预测程序入口
- 完成模型加载, 对视频、摄像头、图片文件等预测过程
- """
- model_dir = args.model_dir
- use_gpu = args.use_gpu
-
- # 加载模型
- mean = [0.5, 0.5, 0.5]
- scale = [0.5, 0.5, 0.5]
- long_size = 192
- model = HumanSeg(model_dir, mean, scale, long_size, use_gpu)
- if args.use_camera:
- # 开启摄像头
- model.video_segment()
- elif args.video_path:
- # 使用视频文件作为输入
- model.video_segment(args.video_path)
- elif args.img_path:
- # 使用图片文件作为输入
- model.image_segment(args.img_path)
- else:
- raise ValueError(
- 'One of (--model_dir, --video_path, --use_camera) should be given.')
-
-
-def parse_args():
- """解析命令行参数
- """
- parser = argparse.ArgumentParser('Realtime Human Segmentation')
- parser.add_argument(
- '--model_dir',
- type=str,
- default='',
- help='path of human segmentation model')
- parser.add_argument(
- '--img_path', type=str, default='', help='path of input image')
- parser.add_argument(
- '--video_path', type=str, default='', help='path of input video')
- parser.add_argument(
- '--use_camera',
- type=bool,
- default=False,
- help='input video stream from camera')
- parser.add_argument(
- '--use_gpu', type=bool, default=False, help='enable gpu')
- return parser.parse_args()
-
-
-if __name__ == "__main__":
- args = parse_args()
- main(args)
diff --git a/contrib/HumanSeg/export.py b/contrib/HumanSeg/export.py
new file mode 100644
index 00000000..6fcae141
--- /dev/null
+++ b/contrib/HumanSeg/export.py
@@ -0,0 +1,28 @@
+import models
+import argparse
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='Export model')
+ parser.add_argument(
+ '--model_dir',
+ dest='model_dir',
+ help='Model path for exporting',
+ type=str)
+ parser.add_argument(
+ '--save_dir',
+ dest='save_dir',
+ help='The directory for saving the export model',
+ type=str,
+ default='./output/export')
+ return parser.parse_args()
+
+
+def export(args):
+ model = models.load_model(args.model_dir)
+ model.export_inference_model(args.save_dir)
+
+
+if __name__ == '__main__':
+ args = parse_args()
+ export(args)
diff --git a/contrib/HumanSeg/human_infer.py b/contrib/HumanSeg/infer.py
similarity index 70%
rename from contrib/HumanSeg/human_infer.py
rename to contrib/HumanSeg/infer.py
index 0764aabb..3e5ac836 100644
--- a/contrib/HumanSeg/human_infer.py
+++ b/contrib/HumanSeg/infer.py
@@ -5,30 +5,35 @@ import cv2
import numpy as np
import tqdm
-import HumanSeg
+import utils
+import models
+import transforms
def parse_args():
parser = argparse.ArgumentParser(
description='HumanSeg inference and visualization')
parser.add_argument(
- '--test_model',
- dest='test_model',
- help='model path for inference',
+ '--model_dir',
+ dest='model_dir',
+ help='Model path for inference',
type=str)
parser.add_argument(
'--data_dir',
dest='data_dir',
- help='the root directory of dataset',
+ help='The root directory of dataset',
type=str)
parser.add_argument(
- '--file_list', dest='file_list', help='file list for test', type=str)
+ '--test_list',
+ dest='test_list',
+ help='Test list file of dataset',
+ type=str)
parser.add_argument(
'--save_dir',
dest='save_dir',
- help='the directory for saveing the inferenc results',
+ help='The directory for saving the inference results',
type=str,
- default='./result')
+ default='./output/result')
return parser.parse_args()
@@ -38,23 +43,26 @@ def mkdir(path):
os.makedirs(sub_dir)
-def process(args):
- model = HumanSeg.models.load_model(args.test_model)
+def infer(args):
+ test_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+ model = models.load_model(args.model_dir)
added_saveed_path = osp.join(args.save_dir, 'added')
mat_saved_path = osp.join(args.save_dir, 'mat')
scoremap_saved_path = osp.join(args.save_dir, 'scoremap')
- with open(args.file_list, 'r') as f:
+ with open(args.test_list, 'r') as f:
files = f.readlines()
for file in tqdm.tqdm(files):
file = file.strip()
im_file = osp.join(args.data_dir, file)
im = cv2.imread(im_file)
- result = model.predict(im)
+ result = model.predict(im, transforms=test_transforms)
# save added image
- added_image = HumanSeg.utils.visualize(im_file, result, weight=0.6)
+ added_image = utils.visualize(im_file, result, weight=0.6)
added_image_file = osp.join(added_saveed_path, file)
mkdir(added_image_file)
cv2.imwrite(added_image_file, added_image)
@@ -78,4 +86,4 @@ def process(args):
if __name__ == '__main__':
args = parse_args()
- process(args)
+ infer(args)
diff --git a/contrib/HumanSeg/main.py b/contrib/HumanSeg/main.py
deleted file mode 100644
index 53cbe0b7..00000000
--- a/contrib/HumanSeg/main.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import os
-import numpy as np
-from HumanSeg.datasets.dataset import Dataset
-from HumanSeg.models import HumanSegMobile
-from HumanSeg.transforms import transforms
-
-train_transforms = transforms.Compose([
- transforms.RandomHorizontalFlip(),
- transforms.Resize((192, 192)),
- transforms.Normalize()
-])
-
-eval_transforms = transforms.Compose(
- [transforms.Resize((192, 192)),
- transforms.Normalize()])
-
-data_dir = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly'
-train_list = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/train.txt'
-val_list = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/val.txt'
-
-train_dataset = Dataset(
- data_dir=data_dir,
- file_list=train_list,
- transforms=train_transforms,
- num_workers='auto',
- buffer_size=100,
- parallel_method='thread',
- shuffle=True)
-
-eval_dataset = Dataset(
- data_dir=data_dir,
- file_list=val_list,
- transforms=eval_transforms,
- num_workers='auto',
- buffer_size=100,
- parallel_method='thread',
- shuffle=False)
-
-model = HumanSegMobile(num_classes=2)
-
-model.train(
- num_epochs=100,
- train_dataset=train_dataset,
- eval_dataset=eval_dataset,
- save_interval_epochs=5,
- train_batch_size=256,
- # resume_weights='/Users/chenguowei01/PycharmProjects/github/PaddleSeg/contrib/HumanSeg/output/epoch_20',
- log_interval_steps=2,
- save_dir='output',
- use_vdl=True,
-)
-
-model.evaluate(eval_dataset, batch_size=10)
-im_file = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/images/8d308c9cc0326a3bdfc90f7f6e1813df89786122.jpg'
-result = model.predict(im_file)
-import cv2
-cv2.imwrite('pred.png', result['label_map'] * 200)
diff --git a/contrib/HumanSeg/models/__init__.py b/contrib/HumanSeg/models/__init__.py
index cbd15db2..02704a07 100644
--- a/contrib/HumanSeg/models/__init__.py
+++ b/contrib/HumanSeg/models/__init__.py
@@ -1,5 +1,4 @@
from .humanseg import HumanSegMobile
from .humanseg import HumanSegServer
from .humanseg import HumanSegLite
-from .humanseg import HRNet
from .load_model import load_model
diff --git a/contrib/HumanSeg/models/humanseg.py b/contrib/HumanSeg/models/humanseg.py
index 93e0064c..cca23954 100644
--- a/contrib/HumanSeg/models/humanseg.py
+++ b/contrib/HumanSeg/models/humanseg.py
@@ -26,10 +26,13 @@ import cv2
import yaml
import paddleslim as slim
-import HumanSeg
-import HumanSeg.utils.logging as logging
-from HumanSeg.utils import seconds_to_hms
-from HumanSeg.utils import ConfusionMatrix
+import utils
+import utils.logging as logging
+from utils import seconds_to_hms
+from utils import ConfusionMatrix
+from utils import get_environ_info
+from nets import DeepLabv3p, ShuffleSeg, HRNet
+import transforms as T
def dict2str(dict_input):
@@ -81,8 +84,8 @@ class SegModel(object):
self.sync_bn = sync_bn
self.labels = None
- self.version = HumanSeg.__version__
- if HumanSeg.env_info['place'] == 'cpu':
+ self.env_info = get_environ_info()
+ if self.env_info['place'] == 'cpu':
self.places = fluid.cpu_places()
else:
self.places = fluid.cuda_places()
@@ -105,8 +108,8 @@ class SegModel(object):
else:
raise Exception("Please support correct batch_size, \
which can be divided by available cards({}) in {}".
- format(HumanSeg.env_info['num'],
- HumanSeg.env_info['place']))
+ format(self.env_info['num'],
+ self.env_info['place']))
def build_net(self, mode='train'):
"""应根据不同的情况进行构建"""
@@ -127,7 +130,7 @@ class SegModel(object):
self.test_prog = self.test_prog.clone(for_test=True)
def arrange_transform(self, transforms, mode='train'):
- arrange_transform = HumanSeg.transforms.transforms.ArrangeSegmenter
+ arrange_transform = T.ArrangeSegmenter
if type(transforms.transforms[-1]).__name__.startswith('Arrange'):
transforms.transforms[-1] = arrange_transform(mode=mode)
else:
@@ -148,7 +151,7 @@ class SegModel(object):
def net_initialize(self,
startup_prog=None,
- pretrain_weights=None,
+ pretrained_weights=None,
resume_weights=None):
if startup_prog is None:
startup_prog = fluid.default_startup_program()
@@ -171,16 +174,15 @@ class SegModel(object):
raise ValueError("Resume model path is not valid!")
logging.info("Model checkpoint loaded successfully!")
- elif pretrain_weights is not None:
+ elif pretrained_weights is not None:
logging.info(
- "Load pretrain weights from {}.".format(pretrain_weights))
- HumanSeg.utils.utils.load_pretrain_weights(
- self.exe, self.train_prog, pretrain_weights)
+ "Load pretrain weights from {}.".format(pretrained_weights))
+ utils.load_pretrained_weights(self.exe, self.train_prog,
+ pretrained_weights)
def get_model_info(self):
# 存储相应的信息到yml文件
info = dict()
- info['version'] = HumanSeg.__version__
info['Model'] = self.__class__.__name__
if 'self' in self.init_params:
del self.init_params['self']
@@ -226,6 +228,8 @@ class SegModel(object):
del self.train_init['train_dataset']
if 'eval_dataset' in self.train_init:
del self.train_init['eval_dataset']
+ if 'optimizer' in self.train_init:
+ del self.train_init['optimizer']
info['train_init'] = self.train_init
return info
@@ -307,11 +311,11 @@ class SegModel(object):
save_dir,
batch_size=1,
batch_nums=10,
- cache_dir="./temp"):
+ cache_dir="./.temp"):
self.arrange_transform(transforms=dataset.transforms, mode='quant')
dataset.num_samples = batch_size * batch_nums
try:
- from HumanSeg.utils import HumanSegPostTrainingQuantization
+ from utils import HumanSegPostTrainingQuantization
except:
raise Exception(
"Model Quantization is not available, try to upgrade your paddlepaddle>=1.7.0"
@@ -335,6 +339,8 @@ class SegModel(object):
cache_dir=cache_dir)
post_training_quantization.quantize()
post_training_quantization.save_quantized_model(save_dir)
+ if cache_dir is not None:
+ os.system('rm -r' + cache_dir)
model_info = self.get_model_info()
model_info['status'] = 'Quant'
@@ -383,7 +389,7 @@ class SegModel(object):
save_interval_epochs=1,
log_interval_steps=2,
save_dir='output',
- pretrain_weights=None,
+ pretrained_weights=None,
resume_weights=None,
optimizer=None,
learning_rate=0.01,
@@ -408,7 +414,7 @@ class SegModel(object):
self.build_program()
self.net_initialize(
startup_prog=fluid.default_startup_program(),
- pretrain_weights=pretrain_weights,
+ pretrained_weights=pretrained_weights,
resume_weights=resume_weights)
# 进行量化
@@ -451,7 +457,7 @@ class SegModel(object):
# 多卡训练
if self.parallel_train_prog is None:
build_strategy = fluid.compiler.BuildStrategy()
- if HumanSeg.env_info['place'] != 'cpu' and len(self.places) > 1:
+ if self.env_info['place'] != 'cpu' and len(self.places) > 1:
build_strategy.sync_batch_norm = self.sync_bn
exec_strategy = fluid.ExecutionStrategy()
exec_strategy.num_iteration_per_drop_scope = 1
@@ -706,80 +712,11 @@ class SegModel(object):
return {'label_map': pred, 'score_map': logit}
-class HumanSegMobile(SegModel):
- # DeepLab mobilenet
- def __init__(self,
- num_classes=2,
- backbone='MobileNetV2_x1.0',
- output_stride=16,
- aspp_with_sep_conv=True,
- decoder_use_sep_conv=True,
- encoder_with_aspp=False,
- enable_decoder=False,
- use_bce_loss=False,
- use_dice_loss=False,
- class_weight=None,
- ignore_index=255,
- sync_bn=True):
- super().__init__(
- num_classes=num_classes,
- use_bce_loss=use_bce_loss,
- use_dice_loss=use_dice_loss,
- class_weight=class_weight,
- ignore_index=ignore_index,
- sync_bn=sync_bn)
- self.init_params = locals()
-
- self.output_stride = output_stride
-
- if backbone not in [
- 'MobileNetV2_x0.25', 'MobileNetV2_x0.5', 'MobileNetV2_x1.0',
- 'MobileNetV2_x1.5', 'MobileNetV2_x2.0'
- ]:
- raise ValueError(
- "backbone: {} is set wrong. it should be one of "
- "('MobileNetV2_x0.25', 'MobileNetV2_x0.5',"
- " 'MobileNetV2_x1.0', 'MobileNetV2_x1.5', 'MobileNetV2_x2.0')".
- format(backbone))
-
- self.backbone = backbone
- self.aspp_with_sep_conv = aspp_with_sep_conv
- self.decoder_use_sep_conv = decoder_use_sep_conv
- self.encoder_with_aspp = encoder_with_aspp
- self.enable_decoder = enable_decoder
- self.sync_bn = sync_bn
-
- def build_net(self, mode='train'):
- model = HumanSeg.nets.DeepLabv3p(
- self.num_classes,
- mode=mode,
- backbone=self.backbone,
- output_stride=self.output_stride,
- aspp_with_sep_conv=self.aspp_with_sep_conv,
- decoder_use_sep_conv=self.decoder_use_sep_conv,
- encoder_with_aspp=self.encoder_with_aspp,
- enable_decoder=self.enable_decoder,
- use_bce_loss=self.use_bce_loss,
- use_dice_loss=self.use_dice_loss,
- class_weight=self.class_weight,
- ignore_index=self.ignore_index)
- inputs = model.generate_inputs()
- model_out = model.build_net(inputs)
- outputs = OrderedDict()
- if mode == 'train':
- self.optimizer.minimize(model_out)
- outputs['loss'] = model_out
- else:
- outputs['pred'] = model_out[0]
- outputs['logit'] = model_out[1]
- return inputs, outputs
-
-
class HumanSegLite(SegModel):
# DeepLab ShuffleNet
def build_net(self, mode='train'):
"""应根据不同的情况进行构建"""
- model = HumanSeg.nets.ShuffleSeg(
+ model = ShuffleSeg(
self.num_classes,
mode=mode,
use_bce_loss=self.use_bce_loss,
@@ -836,7 +773,7 @@ class HumanSegServer(SegModel):
self.sync_bn = sync_bn
def build_net(self, mode='train'):
- model = HumanSeg.nets.DeepLabv3p(
+ model = DeepLabv3p(
self.num_classes,
mode=mode,
backbone=self.backbone,
@@ -861,21 +798,21 @@ class HumanSegServer(SegModel):
return inputs, outputs
-class HRNet(SegModel):
+class HumanSegMobile(SegModel):
def __init__(self,
num_classes=2,
stage1_num_modules=1,
- stage1_num_blocks=[4],
- stage1_num_channels=[64],
+ stage1_num_blocks=[1],
+ stage1_num_channels=[32],
stage2_num_modules=1,
- stage2_num_blocks=[4, 4],
- stage2_num_channels=[18, 36],
- stage3_num_modules=4,
- stage3_num_blocks=[4, 4, 4],
- stage3_num_channels=[18, 36, 72],
- stage4_num_modules=3,
- stage4_num_blocks=[4, 4, 4, 4],
- stage4_num_channels=[18, 36, 72, 144],
+ stage2_num_blocks=[2, 2],
+ stage2_num_channels=[16, 32],
+ stage3_num_modules=1,
+ stage3_num_blocks=[2, 2, 2],
+ stage3_num_channels=[16, 32, 64],
+ stage4_num_modules=1,
+ stage4_num_blocks=[2, 2, 2, 2],
+ stage4_num_channels=[16, 32, 64, 128],
use_bce_loss=False,
use_dice_loss=False,
class_weight=None,
@@ -905,7 +842,7 @@ class HRNet(SegModel):
def build_net(self, mode='train'):
"""应根据不同的情况进行构建"""
- model = HumanSeg.nets.HRNet(
+ model = HRNet(
self.num_classes,
mode=mode,
stage1_num_modules=self.stage1_num_modules,
@@ -934,3 +871,36 @@ class HRNet(SegModel):
outputs['pred'] = model_out[0]
outputs['logit'] = model_out[1]
return inputs, outputs
+
+ def train(self,
+ num_epochs,
+ train_dataset,
+ train_batch_size=2,
+ eval_dataset=None,
+ save_interval_epochs=1,
+ log_interval_steps=2,
+ save_dir='output',
+ pretrained_weights=None,
+ resume_weights=None,
+ optimizer=None,
+ learning_rate=0.01,
+ lr_decay_power=0.9,
+ regularization_coeff=5e-4,
+ use_vdl=False,
+ quant=False):
+ super().train(
+ num_epochs=num_epochs,
+ train_dataset=train_dataset,
+ train_batch_size=train_batch_size,
+ eval_dataset=eval_dataset,
+ save_interval_epochs=save_interval_epochs,
+ log_interval_steps=log_interval_steps,
+ save_dir=save_dir,
+ pretrained_weights=pretrained_weights,
+ resume_weights=resume_weights,
+ optimizer=optimizer,
+ learning_rate=learning_rate,
+ lr_decay_power=lr_decay_power,
+ regularization_coeff=regularization_coeff,
+ use_vdl=use_vdl,
+ quant=quant)
diff --git a/contrib/HumanSeg/models/load_model.py b/contrib/HumanSeg/models/load_model.py
index a7c4de3b..fc6e3db7 100644
--- a/contrib/HumanSeg/models/load_model.py
+++ b/contrib/HumanSeg/models/load_model.py
@@ -18,8 +18,8 @@ import six
import copy
from collections import OrderedDict
import paddle.fluid as fluid
-import HumanSeg
-import HumanSeg.utils.logging as logging
+import utils.logging as logging
+import models
def load_model(model_dir):
@@ -29,10 +29,10 @@ def load_model(model_dir):
info = yaml.load(f.read(), Loader=yaml.Loader)
status = info['status']
- if not hasattr(HumanSeg.models, info['Model']):
- raise Exception("There's no attribute {} in HumanSeg.models".format(
+ if not hasattr(models, info['Model']):
+ raise Exception("There's no attribute {} in models".format(
info['Model']))
- model = getattr(HumanSeg.models, info['Model'])(**info['_init_params'])
+ model = getattr(models, info['Model'])(**info['_init_params'])
if status == "Normal":
startup_prog = fluid.Program()
model.test_prog = fluid.Program()
@@ -73,7 +73,7 @@ def load_model(model_dir):
def build_transforms(transforms_info):
- import HumanSeg.transforms as T
+ import transforms as T
transforms = list()
for op_info in transforms_info:
op_name = list(op_info.keys())[0]
diff --git a/contrib/HumanSeg/nets/backbone/xception.py b/contrib/HumanSeg/nets/backbone/xception.py
index b0ae9641..ad5c3821 100644
--- a/contrib/HumanSeg/nets/backbone/xception.py
+++ b/contrib/HumanSeg/nets/backbone/xception.py
@@ -18,10 +18,10 @@ from __future__ import division
from __future__ import print_function
import math
import paddle.fluid as fluid
-from HumanSeg.nets.libs import scope, name_scope
-from HumanSeg.nets.libs import bn, bn_relu, relu
-from HumanSeg.nets.libs import conv
-from HumanSeg.nets.libs import separate_conv
+from nets.libs import scope, name_scope
+from nets.libs import bn, bn_relu, relu
+from nets.libs import conv
+from nets.libs import separate_conv
__all__ = ['xception_65', 'xception_41', 'xception_71']
diff --git a/contrib/HumanSeg/pretrained_weights/download_pretrained_weights.py b/contrib/HumanSeg/pretrained_weights/download_pretrained_weights.py
new file mode 100644
index 00000000..7ac4000c
--- /dev/null
+++ b/contrib/HumanSeg/pretrained_weights/download_pretrained_weights.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import os
+
+LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
+TEST_PATH = os.path.join(LOCAL_PATH, "../../../", "test")
+sys.path.append(TEST_PATH)
+
+from test_utils import download_file_and_uncompress
+
+model_urls = {
+ "humanseg_server": "",
+ "humanseg_mobile": "",
+ "humanseg_lite": "",
+}
+
+if __name__ == "__main__":
+ for model_name, url in model_urls.items():
+ download_file_and_uncompress(
+ url=url,
+ savepath=LOCAL_PATH,
+ extrapath=LOCAL_PATH,
+ extraname=model_name)
+
+ print("Pretrained Model download success!")
diff --git a/contrib/HumanSeg/quant_offline.py b/contrib/HumanSeg/quant_offline.py
new file mode 100644
index 00000000..c2d51e0c
--- /dev/null
+++ b/contrib/HumanSeg/quant_offline.py
@@ -0,0 +1,73 @@
+import argparse
+from datasets.dataset import Dataset
+import transforms
+import models
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='HumanSeg training')
+ parser.add_argument(
+ '--model_dir',
+ dest='model_dir',
+ help='Model path for quant',
+ type=str,
+ default='output/best_model')
+ parser.add_argument(
+ '--batch_size',
+ dest='batch_size',
+ help='Mini batch size',
+ type=int,
+ default=1)
+ parser.add_argument(
+ '--batch_nums',
+ dest='batch_nums',
+ help='Batch number for quant',
+ type=int,
+ default=10)
+ parser.add_argument(
+ '--data_dir',
+ dest='data_dir',
+ help='the root directory of dataset',
+ type=str)
+ parser.add_argument(
+ '--quant_list',
+ dest='quant_list',
+ help=
+ 'Image file list for model quantization, it can be vat.txt or train.txt',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--save_dir',
+ dest='save_dir',
+ help='The directory for saving the quant model',
+ type=str,
+ default='./output/quant_offline')
+ return parser.parse_args()
+
+
+def evaluate(args):
+ eval_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+
+ eval_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.quant_list,
+ transforms=eval_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=False)
+
+ model = models.load_model(args.model_dir)
+ model.export_quant_model(
+ dataset=eval_dataset,
+ save_dir=args.save_dir,
+ batch_size=args.batch_size,
+ batch_nums=args.batch_nums)
+
+
+if __name__ == '__main__':
+ args = parse_args()
+
+ evaluate(args)
diff --git a/contrib/HumanSeg/quant_online.py b/contrib/HumanSeg/quant_online.py
new file mode 100644
index 00000000..fbc1d026
--- /dev/null
+++ b/contrib/HumanSeg/quant_online.py
@@ -0,0 +1,135 @@
+import argparse
+from datasets.dataset import Dataset
+from models import HumanSegMobile, HumanSegLite, HumanSegServer
+import transforms
+
+MODEL_TYPE = ['HumanSegMobile', 'HumanSegLite', 'HumanSegServer']
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='HumanSeg training')
+ parser.add_argument(
+ '--model_type',
+ dest='model_type',
+ help=
+ "Model type for traing, which is one of ('HumanSegMobile', 'HumanSegLite', 'HumanSegServer')",
+ type=str,
+ default='HumanSegMobile')
+ parser.add_argument(
+ '--data_dir',
+ dest='data_dir',
+ help='The root directory of dataset',
+ type=str)
+ parser.add_argument(
+ '--train_list',
+ dest='train_list',
+ help='Train list file of dataset',
+ type=str)
+ parser.add_argument(
+ '--val_list',
+ dest='val_list',
+ help='Val list file of dataset',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--save_dir',
+ dest='save_dir',
+ help='The directory for saving the model snapshot',
+ type=str,
+ default='./output/quant_train')
+ parser.add_argument(
+ '--num_classes',
+ dest='num_classes',
+ help='Number of classes',
+ type=int,
+ default=2)
+ parser.add_argument(
+ '--num_epochs',
+ dest='num_epochs',
+ help='Number epochs for training',
+ type=int,
+ default=2)
+ parser.add_argument(
+ '--batch_size',
+ dest='batch_size',
+ help='Mini batch size',
+ type=int,
+ default=128)
+ parser.add_argument(
+ '--learning_rate',
+ dest='learning_rate',
+ help='Learning rate',
+ type=float,
+ default=0.001)
+ parser.add_argument(
+ '--pretrained_weights',
+ dest='pretrained_weights',
+ help='The model path for quant',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--save_interval_epochs',
+ dest='save_interval_epochs',
+ help='The interval epochs for save a model snapshot',
+ type=int,
+ default=1)
+
+ return parser.parse_args()
+
+
+def train(args):
+ train_transforms = transforms.Compose([
+ transforms.RandomHorizontalFlip(),
+ transforms.Resize((192, 192)),
+ transforms.Normalize()
+ ])
+
+ eval_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+
+ train_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.train_list,
+ transforms=train_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=True)
+
+ eval_dataset = None
+ if args.val_list is not None:
+ eval_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.val_list,
+ transforms=eval_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=False)
+
+ if args.model_type == 'HumanSegMobile':
+ model = HumanSegMobile(num_classes=2)
+ elif args.model_type == 'HumanSegLite':
+ model = HumanSegLite(num_classes=2)
+ elif args.model_type == 'HumanSegServer':
+ model = HumanSegServer(num_classes=2)
+ else:
+ raise ValueError(
+ "--model_type: {} is set wrong, it shold be one of ('HumanSegMobile', "
+ "'HumanSegLite', 'HumanSegServer')".format(args.model_type))
+ model.train(
+ num_epochs=args.num_epochs,
+ train_dataset=train_dataset,
+ train_batch_size=args.batch_size,
+ eval_dataset=eval_dataset,
+ save_interval_epochs=args.save_interval_epochs,
+ save_dir=args.save_dir,
+ pretrained_weights=args.pretrained_weights,
+ learning_rate=args.learning_rate,
+ quant=True)
+
+
+if __name__ == '__main__':
+ args = parse_args()
+ train(args)
diff --git a/contrib/HumanSeg/requirements.txt b/contrib/HumanSeg/requirements.txt
new file mode 100644
index 00000000..2f4dd30f
--- /dev/null
+++ b/contrib/HumanSeg/requirements.txt
@@ -0,0 +1,10 @@
+pre-commit
+yapf == 0.26.0
+flake8
+pyyaml >= 5.1
+visual >= 1.3.0
+Pillow
+numpy
+six
+opencv-python
+tqdm
diff --git a/contrib/HumanSeg/setup.py b/contrib/HumanSeg/setup.py
deleted file mode 100644
index e87e1ecd..00000000
--- a/contrib/HumanSeg/setup.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import setuptools
-
-long_descrition = 'HumanSeg'
-
-setuptools.setup(
- name='HumanSeg',
- version='1.0.0',
- author='paddleseg',
- description=long_descrition,
- long_descrition=long_descrition,
- packages='./',
- setup_requires=['cython', 'numpy'],
- install_requires=['pyyaml', 'tqdm', 'visualdl==1.3.0', 'paddleslim==1.0.1'],
- license='Apache 2.0')
diff --git a/contrib/HumanSeg/train.py b/contrib/HumanSeg/train.py
new file mode 100644
index 00000000..c7463962
--- /dev/null
+++ b/contrib/HumanSeg/train.py
@@ -0,0 +1,148 @@
+import argparse
+from datasets.dataset import Dataset
+from models import HumanSegMobile, HumanSegLite, HumanSegServer
+import transforms
+
+MODEL_TYPE = ['HumanSegMobile', 'HumanSegLite', 'HumanSegServer']
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='HumanSeg training')
+ parser.add_argument(
+ '--model_type',
+ dest='model_type',
+ help=
+ "Model type for traing, which is one of ('HumanSegMobile', 'HumanSegLite', 'HumanSegServer')",
+ type=str,
+ default='HumanSegMobile')
+ parser.add_argument(
+ '--data_dir',
+ dest='data_dir',
+ help='The root directory of dataset',
+ type=str)
+ parser.add_argument(
+ '--train_list',
+ dest='train_list',
+ help='Train list file of dataset',
+ type=str)
+ parser.add_argument(
+ '--val_list',
+ dest='val_list',
+ help='Val list file of dataset',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--save_dir',
+ dest='save_dir',
+ help='The directory for saving the model snapshot',
+ type=str,
+ default='./output')
+ parser.add_argument(
+ '--num_classes',
+ dest='num_classes',
+ help='Number of classes',
+ type=int,
+ default=2)
+ parser.add_argument(
+ '--num_epochs',
+ dest='num_epochs',
+ help='Number epochs for training',
+ type=int,
+ default=100)
+ parser.add_argument(
+ '--batch_size',
+ dest='batch_size',
+ help='Mini batch size',
+ type=int,
+ default=128)
+ parser.add_argument(
+ '--learning_rate',
+ dest='learning_rate',
+ help='Learning rate',
+ type=float,
+ default=0.01)
+ parser.add_argument(
+ '--pretrained_weights',
+ dest='pretrained_weights',
+ help='The path of pretrianed weight',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--resume_weights',
+ dest='resume_weights',
+ help='The path of resume weight',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--use_vdl',
+ dest='use_vdl',
+ help='Whether to use visualdl',
+ type=bool,
+ default=True)
+ parser.add_argument(
+ '--save_interval_epochs',
+ dest='save_interval_epochs',
+ help='The interval epochs for save a model snapshot',
+ type=int,
+ default=5)
+
+ return parser.parse_args()
+
+
+def train(args):
+ train_transforms = transforms.Compose([
+ transforms.RandomHorizontalFlip(),
+ transforms.Resize((192, 192)),
+ transforms.Normalize()
+ ])
+
+ eval_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+
+ train_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.train_list,
+ transforms=train_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=True)
+
+ eval_dataset = None
+ if args.val_list is not None:
+ eval_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.val_list,
+ transforms=eval_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=False)
+
+ if args.model_type == 'HumanSegMobile':
+ model = HumanSegMobile(num_classes=2)
+ elif args.model_type == 'HumanSegLite':
+ model = HumanSegLite(num_classes=2)
+ elif args.model_type == 'HumanSegServer':
+ model = HumanSegServer(num_classes=2)
+ else:
+ raise ValueError(
+ "--model_type: {} is set wrong, it shold be one of ('HumanSegMobile', "
+ "'HumanSegLite', 'HumanSegServer')".format(args.model_type))
+ model.train(
+ num_epochs=args.num_epochs,
+ train_dataset=train_dataset,
+ train_batch_size=args.batch_size,
+ eval_dataset=eval_dataset,
+ save_interval_epochs=args.save_interval_epochs,
+ save_dir=args.save_dir,
+ pretrained_weights=args.pretrained_weights,
+ resume_weights=args.resume_weights,
+ learning_rate=args.learning_rate,
+ use_vdl=args.use_vdl)
+
+
+if __name__ == '__main__':
+ args = parse_args()
+ train(args)
diff --git a/contrib/HumanSeg/tutorial/export_demo.py b/contrib/HumanSeg/tutorial/export_demo.py
deleted file mode 100644
index 449cf89b..00000000
--- a/contrib/HumanSeg/tutorial/export_demo.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import HumanSeg
-model = HumanSeg.models.load_model('output/best_model')
-model.export_inference_model('output/export')
diff --git a/contrib/HumanSeg/tutorial/infer_demo.py b/contrib/HumanSeg/tutorial/infer_demo.py
deleted file mode 100644
index 89957e71..00000000
--- a/contrib/HumanSeg/tutorial/infer_demo.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import HumanSeg
-from HumanSeg.utils import visualize
-
-im_file = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/pexel/img/person_detection__ds6/img/pexels-photo-704264.jpg'
-model = HumanSeg.models.load_model('output/best_model')
-result = model.predict(im_file)
-visualize(im_file, result, save_dir='output/')
diff --git a/contrib/HumanSeg/tutorial/train_demo.py b/contrib/HumanSeg/tutorial/train_demo.py
deleted file mode 100644
index 3ebccbbb..00000000
--- a/contrib/HumanSeg/tutorial/train_demo.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import os
-import numpy as np
-from HumanSeg.datasets.dataset import Dataset
-from HumanSeg.models import HumanSegMobile
-from HumanSeg.transforms import transforms
-
-train_transforms = transforms.Compose([
- transforms.RandomHorizontalFlip(),
- transforms.Resize((192, 192)),
- transforms.Normalize()
-])
-
-eval_transforms = transforms.Compose(
- [transforms.Resize((192, 192)),
- transforms.Normalize()])
-
-data_dir = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly'
-train_list = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/train.txt'
-val_list = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/val.txt'
-
-train_dataset = Dataset(
- data_dir=data_dir,
- file_list=train_list,
- transforms=train_transforms,
- num_workers='auto',
- buffer_size=100,
- parallel_method='thread',
- shuffle=True)
-
-eval_dataset = Dataset(
- data_dir=data_dir,
- file_list=val_list,
- transforms=eval_transforms,
- num_workers='auto',
- buffer_size=100,
- parallel_method='thread',
- shuffle=False)
-
-model = HumanSegMobile(num_classes=2)
-
-model.train(
- num_epochs=100,
- train_dataset=train_dataset,
- eval_dataset=eval_dataset,
- save_interval_epochs=5,
- train_batch_size=256,
- # resume_weights='/Users/chenguowei01/PycharmProjects/github/PaddleSeg/contrib/HumanSeg/output/epoch_20',
- log_interval_steps=2,
- save_dir='output',
- use_vdl=True,
-)
diff --git a/contrib/HumanSeg/tutorial/val_demo.py b/contrib/HumanSeg/tutorial/val_demo.py
deleted file mode 100644
index f75453dc..00000000
--- a/contrib/HumanSeg/tutorial/val_demo.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import HumanSeg
-from HumanSeg.datasets.dataset import Dataset
-from HumanSeg.transforms import transforms
-
-eval_transforms = transforms.Compose(
- [transforms.Resize((192, 192)),
- transforms.Normalize()])
-
-data_dir = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly'
-val_list = '/ssd1/chenguowei01/dataset/humanseg/supervise.ly/val.txt'
-
-eval_dataset = Dataset(
- data_dir=data_dir,
- file_list=val_list,
- transforms=eval_transforms,
- num_workers='auto',
- buffer_size=100,
- parallel_method='thread',
- shuffle=False)
-
-model = HumanSeg.models.load_model('output/best_model')
-model.evaluate(eval_dataset, 2)
diff --git a/contrib/HumanSeg/utils/__init__.py b/contrib/HumanSeg/utils/__init__.py
index a26f4459..a7760ee4 100644
--- a/contrib/HumanSeg/utils/__init__.py
+++ b/contrib/HumanSeg/utils/__init__.py
@@ -13,7 +13,7 @@
# limitations under the License.
from . import logging
-from . import utils
+from . import humanseg_postprocess
from .metrics import ConfusionMatrix
from .utils import *
from .post_quantization import HumanSegPostTrainingQuantization
diff --git a/contrib/HumanSeg/utils/humanseg_postprocess.py b/contrib/HumanSeg/utils/humanseg_postprocess.py
new file mode 100644
index 00000000..1e5466f6
--- /dev/null
+++ b/contrib/HumanSeg/utils/humanseg_postprocess.py
@@ -0,0 +1,163 @@
+# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ==============================================================================
+
+import os
+import numpy as np
+import cv2
+
+
+def humanseg_tracking(pre_gray, cur_gray, prev_cfd, dl_weights, disflow):
+ """计算光流跟踪匹配点和光流图
+ 输入参数:
+ pre_gray: 上一帧灰度图
+ cur_gray: 当前帧灰度图
+ prev_cfd: 上一帧光流图
+ dl_weights: 融合权重图
+ disflow: 光流数据结构
+ 返回值:
+ is_track: 光流点跟踪二值图,即是否具有光流点匹配
+ track_cfd: 光流跟踪图
+ """
+ check_thres = 8
+ hgt, wdh = pre_gray.shape[:2]
+ track_cfd = np.zeros_like(prev_cfd)
+ is_track = np.zeros_like(pre_gray)
+ # 计算前向光流
+ flow_fw = disflow.calc(pre_gray, cur_gray, None)
+ # 计算后向光流
+ flow_bw = disflow.calc(cur_gray, pre_gray, None)
+ get_round = lambda data: (int)(data + 0.5) if data >= 0 else (int)(data -
+ 0.5)
+ for row in range(hgt):
+ for col in range(wdh):
+ # 计算光流处理后对应点坐标
+ # (row, col) -> (cur_x, cur_y)
+ fxy_fw = flow_fw[row, col]
+ dx_fw = get_round(fxy_fw[0])
+ cur_x = dx_fw + col
+ dy_fw = get_round(fxy_fw[1])
+ cur_y = dy_fw + row
+ if cur_x < 0 or cur_x >= wdh or cur_y < 0 or cur_y >= hgt:
+ continue
+ fxy_bw = flow_bw[cur_y, cur_x]
+ dx_bw = get_round(fxy_bw[0])
+ dy_bw = get_round(fxy_bw[1])
+ # 光流移动小于阈值
+ lmt = ((dy_fw + dy_bw) * (dy_fw + dy_bw) +
+ (dx_fw + dx_bw) * (dx_fw + dx_bw))
+ if lmt >= check_thres:
+ continue
+ # 静止点降权
+ if abs(dy_fw) <= 0 and abs(dx_fw) <= 0 and abs(dy_bw) <= 0 and abs(
+ dx_bw) <= 0:
+ dl_weights[cur_y, cur_x] = 0.05
+ is_track[cur_y, cur_x] = 1
+ track_cfd[cur_y, cur_x] = prev_cfd[row, col]
+ return track_cfd, is_track, dl_weights
+
+
+def humanseg_track_fuse(track_cfd, dl_cfd, dl_weights, is_track):
+ """光流追踪图和人像分割结构融合
+ 输入参数:
+ track_cfd: 光流追踪图
+ dl_cfd: 当前帧分割结果
+ dl_weights: 融合权重图
+ is_track: 光流点匹配二值图
+ 返回值:
+ cur_cfd: 光流跟踪图和人像分割结果融合图
+ """
+ cur_cfd = dl_cfd.copy()
+ idxs = np.where(is_track > 0)
+ for i in range(len(idxs)):
+ x, y = idxs[0][i], idxs[1][i]
+ dl_score = dl_cfd[x, y]
+ track_score = track_cfd[x, y]
+ if dl_score > 0.9 or dl_score < 0.1:
+ if dl_weights[x, y] < 0.1:
+ cur_cfd[x, y] = 0.3 * dl_score + 0.7 * track_score
+ else:
+ cur_cfd[x, y] = 0.4 * dl_score + 0.6 * track_score
+ else:
+ cur_cfd[x, y] = dl_weights[x, y] * dl_score + (
+ 1 - dl_weights[x, y]) * track_score
+ return cur_cfd
+
+
+def threshold_mask(img, thresh_bg, thresh_fg):
+ """设置背景和前景阈值mask
+ 输入参数:
+ img : 原始图像, np.uint8 类型.
+ thresh_bg : 背景阈值百分比,低于该值置为0.
+ thresh_fg : 前景阈值百分比,超过该值置为1.
+ 返回值:
+ dst : 原始图像设置完前景背景阈值mask结果, np.float32 类型.
+ """
+ dst = (img / 255.0 - thresh_bg) / (thresh_fg - thresh_bg)
+ dst[np.where(dst > 1)] = 1
+ dst[np.where(dst < 0)] = 0
+ return dst.astype(np.float32)
+
+
+def optflow_handle(cur_gray, scoremap, is_init):
+ """光流优化
+ Args:
+ cur_gray : 当前帧灰度图
+ scoremap : 当前帧分割结果
+ is_init : 是否第一帧
+ Returns:
+ dst : 光流追踪图和预测结果融合图, 类型为 np.float32
+ """
+ height, width = scoremap.shape[0], scoremap.shape[1]
+ disflow = cv2.DISOpticalFlow_create(cv2.DISOPTICAL_FLOW_PRESET_ULTRAFAST)
+ prev_gray = np.zeros((height, width), np.uint8)
+ prev_cfd = np.zeros((height, width), np.float32)
+ cur_cfd = scoremap.copy()
+ if is_init:
+ is_init = False
+ if height <= 64 or width <= 64:
+ disflow.setFinestScale(1)
+ elif height <= 160 or width <= 160:
+ disflow.setFinestScale(2)
+ else:
+ disflow.setFinestScale(3)
+ fusion_cfd = cur_cfd
+ else:
+ weights = np.ones((height, width), np.float32) * 0.3
+ track_cfd, is_track, weights = humanseg_tracking(
+ prev_gray, cur_gray, prev_cfd, weights, disflow)
+ fusion_cfd = humanseg_track_fuse(track_cfd, cur_cfd, weights, is_track)
+ fusion_cfd = cv2.GaussianBlur(fusion_cfd, (3, 3), 0)
+ return fusion_cfd
+
+
+def postprocess(image, output_data):
+ """对预测结果进行后处理
+ Args:
+ image: 原始图,opencv 图片对象
+ output_data: Paddle预测结果原始数据
+ Returns:
+ 原图和预测结果融合并做了光流优化的结果图
+ """
+ scoremap = output_data[:, :, 1]
+ scoremap = (scoremap * 255).astype(np.uint8)
+ # 光流处理
+ cur_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
+ optflow_map = optflow_handle(cur_gray, scoremap, False)
+ optflow_map = cv2.GaussianBlur(optflow_map, (3, 3), 0)
+ optflow_map = threshold_mask(optflow_map, thresh_bg=0.2, thresh_fg=0.8)
+ optflow_map = np.repeat(optflow_map[:, :, np.newaxis], 3, axis=2)
+ bg_im = np.ones_like(optflow_map) * 255
+ comb = (optflow_map * image + (1 - optflow_map) * bg_im).astype(np.uint8)
+ return comb
diff --git a/contrib/HumanSeg/utils/logging.py b/contrib/HumanSeg/utils/logging.py
index d0a97deb..1669466f 100644
--- a/contrib/HumanSeg/utils/logging.py
+++ b/contrib/HumanSeg/utils/logging.py
@@ -15,16 +15,16 @@
import time
import os
import sys
-import HumanSeg
levels = {0: 'ERROR', 1: 'WARNING', 2: 'INFO', 3: 'DEBUG'}
+log_level = 2
def log(level=2, message=""):
current_time = time.time()
time_array = time.localtime(current_time)
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time_array)
- if HumanSeg.log_level >= level:
+ if log_level >= level:
print("{} [{}]\t{}".format(current_time, levels[level],
message).encode("utf-8").decode("latin1"))
sys.stdout.flush()
diff --git a/contrib/HumanSeg/utils/post_quantization.py b/contrib/HumanSeg/utils/post_quantization.py
index 84153c52..00d61c80 100644
--- a/contrib/HumanSeg/utils/post_quantization.py
+++ b/contrib/HumanSeg/utils/post_quantization.py
@@ -19,7 +19,7 @@ from paddle.fluid.contrib.slim.quantization import PostTrainingQuantization
import paddle.fluid as fluid
import os
-import HumanSeg.utils.logging as logging
+import utils.logging as logging
class HumanSegPostTrainingQuantization(PostTrainingQuantization):
diff --git a/contrib/HumanSeg/utils/utils.py b/contrib/HumanSeg/utils/utils.py
index 87382542..0e09e8b2 100644
--- a/contrib/HumanSeg/utils/utils.py
+++ b/contrib/HumanSeg/utils/utils.py
@@ -159,7 +159,7 @@ def load_pdparams(exe, main_prog, model_dir):
if not isinstance(var, fluid.framework.Parameter):
continue
if var.name not in params_dict:
- raise Exception("{} is not in saved paddlex model".format(var.name))
+ raise Exception("{} is not in saved model".format(var.name))
if var.shape != params_dict[var.name].shape:
unused_vars.append(var.name)
logging.warning(
@@ -181,7 +181,7 @@ def load_pdparams(exe, main_prog, model_dir):
len(vars_to_load), model_dir))
-def load_pretrain_weights(exe, main_prog, weights_dir, fuse_bn=False):
+def load_pretrained_weights(exe, main_prog, weights_dir, fuse_bn=False):
if not osp.exists(weights_dir):
raise Exception("Path {} not exists.".format(weights_dir))
if osp.exists(osp.join(weights_dir, "model.pdparams")):
diff --git a/contrib/HumanSeg/val.py b/contrib/HumanSeg/val.py
new file mode 100644
index 00000000..ffceecdc
--- /dev/null
+++ b/contrib/HumanSeg/val.py
@@ -0,0 +1,56 @@
+import argparse
+from datasets.dataset import Dataset
+import transforms
+import models
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='HumanSeg training')
+ parser.add_argument(
+ '--model_dir',
+ dest='model_dir',
+ help='Model path for evaluating',
+ type=str,
+ default='output/best_model')
+ parser.add_argument(
+ '--data_dir',
+ dest='data_dir',
+ help='The root directory of dataset',
+ type=str)
+ parser.add_argument(
+ '--val_list',
+ dest='val_list',
+ help='Val list file of dataset',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--batch_size',
+ dest='batch_size',
+ help='Mini batch size',
+ type=int,
+ default=128)
+ return parser.parse_args()
+
+
+def evaluate(args):
+ eval_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+
+ eval_dataset = Dataset(
+ data_dir=args.data_dir,
+ file_list=args.val_list,
+ transforms=eval_transforms,
+ num_workers='auto',
+ buffer_size=100,
+ parallel_method='thread',
+ shuffle=False)
+
+ model = models.load_model(args.model_dir)
+ model.evaluate(eval_dataset, args.batch_size)
+
+
+if __name__ == '__main__':
+ args = parse_args()
+
+ evaluate(args)
diff --git a/contrib/HumanSeg/video_infer.py b/contrib/HumanSeg/video_infer.py
new file mode 100644
index 00000000..b4fa79ad
--- /dev/null
+++ b/contrib/HumanSeg/video_infer.py
@@ -0,0 +1,87 @@
+import argparse
+import os
+import os.path as osp
+import cv2
+import numpy as np
+
+from utils.humanseg_postprocess import postprocess
+import models
+import transforms
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='HumanSeg inference for video')
+ parser.add_argument(
+ '--model_dir',
+ dest='model_dir',
+ help='Model path for inference',
+ type=str)
+ parser.add_argument(
+ '--video_path',
+ dest='video_path',
+ help=
+ 'Video path for inference, camera will be used if the path not existing',
+ type=str,
+ default=None)
+ parser.add_argument(
+ '--save_dir',
+ dest='save_dir',
+ help='The directory for saving the inference results',
+ type=str,
+ default='./output')
+
+ return parser.parse_args()
+
+
+def video_infer(args):
+ test_transforms = transforms.Compose(
+ [transforms.Resize((192, 192)),
+ transforms.Normalize()])
+ model = models.load_model(args.model_dir)
+ if not args.video_path:
+ cap = cv2.VideoCapture(0)
+ else:
+ cap = cv2.VideoCapture(args.video_path)
+ if not cap.isOpened():
+ raise IOError("Error opening video stream or file, "
+ "--video_path whether existing: {}"
+ " or camera whether working".format(args.video_path))
+ return
+ if args.video_path:
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+ fps = cap.get(cv2.CAP_PROP_FPS)
+ # 用于保存预测结果视频
+ out = cv2.VideoWriter(
+ osp.join(args.save_dir, 'result.avi'),
+ cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps, (width, height))
+ # 开始获取视频帧
+ while cap.isOpened():
+ ret, frame = cap.read()
+ if ret:
+ results = model.predict(frame, test_transforms)
+ img_mat = postprocess(frame, results['score_map'])
+ out.write(img_mat)
+ else:
+ break
+ cap.release()
+ out.release()
+
+ else:
+ while cap.isOpened():
+ ret, frame = cap.read()
+ if ret:
+ results = model.predict(frame, test_transforms)
+ print(frame.shape, results['score_map'].shape)
+ img_mat = postprocess(frame, results['score_map'])
+ cv2.imshow('HumanSegmentation', img_mat)
+ if cv2.waitKey(1) & 0xFF == ord('q'):
+ break
+ else:
+ break
+ cap.release()
+
+
+if __name__ == "__main__":
+ args = parse_args()
+ video_infer(args)
diff --git a/contrib/RealTimeHumanSeg/README.md b/contrib/RealTimeHumanSeg/README.md
deleted file mode 100644
index e8693e11..00000000
--- a/contrib/RealTimeHumanSeg/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# 实时人像分割预测部署
-
-本模型基于飞浆开源的人像分割模型,并做了大量的针对视频的光流追踪优化,提供了完整的支持视频流的实时人像分割解决方案,并提供了高性能的`Python`和`C++`集成部署方案,以满足不同场景的需求。
-
-
-## 模型下载
-
-支持的模型文件如下,请根据应用场景选择合适的模型:
-|模型文件 | 说明 |
-|---|---|
-|[shv75_deeplab_0303_quant](https://paddleseg.bj.bcebos.com/deploy/models/shv75_0303_quant.zip) | 小模型, 适合轻量级计算环境 |
-|[shv75_deeplab_0303](https://paddleseg.bj.bcebos.com/deploy/models/shv75_deeplab_0303.zip)| 小模型,适合轻量级计算环境 |
-|[deeplabv3_xception_humanseg](https://paddleseg.bj.bcebos.com/deploy/models/deeplabv3_xception_humanseg.zip) | 服务端GPU环境 |
-
-**注意:下载后解压到合适的路径,后续该路径将做为预测参数用于加载模型。**
-
-
-## 预测部署
-- [Python预测部署](./python)
-- [C++预测部署](./cpp)
-
-## 效果预览
-
-
-
diff --git a/contrib/RealTimeHumanSeg/cpp/CMakeLists.txt b/contrib/RealTimeHumanSeg/cpp/CMakeLists.txt
deleted file mode 100644
index 5a7b89ac..00000000
--- a/contrib/RealTimeHumanSeg/cpp/CMakeLists.txt
+++ /dev/null
@@ -1,221 +0,0 @@
-cmake_minimum_required(VERSION 3.0)
-project(PaddleMaskDetector CXX C)
-
-option(WITH_MKL "Compile demo with MKL/OpenBlas support,defaultuseMKL." ON)
-option(WITH_GPU "Compile demo with GPU/CPU, default use CPU." ON)
-option(WITH_STATIC_LIB "Compile demo with static/shared library, default use static." ON)
-option(USE_TENSORRT "Compile demo with TensorRT." OFF)
-
-SET(PADDLE_DIR "" CACHE PATH "Location of libraries")
-SET(OPENCV_DIR "" CACHE PATH "Location of libraries")
-SET(CUDA_LIB "" CACHE PATH "Location of libraries")
-
-macro(safe_set_static_flag)
- foreach(flag_var
- CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
- if(${flag_var} MATCHES "/MD")
- string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
- endif(${flag_var} MATCHES "/MD")
- endforeach(flag_var)
-endmacro()
-
-if (WITH_MKL)
- ADD_DEFINITIONS(-DUSE_MKL)
-endif()
-
-if (NOT DEFINED PADDLE_DIR OR ${PADDLE_DIR} STREQUAL "")
- message(FATAL_ERROR "please set PADDLE_DIR with -DPADDLE_DIR=/path/paddle_influence_dir")
-endif()
-
-if (NOT DEFINED OPENCV_DIR OR ${OPENCV_DIR} STREQUAL "")
- message(FATAL_ERROR "please set OPENCV_DIR with -DOPENCV_DIR=/path/opencv")
-endif()
-
-include_directories("${CMAKE_SOURCE_DIR}/")
-include_directories("${PADDLE_DIR}/")
-include_directories("${PADDLE_DIR}/third_party/install/protobuf/include")
-include_directories("${PADDLE_DIR}/third_party/install/glog/include")
-include_directories("${PADDLE_DIR}/third_party/install/gflags/include")
-include_directories("${PADDLE_DIR}/third_party/install/xxhash/include")
-if (EXISTS "${PADDLE_DIR}/third_party/install/snappy/include")
- include_directories("${PADDLE_DIR}/third_party/install/snappy/include")
-endif()
-if(EXISTS "${PADDLE_DIR}/third_party/install/snappystream/include")
- include_directories("${PADDLE_DIR}/third_party/install/snappystream/include")
-endif()
-include_directories("${PADDLE_DIR}/third_party/install/zlib/include")
-include_directories("${PADDLE_DIR}/third_party/boost")
-include_directories("${PADDLE_DIR}/third_party/eigen3")
-
-if (EXISTS "${PADDLE_DIR}/third_party/install/snappy/lib")
- link_directories("${PADDLE_DIR}/third_party/install/snappy/lib")
-endif()
-if(EXISTS "${PADDLE_DIR}/third_party/install/snappystream/lib")
- link_directories("${PADDLE_DIR}/third_party/install/snappystream/lib")
-endif()
-
-link_directories("${PADDLE_DIR}/third_party/install/zlib/lib")
-link_directories("${PADDLE_DIR}/third_party/install/protobuf/lib")
-link_directories("${PADDLE_DIR}/third_party/install/glog/lib")
-link_directories("${PADDLE_DIR}/third_party/install/gflags/lib")
-link_directories("${PADDLE_DIR}/third_party/install/xxhash/lib")
-link_directories("${PADDLE_DIR}/paddle/lib/")
-link_directories("${CMAKE_CURRENT_BINARY_DIR}")
-if (WIN32)
- include_directories("${PADDLE_DIR}/paddle/fluid/inference")
- include_directories("${PADDLE_DIR}/paddle/include")
- link_directories("${PADDLE_DIR}/paddle/fluid/inference")
- include_directories("${OPENCV_DIR}/build/include")
- include_directories("${OPENCV_DIR}/opencv/build/include")
- link_directories("${OPENCV_DIR}/build/x64/vc14/lib")
-else ()
- find_package(OpenCV REQUIRED PATHS ${OPENCV_DIR}/share/OpenCV NO_DEFAULT_PATH)
- include_directories("${PADDLE_DIR}/paddle/include")
- link_directories("${PADDLE_DIR}/paddle/lib")
- include_directories(${OpenCV_INCLUDE_DIRS})
-endif ()
-
-if (WIN32)
- add_definitions("/DGOOGLE_GLOG_DLL_DECL=")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /bigobj /MTd")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /bigobj /MT")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj /MTd")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /bigobj /MT")
- if (WITH_STATIC_LIB)
- safe_set_static_flag()
- add_definitions(-DSTATIC_LIB)
- endif()
-else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -o2 -fopenmp -std=c++11")
- set(CMAKE_STATIC_LIBRARY_PREFIX "")
-endif()
-
-# TODO let users define cuda lib path
-if (WITH_GPU)
- if (NOT DEFINED CUDA_LIB OR ${CUDA_LIB} STREQUAL "")
- message(FATAL_ERROR "please set CUDA_LIB with -DCUDA_LIB=/path/cuda-8.0/lib64")
- endif()
- if (NOT WIN32)
- if (NOT DEFINED CUDNN_LIB)
- message(FATAL_ERROR "please set CUDNN_LIB with -DCUDNN_LIB=/path/cudnn_v7.4/cuda/lib64")
- endif()
- endif(NOT WIN32)
-endif()
-
-
-if (NOT WIN32)
- if (USE_TENSORRT AND WITH_GPU)
- include_directories("${PADDLE_DIR}/third_party/install/tensorrt/include")
- link_directories("${PADDLE_DIR}/third_party/install/tensorrt/lib")
- endif()
-endif(NOT WIN32)
-
-if (NOT WIN32)
- set(NGRAPH_PATH "${PADDLE_DIR}/third_party/install/ngraph")
- if(EXISTS ${NGRAPH_PATH})
- include(GNUInstallDirs)
- include_directories("${NGRAPH_PATH}/include")
- link_directories("${NGRAPH_PATH}/${CMAKE_INSTALL_LIBDIR}")
- set(NGRAPH_LIB ${NGRAPH_PATH}/${CMAKE_INSTALL_LIBDIR}/libngraph${CMAKE_SHARED_LIBRARY_SUFFIX})
- endif()
-endif()
-
-if(WITH_MKL)
- include_directories("${PADDLE_DIR}/third_party/install/mklml/include")
- if (WIN32)
- set(MATH_LIB ${PADDLE_DIR}/third_party/install/mklml/lib/mklml.lib
- ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5md.lib)
- else ()
- set(MATH_LIB ${PADDLE_DIR}/third_party/install/mklml/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX}
- ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5${CMAKE_SHARED_LIBRARY_SUFFIX})
- execute_process(COMMAND cp -r ${PADDLE_DIR}/third_party/install/mklml/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX} /usr/lib)
- endif ()
- set(MKLDNN_PATH "${PADDLE_DIR}/third_party/install/mkldnn")
- if(EXISTS ${MKLDNN_PATH})
- include_directories("${MKLDNN_PATH}/include")
- if (WIN32)
- set(MKLDNN_LIB ${MKLDNN_PATH}/lib/mkldnn.lib)
- else ()
- set(MKLDNN_LIB ${MKLDNN_PATH}/lib/libmkldnn.so.0)
- endif ()
- endif()
-else()
- set(MATH_LIB ${PADDLE_DIR}/third_party/install/openblas/lib/libopenblas${CMAKE_STATIC_LIBRARY_SUFFIX})
-endif()
-
-if (WIN32)
- if(EXISTS "${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX}")
- set(DEPS
- ${PADDLE_DIR}/paddle/fluid/inference/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
- else()
- set(DEPS
- ${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
- endif()
-endif()
-
-if(WITH_STATIC_LIB)
- set(DEPS
- ${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_STATIC_LIBRARY_SUFFIX})
-else()
- set(DEPS
- ${PADDLE_DIR}/paddle/lib/libpaddle_fluid${CMAKE_SHARED_LIBRARY_SUFFIX})
-endif()
-
-if (NOT WIN32)
- set(DEPS ${DEPS}
- ${MATH_LIB} ${MKLDNN_LIB}
- glog gflags protobuf z xxhash
- )
- if(EXISTS "${PADDLE_DIR}/third_party/install/snappystream/lib")
- set(DEPS ${DEPS} snappystream)
- endif()
- if (EXISTS "${PADDLE_DIR}/third_party/install/snappy/lib")
- set(DEPS ${DEPS} snappy)
- endif()
-else()
- set(DEPS ${DEPS}
- ${MATH_LIB} ${MKLDNN_LIB}
- opencv_world346 glog gflags_static libprotobuf zlibstatic xxhash)
- set(DEPS ${DEPS} libcmt shlwapi)
- if (EXISTS "${PADDLE_DIR}/third_party/install/snappy/lib")
- set(DEPS ${DEPS} snappy)
- endif()
- if(EXISTS "${PADDLE_DIR}/third_party/install/snappystream/lib")
- set(DEPS ${DEPS} snappystream)
- endif()
-endif(NOT WIN32)
-
-if(WITH_GPU)
- if(NOT WIN32)
- if (USE_TENSORRT)
- set(DEPS ${DEPS} ${PADDLE_DIR}/third_party/install/tensorrt/lib/libnvinfer${CMAKE_STATIC_LIBRARY_SUFFIX})
- set(DEPS ${DEPS} ${PADDLE_DIR}/third_party/install/tensorrt/lib/libnvinfer_plugin${CMAKE_STATIC_LIBRARY_SUFFIX})
- endif()
- set(DEPS ${DEPS} ${CUDA_LIB}/libcudart${CMAKE_SHARED_LIBRARY_SUFFIX})
- set(DEPS ${DEPS} ${CUDNN_LIB}/libcudnn${CMAKE_SHARED_LIBRARY_SUFFIX})
- else()
- set(DEPS ${DEPS} ${CUDA_LIB}/cudart${CMAKE_STATIC_LIBRARY_SUFFIX} )
- set(DEPS ${DEPS} ${CUDA_LIB}/cublas${CMAKE_STATIC_LIBRARY_SUFFIX} )
- set(DEPS ${DEPS} ${CUDA_LIB}/cudnn${CMAKE_STATIC_LIBRARY_SUFFIX})
- endif()
-endif()
-
-if (NOT WIN32)
- set(EXTERNAL_LIB "-ldl -lrt -lgomp -lz -lm -lpthread")
- set(DEPS ${DEPS} ${EXTERNAL_LIB} ${OpenCV_LIBS})
-endif()
-
-add_executable(main main.cc humanseg.cc humanseg_postprocess.cc)
-target_link_libraries(main ${DEPS})
-
-if (WIN32)
- add_custom_command(TARGET main POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/mklml.dll ./mklml.dll
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5md.dll ./libiomp5md.dll
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./mkldnn.dll
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/mklml.dll ./release/mklml.dll
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mklml/lib/libiomp5md.dll ./release/libiomp5md.dll
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PADDLE_DIR}/third_party/install/mkldnn/lib/mkldnn.dll ./release/mkldnn.dll
- )
-endif()
diff --git a/contrib/RealTimeHumanSeg/cpp/CMakeSettings.json b/contrib/RealTimeHumanSeg/cpp/CMakeSettings.json
deleted file mode 100644
index 87cbe721..00000000
--- a/contrib/RealTimeHumanSeg/cpp/CMakeSettings.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "configurations": [
- {
- "name": "x64-Release",
- "generator": "Ninja",
- "configurationType": "RelWithDebInfo",
- "inheritEnvironments": [ "msvc_x64_x64" ],
- "buildRoot": "${projectDir}\\out\\build\\${name}",
- "installRoot": "${projectDir}\\out\\install\\${name}",
- "cmakeCommandArgs": "",
- "buildCommandArgs": "-v",
- "ctestCommandArgs": "",
- "variables": [
- {
- "name": "CUDA_LIB",
- "value": "D:/projects/packages/cuda10_0/lib64",
- "type": "PATH"
- },
- {
- "name": "CUDNN_LIB",
- "value": "D:/projects/packages/cuda10_0/lib64",
- "type": "PATH"
- },
- {
- "name": "OPENCV_DIR",
- "value": "D:/projects/packages/opencv3_4_6",
- "type": "PATH"
- },
- {
- "name": "PADDLE_DIR",
- "value": "D:/projects/packages/fluid_inference1_6_1",
- "type": "PATH"
- },
- {
- "name": "CMAKE_BUILD_TYPE",
- "value": "Release",
- "type": "STRING"
- }
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/contrib/RealTimeHumanSeg/cpp/README.md b/contrib/RealTimeHumanSeg/cpp/README.md
deleted file mode 100644
index 5f118413..00000000
--- a/contrib/RealTimeHumanSeg/cpp/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# 视频实时图像分割模型C++预测部署
-
-本文档主要介绍实时图像分割模型如何在`Windows`和`Linux`上完成基于`C++`的预测部署。
-
-## C++预测部署编译
-
-### 1. 下载模型
-点击右边下载:[模型下载地址](https://paddleseg.bj.bcebos.com/deploy/models/humanseg_paddleseg_int8.zip)
-
-模型文件路径将做为预测时的输入参数,请解压到合适的目录位置。
-
-### 2. 编译
-本项目支持在Windows和Linux上编译并部署C++项目,不同平台的编译请参考:
-- [Linux 编译](./docs/linux_build.md)
-- [Windows 使用 Visual Studio 2019编译](./docs/windows_build.md)
diff --git a/contrib/RealTimeHumanSeg/cpp/docs/linux_build.md b/contrib/RealTimeHumanSeg/cpp/docs/linux_build.md
deleted file mode 100644
index 823ff3ae..00000000
--- a/contrib/RealTimeHumanSeg/cpp/docs/linux_build.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# 视频实时人像分割模型Linux平台C++预测部署
-
-
-## 1. 系统和软件依赖
-
-### 1.1 操作系统及硬件要求
-
-- Ubuntu 14.04 或者 16.04 (其它平台未测试)
-- GCC版本4.8.5 ~ 4.9.2
-- 支持Intel MKL-DNN的CPU
-- NOTE: 如需在Nvidia GPU运行,请自行安装CUDA 9.0 / 10.0 + CUDNN 7.3+ (不支持9.1/10.1版本的CUDA)
-
-### 1.2 下载PaddlePaddle C++预测库
-
-PaddlePaddle C++ 预测库主要分为CPU版本和GPU版本。
-
-其中,GPU 版本支持`CUDA 10.0` 和 `CUDA 9.0`:
-
-以下为各版本C++预测库的下载链接:
-
-| 版本 | 链接 |
-| ---- | ---- |
-| CPU+MKL版 | [fluid_inference.tgz](https://paddle-inference-lib.bj.bcebos.com/1.6.3-cpu-avx-mkl/fluid_inference.tgz) |
-| CUDA9.0+MKL 版 | [fluid_inference.tgz](https://paddle-inference-lib.bj.bcebos.com/1.6.3-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz) |
-| CUDA10.0+MKL 版 | [fluid_inference.tgz](https://paddle-inference-lib.bj.bcebos.com/1.6.3-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz) |
-
-更多可用预测库版本,请点击以下链接下载:[C++预测库下载列表](https://paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/deploy/inference/build_and_install_lib_cn.html)
-
-
-下载并解压, 解压后的 `fluid_inference`目录包含的内容:
-```
-fluid_inference
-├── paddle # paddle核心库和头文件
-|
-├── third_party # 第三方依赖库和头文件
-|
-└── version.txt # 版本和编译信息
-```
-
-**注意:** 请把解压后的目录放到合适的路径,**该目录路径后续会作为编译依赖**使用。
-
-## 2. 编译与运行
-
-### 2.1 配置编译脚本
-
-打开文件`linux_build.sh`, 看到以下内容:
-```shell
-# 是否使用GPU
-WITH_GPU=OFF
-# Paddle 预测库路径
-PADDLE_DIR=/PATH/TO/fluid_inference/
-# CUDA库路径, 仅 WITH_GPU=ON 时设置
-CUDA_LIB=/PATH/TO/CUDA_LIB64/
-# CUDNN库路径,仅 WITH_GPU=ON 且 CUDA_LIB有效时设置
-CUDNN_LIB=/PATH/TO/CUDNN_LIB64/
-# OpenCV 库路径, 无须设置
-OPENCV_DIR=/PATH/TO/opencv3gcc4.8/
-
-cd build
-cmake .. \
- -DWITH_GPU=${WITH_GPU} \
- -DPADDLE_DIR=${PADDLE_DIR} \
- -DCUDA_LIB=${CUDA_LIB} \
- -DCUDNN_LIB=${CUDNN_LIB} \
- -DOPENCV_DIR=${OPENCV_DIR} \
- -DWITH_STATIC_LIB=OFF
-make -j4
-```
-
-把上述参数根据实际情况做修改后,运行脚本编译程序:
-```shell
-sh linux_build.sh
-```
-
-### 2.2. 运行和可视化
-
-可执行文件有 **2** 个参数,第一个是前面导出的`inference_model`路径,第二个是需要预测的视频路径。
-
-示例:
-```shell
-./build/main ./models /PATH/TO/TEST_VIDEO
-```
-
-点击下载[测试视频](https://paddleseg.bj.bcebos.com/deploy/data/test.avi)
-
-预测的结果保存在视频文件`result.avi`中。
diff --git a/contrib/RealTimeHumanSeg/cpp/docs/windows_build.md b/contrib/RealTimeHumanSeg/cpp/docs/windows_build.md
deleted file mode 100644
index 6937dbcf..00000000
--- a/contrib/RealTimeHumanSeg/cpp/docs/windows_build.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# 视频实时人像分割模型Windows平台C++预测部署
-
-## 1. 系统和软件依赖
-
-### 1.1 基础依赖
-
-- Windows 10 / Windows Server 2016+ (其它平台未测试)
-- Visual Studio 2019 (社区版或专业版均可)
-- CUDA 9.0 / 10.0 + CUDNN 7.3+ (不支持9.1/10.1版本的CUDA)
-
-### 1.2 下载OpenCV并设置环境变量
-
-- 在OpenCV官网下载适用于Windows平台的3.4.6版本: [点击下载](https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download)
-- 运行下载的可执行文件,将OpenCV解压至合适目录,这里以解压到`D:\projects\opencv`为例
-- 把OpenCV动态库加入到系统环境变量
- - 此电脑(我的电脑)->属性->高级系统设置->环境变量
- - 在系统变量中找到Path(如没有,自行创建),并双击编辑
- - 新建,将opencv路径填入并保存,如D:\projects\opencv\build\x64\vc14\bin
-
-**注意:** `OpenCV`的解压目录后续将做为编译配置项使用,所以请放置合适的目录中。
-
-### 1.3 下载PaddlePaddle C++ 预测库
-
-`PaddlePaddle` **C++ 预测库** 主要分为`CPU`和`GPU`版本, 其中`GPU版本`提供`CUDA 9.0` 和 `CUDA 10.0` 支持。
-
-常用的版本如下:
-
-| 版本 | 链接 |
-| ---- | ---- |
-| CPU+MKL版 | [fluid_inference_install_dir.zip](https://paddle-wheel.bj.bcebos.com/1.6.3/win-infer/mkl/cpu/fluid_inference_install_dir.zip) |
-| CUDA9.0+MKL 版 | [fluid_inference_install_dir.zip](https://paddle-wheel.bj.bcebos.com/1.6.3/win-infer/mkl/post97/fluid_inference_install_dir.zip) |
-| CUDA10.0+MKL 版 | [fluid_inference_install_dir.zip](https://paddle-wheel.bj.bcebos.com/1.6.3/win-infer/mkl/post107/fluid_inference_install_dir.zip) |
-
-更多不同平台的可用预测库版本,请[点击查看](https://paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/deploy/inference/windows_cpp_inference.html) 选择适合你的版本。
-
-
-下载并解压, 解压后的 `fluid_inference`目录包含的内容:
-```
-fluid_inference_install_dir
-├── paddle # paddle核心库和头文件
-|
-├── third_party # 第三方依赖库和头文件
-|
-└── version.txt # 版本和编译信息
-```
-
-**注意:** 这里的`fluid_inference_install_dir` 目录所在路径,将用于后面的编译参数设置,请放置在合适的位置。
-
-## 2. Visual Studio 2019 编译
-
-- 2.1 打开Visual Studio 2019 Community,点击`继续但无需代码`, 如下图:
-![step2.1](https://paddleseg.bj.bcebos.com/inference/vs2019_step1.png)
-
-- 2.2 点击 `文件`->`打开`->`CMake`, 如下图:
-![step2.2](https://paddleseg.bj.bcebos.com/inference/vs2019_step2.png)
-
-- 2.3 选择本项目根目录`CMakeList.txt`文件打开, 如下图:
-![step2.3](https://paddleseg.bj.bcebos.com/deploy/docs/vs2019_step2.3.png)
-
-- 2.4 点击:`项目`->`PaddleMaskDetector的CMake设置`
-![step2.4](https://paddleseg.bj.bcebos.com/deploy/docs/vs2019_step2.4.png)
-
-- 2.5 点击浏览设置`OPENCV_DIR`, `CUDA_LIB` 和 `PADDLE_DIR` 3个编译依赖库的位置, 设置完成后点击`保存并生成CMake缓存并加载变量`
-![step2.5](https://paddleseg.bj.bcebos.com/inference/vs2019_step5.png)
-
-- 2.6 点击`生成`->`全部生成` 编译项目
-![step2.6](https://paddleseg.bj.bcebos.com/inference/vs2019_step6.png)
-
-## 3. 运行程序
-
-成功编译后, 产出的可执行文件在项目子目录`out\build\x64-Release`目录, 按以下步骤运行代码:
-
-- 打开`cmd`切换至该目录
-- 运行以下命令传入模型路径与测试视频
-
-```shell
-main.exe ./models/ ./data/test.avi
-```
-第一个参数即人像分割预测模型的路径,第二个参数即要预测的视频。
-
-点击下载[测试视频](https://paddleseg.bj.bcebos.com/deploy/data/test.avi)
-
-运行后,预测结果保存在文件`result.avi`中。
diff --git a/contrib/RealTimeHumanSeg/cpp/humanseg.cc b/contrib/RealTimeHumanSeg/cpp/humanseg.cc
deleted file mode 100644
index b81c8120..00000000
--- a/contrib/RealTimeHumanSeg/cpp/humanseg.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-# include "humanseg.h"
-# include "humanseg_postprocess.h"
-
-// Normalize the image by (pix - mean) * scale
-void NormalizeImage(
- const std::vector &mean,
- const std::vector &scale,
- cv::Mat& im, // NOLINT
- float* input_buffer) {
- int height = im.rows;
- int width = im.cols;
- int stride = width * height;
- for (int h = 0; h < height; h++) {
- for (int w = 0; w < width; w++) {
- int base = h * width + w;
- input_buffer[base + 0 * stride] =
- (im.at(h, w)[0] - mean[0]) * scale[0];
- input_buffer[base + 1 * stride] =
- (im.at(h, w)[1] - mean[1]) * scale[1];
- input_buffer[base + 2 * stride] =
- (im.at(h, w)[2] - mean[2]) * scale[2];
- }
- }
-}
-
-// Load Model and return model predictor
-void LoadModel(
- const std::string& model_dir,
- bool use_gpu,
- std::unique_ptr* predictor) {
- // Config the model info
- paddle::AnalysisConfig config;
- auto prog_file = model_dir + "/__model__";
- auto params_file = model_dir + "/__params__";
- config.SetModel(prog_file, params_file);
- if (use_gpu) {
- config.EnableUseGpu(100, 0);
- } else {
- config.DisableGpu();
- }
- config.SwitchUseFeedFetchOps(false);
- config.SwitchSpecifyInputNames(true);
- // Memory optimization
- config.EnableMemoryOptim();
- *predictor = std::move(CreatePaddlePredictor(config));
-}
-
-void HumanSeg::Preprocess(const cv::Mat& image_mat) {
- // Clone the image : keep the original mat for postprocess
- cv::Mat im = image_mat.clone();
- auto eval_wh = cv::Size(eval_size_[0], eval_size_[1]);
- cv::resize(im, im, eval_wh, 0.f, 0.f, cv::INTER_LINEAR);
-
- im.convertTo(im, CV_32FC3, 1.0);
- int rc = im.channels();
- int rh = im.rows;
- int rw = im.cols;
- input_shape_ = {1, rc, rh, rw};
- input_data_.resize(1 * rc * rh * rw);
- float* buffer = input_data_.data();
- NormalizeImage(mean_, scale_, im, input_data_.data());
-}
-
-cv::Mat HumanSeg::Postprocess(const cv::Mat& im) {
- int h = input_shape_[2];
- int w = input_shape_[3];
- scoremap_data_.resize(3 * h * w * sizeof(float));
- float* base = output_data_.data() + h * w;
- for (int i = 0; i < h * w; ++i) {
- scoremap_data_[i] = uchar(base[i] * 255);
- }
-
- cv::Mat im_scoremap = cv::Mat(h, w, CV_8UC1);
- im_scoremap.data = scoremap_data_.data();
- cv::resize(im_scoremap, im_scoremap, cv::Size(im.cols, im.rows));
- im_scoremap.convertTo(im_scoremap, CV_32FC1, 1 / 255.0);
-
- float* pblob = reinterpret_cast(im_scoremap.data);
- int out_buff_capacity = 10 * im.cols * im.rows * sizeof(float);
- segout_data_.resize(out_buff_capacity);
- unsigned char* seg_result = segout_data_.data();
- MergeProcess(im.data, pblob, im.rows, im.cols, seg_result);
- cv::Mat seg_mat(im.rows, im.cols, CV_8UC1, seg_result);
- cv::resize(seg_mat, seg_mat, cv::Size(im.cols, im.rows));
- cv::GaussianBlur(seg_mat, seg_mat, cv::Size(5, 5), 0, 0);
- float fg_threshold = 0.8;
- float bg_threshold = 0.4;
- cv::Mat show_seg_mat;
- seg_mat.convertTo(seg_mat, CV_32FC1, 1 / 255.0);
- ThresholdMask(seg_mat, fg_threshold, bg_threshold, show_seg_mat);
- auto out_im = MergeSegMat(show_seg_mat, im);
- return out_im;
-}
-
-cv::Mat HumanSeg::Predict(const cv::Mat& im) {
- // Preprocess image
- Preprocess(im);
- // Prepare input tensor
- auto input_names = predictor_->GetInputNames();
- auto in_tensor = predictor_->GetInputTensor(input_names[0]);
- in_tensor->Reshape(input_shape_);
- in_tensor->copy_from_cpu(input_data_.data());
- // Run predictor
- predictor_->ZeroCopyRun();
- // Get output tensor
- auto output_names = predictor_->GetOutputNames();
- auto out_tensor = predictor_->GetOutputTensor(output_names[0]);
- auto output_shape = out_tensor->shape();
- // Calculate output length
- int output_size = 1;
- for (int j = 0; j < output_shape.size(); ++j) {
- output_size *= output_shape[j];
- }
- output_data_.resize(output_size);
- out_tensor->copy_to_cpu(output_data_.data());
- // Postprocessing result
- return Postprocess(im);
-}
diff --git a/contrib/RealTimeHumanSeg/cpp/humanseg.h b/contrib/RealTimeHumanSeg/cpp/humanseg.h
deleted file mode 100644
index edaf825f..00000000
--- a/contrib/RealTimeHumanSeg/cpp/humanseg.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "paddle_inference_api.h" // NOLINT
-
-// Load Paddle Inference Model
-void LoadModel(
- const std::string& model_dir,
- bool use_gpu,
- std::unique_ptr* predictor);
-
-class HumanSeg {
- public:
- explicit HumanSeg(const std::string& model_dir,
- const std::vector& mean,
- const std::vector& scale,
- const std::vector& eval_size,
- bool use_gpu = false) :
- mean_(mean),
- scale_(scale),
- eval_size_(eval_size) {
- LoadModel(model_dir, use_gpu, &predictor_);
- }
-
- // Run predictor
- cv::Mat Predict(const cv::Mat& im);
-
- private:
- // Preprocess image and copy data to input buffer
- void Preprocess(const cv::Mat& im);
- // Postprocess result
- cv::Mat Postprocess(const cv::Mat& im);
-
- std::unique_ptr predictor_;
- std::vector input_data_;
- std::vector input_shape_;
- std::vector output_data_;
- std::vector scoremap_data_;
- std::vector segout_data_;
- std::vector mean_;
- std::vector scale_;
- std::vector eval_size_;
-};
diff --git a/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.cc b/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.cc
deleted file mode 100644
index a373df39..00000000
--- a/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "humanseg_postprocess.h" // NOLINT
-
-int HumanSegTrackFuse(const cv::Mat &track_fg_cfd,
- const cv::Mat &dl_fg_cfd,
- const cv::Mat &dl_weights,
- const cv::Mat &is_track,
- const float cfd_diff_thres,
- const int patch_size,
- cv::Mat cur_fg_cfd) {
- float *cur_fg_cfd_ptr = reinterpret_cast(cur_fg_cfd.data);
- float *dl_fg_cfd_ptr = reinterpret_cast(dl_fg_cfd.data);
- float *track_fg_cfd_ptr = reinterpret_cast(track_fg_cfd.data);
- float *dl_weights_ptr = reinterpret_cast(dl_weights.data);
- uchar *is_track_ptr = reinterpret_cast(is_track.data);
- int y_offset = 0;
- int ptr_offset = 0;
- int h = track_fg_cfd.rows;
- int w = track_fg_cfd.cols;
- float dl_fg_score = 0.0;
- float track_fg_score = 0.0;
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- dl_fg_score = dl_fg_cfd_ptr[ptr_offset];
- if (is_track_ptr[ptr_offset] > 0) {
- track_fg_score = track_fg_cfd_ptr[ptr_offset];
- if (dl_fg_score > 0.9 || dl_fg_score < 0.1) {
- if (dl_weights_ptr[ptr_offset] <= 0.10) {
- cur_fg_cfd_ptr[ptr_offset] = dl_fg_score * 0.3
- + track_fg_score * 0.7;
- } else {
- cur_fg_cfd_ptr[ptr_offset] = dl_fg_score * 0.4
- + track_fg_score * 0.6;
- }
- } else {
- cur_fg_cfd_ptr[ptr_offset] = dl_fg_score * dl_weights_ptr[ptr_offset]
- + track_fg_score * (1 - dl_weights_ptr[ptr_offset]);
- }
- } else {
- cur_fg_cfd_ptr[ptr_offset] = dl_fg_score;
- }
- ++ptr_offset;
- }
- y_offset += w;
- ptr_offset = y_offset;
- }
- return 0;
-}
-
-int HumanSegTracking(const cv::Mat &prev_gray,
- const cv::Mat &cur_gray,
- const cv::Mat &prev_fg_cfd,
- int patch_size,
- cv::Mat track_fg_cfd,
- cv::Mat is_track,
- cv::Mat dl_weights,
- cv::Ptr disflow) {
- cv::Mat flow_fw;
- disflow->calc(prev_gray, cur_gray, flow_fw);
-
- cv::Mat flow_bw;
- disflow->calc(cur_gray, prev_gray, flow_bw);
-
- float double_check_thres = 8;
-
- cv::Point2f fxy_fw;
- int dy_fw = 0;
- int dx_fw = 0;
- cv::Point2f fxy_bw;
- int dy_bw = 0;
- int dx_bw = 0;
-
- float *prev_fg_cfd_ptr = reinterpret_cast(prev_fg_cfd.data);
- float *track_fg_cfd_ptr = reinterpret_cast(track_fg_cfd.data);
- float *dl_weights_ptr = reinterpret_cast(dl_weights.data);
- uchar *is_track_ptr = reinterpret_cast(is_track.data);
-
- int prev_y_offset = 0;
- int prev_ptr_offset = 0;
- int cur_ptr_offset = 0;
- float *flow_fw_ptr = reinterpret_cast(flow_fw.data);
-
- float roundy_fw = 0.0;
- float roundx_fw = 0.0;
- float roundy_bw = 0.0;
- float roundx_bw = 0.0;
-
- int h = prev_fg_cfd.rows;
- int w = prev_fg_cfd.cols;
- for (int r = 0; r < h; ++r) {
- for (int c = 0; c < w; ++c) {
- ++prev_ptr_offset;
-
- fxy_fw = flow_fw.ptr(r)[c];
- roundy_fw = fxy_fw.y >= 0 ? 0.5 : -0.5;
- roundx_fw = fxy_fw.x >= 0 ? 0.5 : -0.5;
- dy_fw = static_cast(fxy_fw.y + roundy_fw);
- dx_fw = static_cast(fxy_fw.x + roundx_fw);
-
- int cur_x = c + dx_fw;
- int cur_y = r + dy_fw;
-
- if (cur_x < 0
- || cur_x >= h
- || cur_y < 0
- || cur_y >= w) {
- continue;
- }
- fxy_bw = flow_bw.ptr(cur_y)[cur_x];
- roundy_bw = fxy_bw.y >= 0 ? 0.5 : -0.5;
- roundx_bw = fxy_bw.x >= 0 ? 0.5 : -0.5;
- dy_bw = static_cast(fxy_bw.y + roundy_bw);
- dx_bw = static_cast(fxy_bw.x + roundx_bw);
-
- auto total = (dy_fw + dy_bw) * (dy_fw + dy_bw)
- + (dx_fw + dx_bw) * (dx_fw + dx_bw);
- if (total >= double_check_thres) {
- continue;
- }
-
- cur_ptr_offset = cur_y * w + cur_x;
- if (abs(dy_fw) <= 0
- && abs(dx_fw) <= 0
- && abs(dy_bw) <= 0
- && abs(dx_bw) <= 0) {
- dl_weights_ptr[cur_ptr_offset] = 0.05;
- }
- is_track_ptr[cur_ptr_offset] = 1;
- track_fg_cfd_ptr[cur_ptr_offset] = prev_fg_cfd_ptr[prev_ptr_offset];
- }
- prev_y_offset += w;
- prev_ptr_offset = prev_y_offset - 1;
- }
- return 0;
-}
-
-int MergeProcess(const uchar *im_buff,
- const float *scoremap_buff,
- const int height,
- const int width,
- uchar *result_buff) {
- cv::Mat prev_fg_cfd;
- cv::Mat cur_fg_cfd;
- cv::Mat cur_fg_mask;
- cv::Mat track_fg_cfd;
- cv::Mat prev_gray;
- cv::Mat cur_gray;
- cv::Mat bgr_temp;
- cv::Mat is_track;
- cv::Mat static_roi;
- cv::Mat weights;
- cv::Ptr disflow =
- cv::optflow::createOptFlow_DIS(
- cv::optflow::DISOpticalFlow::PRESET_ULTRAFAST);
-
- bool is_init = false;
- const float *cfd_ptr = scoremap_buff;
- if (!is_init) {
- is_init = true;
- cur_fg_cfd = cv::Mat(height, width, CV_32FC1, cv::Scalar::all(0));
- memcpy(cur_fg_cfd.data, cfd_ptr, height * width * sizeof(float));
- cur_fg_mask = cv::Mat(height, width, CV_8UC1, cv::Scalar::all(0));
-
- if (height <= 64 || width <= 64) {
- disflow->setFinestScale(1);
- } else if (height <= 160 || width <= 160) {
- disflow->setFinestScale(2);
- } else {
- disflow->setFinestScale(3);
- }
- is_track = cv::Mat(height, width, CV_8UC1, cv::Scalar::all(0));
- static_roi = cv::Mat(height, width, CV_8UC1, cv::Scalar::all(0));
- track_fg_cfd = cv::Mat(height, width, CV_32FC1, cv::Scalar::all(0));
-
- bgr_temp = cv::Mat(height, width, CV_8UC3);
- memcpy(bgr_temp.data, im_buff, height * width * 3 * sizeof(uchar));
- cv::cvtColor(bgr_temp, cur_gray, cv::COLOR_BGR2GRAY);
- weights = cv::Mat(height, width, CV_32FC1, cv::Scalar::all(0.30));
- } else {
- memcpy(cur_fg_cfd.data, cfd_ptr, height * width * sizeof(float));
- memcpy(bgr_temp.data, im_buff, height * width * 3 * sizeof(uchar));
- cv::cvtColor(bgr_temp, cur_gray, cv::COLOR_BGR2GRAY);
- memset(is_track.data, 0, height * width * sizeof(uchar));
- memset(static_roi.data, 0, height * width * sizeof(uchar));
- weights = cv::Mat(height, width, CV_32FC1, cv::Scalar::all(0.30));
- HumanSegTracking(prev_gray,
- cur_gray,
- prev_fg_cfd,
- 0,
- track_fg_cfd,
- is_track,
- weights,
- disflow);
- HumanSegTrackFuse(track_fg_cfd,
- cur_fg_cfd,
- weights,
- is_track,
- 1.1,
- 0,
- cur_fg_cfd);
- }
- int ksize = 3;
- cv::GaussianBlur(cur_fg_cfd, cur_fg_cfd, cv::Size(ksize, ksize), 0, 0);
- prev_fg_cfd = cur_fg_cfd.clone();
- prev_gray = cur_gray.clone();
- cur_fg_cfd.convertTo(cur_fg_mask, CV_8UC1, 255);
- memcpy(result_buff, cur_fg_mask.data, height * width);
- return 0;
-}
-
-cv::Mat MergeSegMat(const cv::Mat& seg_mat,
- const cv::Mat& ori_frame) {
- cv::Mat return_frame;
- cv::resize(ori_frame, return_frame, cv::Size(ori_frame.cols, ori_frame.rows));
- for (int i = 0; i < ori_frame.rows; i++) {
- for (int j = 0; j < ori_frame.cols; j++) {
- float score = seg_mat.at(i, j) / 255.0;
- if (score > 0.1) {
- return_frame.at(i, j)[2] = static_cast((1 - score) * 255
- + score*return_frame.at(i, j)[2]);
- return_frame.at(i, j)[1] = static_cast((1 - score) * 255
- + score*return_frame.at(i, j)[1]);
- return_frame.at(i, j)[0] = static_cast((1 - score) * 255
- + score*return_frame.at(i, j)[0]);
- } else {
- return_frame.at(i, j) = {255, 255, 255};
- }
- }
- }
- return return_frame;
-}
-
-int ThresholdMask(const cv::Mat &fg_cfd,
- const float fg_thres,
- const float bg_thres,
- cv::Mat& fg_mask) {
- if (fg_cfd.type() != CV_32FC1) {
- printf("ThresholdMask: type is not CV_32FC1.\n");
- return -1;
- }
- if (!(fg_mask.type() == CV_8UC1
- && fg_mask.rows == fg_cfd.rows
- && fg_mask.cols == fg_cfd.cols)) {
- fg_mask = cv::Mat(fg_cfd.rows, fg_cfd.cols, CV_8UC1, cv::Scalar::all(0));
- }
-
- for (int r = 0; r < fg_cfd.rows; ++r) {
- for (int c = 0; c < fg_cfd.cols; ++c) {
- float score = fg_cfd.at(r, c);
- if (score < bg_thres) {
- fg_mask.at(r, c) = 0;
- } else if (score > fg_thres) {
- fg_mask.at(r, c) = 255;
- } else {
- fg_mask.at(r, c) = static_cast(
- (score-bg_thres) / (fg_thres - bg_thres) * 255);
- }
- }
- }
- return 0;
-}
diff --git a/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.h b/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.h
deleted file mode 100644
index f5059857..00000000
--- a/contrib/RealTimeHumanSeg/cpp/humanseg_postprocess.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include
-#include
-#include
-#include
-
-int ThresholdMask(const cv::Mat &fg_cfd,
- const float fg_thres,
- const float bg_thres,
- cv::Mat& fg_mask);
-
-cv::Mat MergeSegMat(const cv::Mat& seg_mat,
- const cv::Mat& ori_frame);
-
-int MergeProcess(const uchar *im_buff,
- const float *im_scoremap_buff,
- const int height,
- const int width,
- uchar *result_buff);
diff --git a/contrib/RealTimeHumanSeg/cpp/linux_build.sh b/contrib/RealTimeHumanSeg/cpp/linux_build.sh
deleted file mode 100644
index da0f75ef..00000000
--- a/contrib/RealTimeHumanSeg/cpp/linux_build.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-OPENCV_URL=https://bj.bcebos.com/paddleseg/deps/opencv346gcc4.8contrib.tar.bz2
-if [ ! -d "./deps/opencv346_with_contrib" ]; then
- mkdir -p deps
- cd deps
- wget -c ${OPENCV_URL}
- tar xvfj opencv346gcc4.8contrib.tar.bz2
- rm -rf opencv346gcc4.8contrib.tar.bz2
- cd ..
-fi
-
-WITH_GPU=OFF
-PADDLE_DIR=/root/project/fluid_inference/
-CUDA_LIB=/usr/local/cuda-10.0/lib64/
-CUDNN_LIB=/usr/local/cuda-10.0/lib64/
-OPENCV_DIR=$(pwd)/deps/opencv346_with_contrib/
-echo ${OPENCV_DIR}
-
-rm -rf build
-mkdir -p build
-cd build
-
-cmake .. \
- -DWITH_GPU=${WITH_GPU} \
- -DPADDLE_DIR=${PADDLE_DIR} \
- -DCUDA_LIB=${CUDA_LIB} \
- -DCUDNN_LIB=${CUDNN_LIB} \
- -DOPENCV_DIR=${OPENCV_DIR} \
- -DWITH_STATIC_LIB=OFF
-make clean
-make -j12
-
diff --git a/contrib/RealTimeHumanSeg/cpp/main.cc b/contrib/RealTimeHumanSeg/cpp/main.cc
deleted file mode 100644
index 303051f0..00000000
--- a/contrib/RealTimeHumanSeg/cpp/main.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include
-#include
-
-#include "humanseg.h" // NOLINT
-#include "humanseg_postprocess.h" // NOLINT
-
-// Do predicting on a video file
-int VideoPredict(const std::string& video_path, HumanSeg& seg)
-{
- cv::VideoCapture capture;
- capture.open(video_path.c_str());
- if (!capture.isOpened()) {
- printf("can not open video : %s\n", video_path.c_str());
- return -1;
- }
-
- int video_width = static_cast(capture.get(CV_CAP_PROP_FRAME_WIDTH));
- int video_height = static_cast(capture.get(CV_CAP_PROP_FRAME_HEIGHT));
- cv::VideoWriter video_out;
- std::string video_out_path = "result.avi";
- video_out.open(video_out_path.c_str(),
- CV_FOURCC('M', 'J', 'P', 'G'),
- 30.0,
- cv::Size(video_width, video_height),
- true);
- if (!video_out.isOpened()) {
- printf("create video writer failed!\n");
- return -1;
- }
- cv::Mat frame;
- while (capture.read(frame)) {
- if (frame.empty()) {
- break;
- }
- cv::Mat out_im = seg.Predict(frame);
- video_out.write(out_im);
- }
- capture.release();
- video_out.release();
- return 0;
-}
-
-// Do predicting on a image file
-int ImagePredict(const std::string& image_path, HumanSeg& seg)
-{
- cv::Mat img = imread(image_path, cv::IMREAD_COLOR);
- cv::Mat out_im = seg.Predict(img);
- imwrite("result.jpeg", out_im);
- return 0;
-}
-
-int main(int argc, char* argv[]) {
- if (argc < 3 || argc > 4) {
- std::cout << "Usage:"
- << "./humanseg ./models/ ./data/test.avi"
- << std::endl;
- return -1;
- }
-
- bool use_gpu = (argc == 4 ? std::stoi(argv[3]) : false);
- auto model_dir = std::string(argv[1]);
- auto input_path = std::string(argv[2]);
-
- // Init Model
- std::vector means = {104.008, 116.669, 122.675};
- std::vector scale = {1.000, 1.000, 1.000};
- std::vector eval_sz = {192, 192};
- HumanSeg seg(model_dir, means, scale, eval_sz, use_gpu);
-
- // Call ImagePredict while input_path is a image file path
- // The output will be saved as result.jpeg
- // ImagePredict(input_path, seg);
-
- // Call VideoPredict while input_path is a video file path
- // The output will be saved as result.avi
- VideoPredict(input_path, seg);
- return 0;
-}
diff --git a/contrib/RealTimeHumanSeg/python/README.md b/contrib/RealTimeHumanSeg/python/README.md
deleted file mode 100644
index 1e089c9f..00000000
--- a/contrib/RealTimeHumanSeg/python/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# 实时人像分割Python预测部署方案
-
-本方案基于Python实现,最小化依赖并把所有模型加载、数据预处理、预测、光流处理等后处理都封装在文件`infer.py`中,用户可以直接使用或集成到自己项目中。
-
-
-## 前置依赖
-- Windows(7,8,10) / Linux (Ubuntu 16.04) or MacOS 10.1+
-- Paddle 1.6.1+
-- Python 3.0+
-
-注意:
-1. 仅测试过Paddle1.6 和 1.7, 其它版本不支持
-2. MacOS上不支持GPU预测
-3. Python2上未测试
-
-其它未涉及情形,能正常安装`Paddle` 和`OpenCV`通常都能正常使用。
-
-
-## 安装依赖
-### 1. 安装paddle
-
-PaddlePaddle的安装, 请按照[官网指引](https://paddlepaddle.org.cn/install/quick)安装合适自己的版本。
-
-### 2. 安装其它依赖
-
-执行如下命令
-
-```shell
-pip install -r requirements.txt
-```
-
-## 运行
-
-
-1. 输入图片进行分割
-```
-python infer.py --model_dir /PATH/TO/INFERENCE/MODEL --img_path /PATH/TO/INPUT/IMAGE
-```
-
-预测结果会保存为`result.jpeg`。
-2. 输入视频进行分割
-```shell
-python infer.py --model_dir /PATH/TO/INFERENCE/MODEL --video_path /PATH/TO/INPUT/VIDEO
-```
-
-预测结果会保存在`result.avi`。
-
-3. 使用摄像头视频流
-```shell
-python infer.py --model_dir /PATH/TO/INFERENCE/MODEL --use_camera 1
-```
-预测结果会通过可视化窗口实时显示。
-
-**注意:**
-
-
-`GPU`默认关闭, 如果要使用`GPU`进行加速,则先运行
-```
-export CUDA_VISIBLE_DEVICES=0
-```
-然后在前面的预测命令中增加参数`--use_gpu 1`即可。
diff --git a/contrib/RealTimeHumanSeg/python/infer.py b/contrib/RealTimeHumanSeg/python/infer.py
deleted file mode 100644
index 73df081e..00000000
--- a/contrib/RealTimeHumanSeg/python/infer.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# coding: utf8
-# copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""实时人像分割Python预测部署"""
-
-import os
-import argparse
-import numpy as np
-import cv2
-
-import paddle.fluid as fluid
-
-
-def human_seg_tracking(pre_gray, cur_gray, prev_cfd, dl_weights, disflow):
- """计算光流跟踪匹配点和光流图
- 输入参数:
- pre_gray: 上一帧灰度图
- cur_gray: 当前帧灰度图
- prev_cfd: 上一帧光流图
- dl_weights: 融合权重图
- disflow: 光流数据结构
- 返回值:
- is_track: 光流点跟踪二值图,即是否具有光流点匹配
- track_cfd: 光流跟踪图
- """
- check_thres = 8
- hgt, wdh = pre_gray.shape[:2]
- track_cfd = np.zeros_like(prev_cfd)
- is_track = np.zeros_like(pre_gray)
- # 计算前向光流
- flow_fw = disflow.calc(pre_gray, cur_gray, None)
- # 计算后向光流
- flow_bw = disflow.calc(cur_gray, pre_gray, None)
- get_round = lambda data: (int)(data + 0.5) if data >= 0 else (int)(data -0.5)
- for row in range(hgt):
- for col in range(wdh):
- # 计算光流处理后对应点坐标
- # (row, col) -> (cur_x, cur_y)
- fxy_fw = flow_fw[row, col]
- dx_fw = get_round(fxy_fw[0])
- cur_x = dx_fw + col
- dy_fw = get_round(fxy_fw[1])
- cur_y = dy_fw + row
- if cur_x < 0 or cur_x >= wdh or cur_y < 0 or cur_y >= hgt:
- continue
- fxy_bw = flow_bw[cur_y, cur_x]
- dx_bw = get_round(fxy_bw[0])
- dy_bw = get_round(fxy_bw[1])
- # 光流移动小于阈值
- lmt = ((dy_fw + dy_bw) * (dy_fw + dy_bw) + (dx_fw + dx_bw) * (dx_fw + dx_bw))
- if lmt >= check_thres:
- continue
- # 静止点降权
- if abs(dy_fw) <= 0 and abs(dx_fw) <= 0 and abs(dy_bw) <= 0 and abs(dx_bw) <= 0:
- dl_weights[cur_y, cur_x] = 0.05
- is_track[cur_y, cur_x] = 1
- track_cfd[cur_y, cur_x] = prev_cfd[row, col]
- return track_cfd, is_track, dl_weights
-
-
-def human_seg_track_fuse(track_cfd, dl_cfd, dl_weights, is_track):
- """光流追踪图和人像分割结构融合
- 输入参数:
- track_cfd: 光流追踪图
- dl_cfd: 当前帧分割结果
- dl_weights: 融合权重图
- is_track: 光流点匹配二值图
- 返回值:
- cur_cfd: 光流跟踪图和人像分割结果融合图
- """
- cur_cfd = dl_cfd.copy()
- idxs = np.where(is_track > 0)
- for i in range(len(idxs)):
- x, y = idxs[0][i], idxs[1][i]
- dl_score = dl_cfd[y, x]
- track_score = track_cfd[y, x]
- if dl_score > 0.9 or dl_score < 0.1:
- if dl_weights[x, y] < 0.1:
- cur_cfd[x, y] = 0.3 * dl_score + 0.7 * track_score
- else:
- cur_cfd[x, y] = 0.4 * dl_score + 0.6 * track_score
- else:
- cur_cfd[x, y] = dl_weights[x, y] * dl_score + (1 - dl_weights[x, y]) * track_score
- return cur_cfd
-
-
-def threshold_mask(img, thresh_bg, thresh_fg):
- """设置背景和前景阈值mask
- 输入参数:
- img : 原始图像, np.uint8 类型.
- thresh_bg : 背景阈值百分比,低于该值置为0.
- thresh_fg : 前景阈值百分比,超过该值置为1.
- 返回值:
- dst : 原始图像设置完前景背景阈值mask结果, np.float32 类型.
- """
- dst = (img / 255.0 - thresh_bg) / (thresh_fg - thresh_bg)
- dst[np.where(dst > 1)] = 1
- dst[np.where(dst < 0)] = 0
- return dst.astype(np.float32)
-
-
-def optflow_handle(cur_gray, scoremap, is_init):
- """光流优化
- Args:
- cur_gray : 当前帧灰度图
- scoremap : 当前帧分割结果
- is_init : 是否第一帧
- Returns:
- dst : 光流追踪图和预测结果融合图, 类型为 np.float32
- """
- width, height = scoremap.shape[0], scoremap.shape[1]
- disflow = cv2.DISOpticalFlow_create(
- cv2.DISOPTICAL_FLOW_PRESET_ULTRAFAST)
- prev_gray = np.zeros((height, width), np.uint8)
- prev_cfd = np.zeros((height, width), np.float32)
- cur_cfd = scoremap.copy()
- if is_init:
- is_init = False
- if height <= 64 or width <= 64:
- disflow.setFinestScale(1)
- elif height <= 160 or width <= 160:
- disflow.setFinestScale(2)
- else:
- disflow.setFinestScale(3)
- fusion_cfd = cur_cfd
- else:
- weights = np.ones((width, height), np.float32) * 0.3
- track_cfd, is_track, weights = human_seg_tracking(
- prev_gray, cur_gray, prev_cfd, weights, disflow)
- fusion_cfd = human_seg_track_fuse(track_cfd, cur_cfd, weights, is_track)
- fusion_cfd = cv2.GaussianBlur(fusion_cfd, (3, 3), 0)
- return fusion_cfd
-
-
-class HumanSeg:
- """人像分割类
- 封装了人像分割模型的加载,数据预处理,预测,后处理等
- """
- def __init__(self, model_dir, mean, scale, eval_size, use_gpu=False):
-
- self.mean = np.array(mean).reshape((3, 1, 1))
- self.scale = np.array(scale).reshape((3, 1, 1))
- self.eval_size = eval_size
- self.load_model(model_dir, use_gpu)
-
- def load_model(self, model_dir, use_gpu):
- """加载模型并创建predictor
- Args:
- model_dir: 预测模型路径, 包含 `__model__` 和 `__params__`
- use_gpu: 是否使用GPU加速
- """
- prog_file = os.path.join(model_dir, '__model__')
- params_file = os.path.join(model_dir, '__params__')
- config = fluid.core.AnalysisConfig(prog_file, params_file)
- if use_gpu:
- config.enable_use_gpu(100, 0)
- config.switch_ir_optim(True)
- else:
- config.disable_gpu()
- config.disable_glog_info()
- config.switch_specify_input_names(True)
- config.enable_memory_optim()
- self.predictor = fluid.core.create_paddle_predictor(config)
-
- def preprocess(self, image):
- """图像预处理
- hwc_rgb 转换为 chw_bgr,并进行归一化
- 输入参数:
- image: 原始图像
- 返回值:
- 经过预处理后的图片结果
- """
- img_mat = cv2.resize(
- image, self.eval_size, interpolation=cv2.INTER_LINEAR)
- # HWC -> CHW
- img_mat = img_mat.swapaxes(1, 2)
- img_mat = img_mat.swapaxes(0, 1)
- # Convert to float
- img_mat = img_mat[:, :, :].astype('float32')
- # img_mat = (img_mat - mean) * scale
- img_mat = img_mat - self.mean
- img_mat = img_mat * self.scale
- img_mat = img_mat[np.newaxis, :, :, :]
- return img_mat
-
- def postprocess(self, image, output_data):
- """对预测结果进行后处理
- Args:
- image: 原始图,opencv 图片对象
- output_data: Paddle预测结果原始数据
- Returns:
- 原图和预测结果融合并做了光流优化的结果图
- """
- scoremap = output_data[0, 1, :, :]
- scoremap = (scoremap * 255).astype(np.uint8)
- ori_h, ori_w = image.shape[0], image.shape[1]
- evl_h, evl_w = self.eval_size[0], self.eval_size[1]
- # 光流处理
- cur_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
- cur_gray = cv2.resize(cur_gray, (evl_w, evl_h))
- optflow_map = optflow_handle(cur_gray, scoremap, False)
- optflow_map = cv2.GaussianBlur(optflow_map, (3, 3), 0)
- optflow_map = threshold_mask(optflow_map, thresh_bg=0.2, thresh_fg=0.8)
- optflow_map = cv2.resize(optflow_map, (ori_w, ori_h))
- optflow_map = np.repeat(optflow_map[:, :, np.newaxis], 3, axis=2)
- bg_im = np.ones_like(optflow_map) * 255
- comb = (optflow_map * image + (1 - optflow_map) * bg_im).astype(np.uint8)
- return comb
-
- def run_predict(self, image):
- """运行预测并返回可视化结果图
- 输入参数:
- image: 需要预测的原始图, opencv图片对象
- 返回值:
- 可视化的预测结果图
- """
- im_mat = self.preprocess(image)
- im_tensor = fluid.core.PaddleTensor(im_mat.copy().astype('float32'))
- output_data = self.predictor.run([im_tensor])[0]
- output_data = output_data.as_ndarray()
- return self.postprocess(image, output_data)
-
-
-def predict_image(seg, image_path):
- """对图片文件进行分割
- 结果保存到`result.jpeg`文件中
- """
- img_mat = cv2.imread(image_path)
- img_mat = seg.run_predict(img_mat)
- cv2.imwrite('result.jpeg', img_mat)
-
-
-def predict_video(seg, video_path):
- """对视频文件进行分割
- 结果保存到`result.avi`文件中
- """
- cap = cv2.VideoCapture(video_path)
- if not cap.isOpened():
- print("Error opening video stream or file")
- return
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
- fps = cap.get(cv2.CAP_PROP_FPS)
- # 用于保存预测结果视频
- out = cv2.VideoWriter('result.avi',
- cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps,
- (width, height))
- # 开始获取视频帧
- while cap.isOpened():
- ret, frame = cap.read()
- if ret:
- img_mat = seg.run_predict(frame)
- out.write(img_mat)
- else:
- break
- cap.release()
- out.release()
-
-
-def predict_camera(seg):
- """从摄像头获取视频流进行预测
- 视频分割结果实时显示到可视化窗口中
- """
- cap = cv2.VideoCapture(0)
- if not cap.isOpened():
- print("Error opening video stream or file")
- return
- # Start capturing from video
- while cap.isOpened():
- ret, frame = cap.read()
- if ret:
- img_mat = seg.run_predict(frame)
- cv2.imshow('HumanSegmentation', img_mat)
- if cv2.waitKey(1) & 0xFF == ord('q'):
- break
- else:
- break
- cap.release()
-
-
-def main(args):
- """预测程序入口
- 完成模型加载, 对视频、摄像头、图片文件等预测过程
- """
- model_dir = args.model_dir
- use_gpu = args.use_gpu
-
- # 加载模型
- mean = [104.008, 116.669, 122.675]
- scale = [1.0, 1.0, 1.0]
- eval_size = (192, 192)
- seg = HumanSeg(model_dir, mean, scale, eval_size, use_gpu)
- if args.use_camera:
- # 开启摄像头
- predict_camera(seg)
- elif args.video_path:
- # 使用视频文件作为输入
- predict_video(seg, args.video_path)
- elif args.img_path:
- # 使用图片文件作为输入
- predict_image(seg, args.img_path)
-
-
-def parse_args():
- """解析命令行参数
- """
- parser = argparse.ArgumentParser('Realtime Human Segmentation')
- parser.add_argument('--model_dir',
- type=str,
- default='',
- help='path of human segmentation model')
- parser.add_argument('--img_path',
- type=str,
- default='',
- help='path of input image')
- parser.add_argument('--video_path',
- type=str,
- default='',
- help='path of input video')
- parser.add_argument('--use_camera',
- type=bool,
- default=False,
- help='input video stream from camera')
- parser.add_argument('--use_gpu',
- type=bool,
- default=False,
- help='enable gpu')
- return parser.parse_args()
-
-
-if __name__ == "__main__":
- args = parse_args()
- main(args)
diff --git a/contrib/RealTimeHumanSeg/python/requirements.txt b/contrib/RealTimeHumanSeg/python/requirements.txt
deleted file mode 100644
index 953dae0c..00000000
--- a/contrib/RealTimeHumanSeg/python/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-opencv-python==4.1.2.30
-opencv-contrib-python==4.2.0.32
--
GitLab