Commit 0d97cc8c authored by Sugon_ldc's avatar Sugon_ldc
Browse files

add new model

parents
Pipeline #316 failed with stages
in 0 seconds
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="cpu_thread_num_entries">
<item>1 threads</item>
<item>2 threads</item>
<item>4 threads</item>
<item>8 threads</item>
</string-array>
<string-array name="cpu_thread_num_values">
<item>1</item>
<item>2</item>
<item>4</item>
<item>8</item>
</string-array>
<string-array name="cpu_power_mode_entries">
<item>HIGH(only big cores)</item>
<item>LOW(only LITTLE cores)</item>
<item>FULL(all cores)</item>
<item>NO_BIND(depends on system)</item>
<item>RAND_HIGH</item>
<item>RAND_LOW</item>
</string-array>
<string-array name="cpu_power_mode_values">
<item>LITE_POWER_HIGH</item>
<item>LITE_POWER_LOW</item>
<item>LITE_POWER_FULL</item>
<item>LITE_POWER_NO_BIND</item>
<item>LITE_POWER_RAND_HIGH</item>
<item>LITE_POWER_RAND_LOW</item>
</string-array>
<string-array name="input_color_format_entries">
<item>BGR color format</item>
<item>RGB color format</item>
</string-array>
<string-array name="input_color_format_values">
<item>BGR</item>
<item>RGB</item>
</string-array>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>
<resources>
<string name="app_name">人像抠图(发丝级背景替换)</string>
<!-- image matting settings -->
<string name="CHOOSE_PRE_INSTALLED_MODEL_KEY">CHOOSE_PRE_INSTALLED_MODEL_KEY</string>
<string name="ENABLE_CUSTOM_SETTINGS_KEY">ENABLE_CUSTOM_SETTINGS_KEY</string>
<string name="MODEL_PATH_KEY">MODEL_PATH_KEY</string>
<string name="LABEL_PATH_KEY">LABEL_PATH_KEY</string>
<string name="IMAGE_PATH_KEY">IMAGE_PATH_KEY</string>
<string name="BG_PATH_KEY">BG_PATH_KEY</string>
<string name="CPU_THREAD_NUM_KEY">CPU_THREAD_NUM_KEY</string>
<string name="CPU_POWER_MODE_KEY">CPU_POWER_MODE_KEY</string>
<string name="INPUT_COLOR_FORMAT_KEY">INPUT_COLOR_FORMAT_KEY</string>
<string name="INPUT_SHAPE_KEY">INPUT_SHAPE_KEY</string>
<string name="MODEL_PATH_DEFAULT">image_matting/models/modnet</string>
<string name="LABEL_PATH_DEFAULT">image_matting/labels/label_list</string>
<string name="IMAGE_PATH_DEFAULT">image_matting/images/human.jpg</string>
<string name="BG_PATH_DEFAULT">image_matting/images/bg.jpg</string>
<string name="CPU_THREAD_NUM_DEFAULT">1</string>
<string name="CPU_POWER_MODE_DEFAULT">LITE_POWER_HIGH</string>
<string name="INPUT_COLOR_FORMAT_DEFAULT">RGB</string>
<string name="INPUT_SHAPE_DEFAULT">1,3,256,256</string>
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
</style>
<style name="OverflowMenuStyle" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
<item name="overlapAnchor">false</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Model Settings">
<ListPreference
android:defaultValue="@string/MODEL_PATH_DEFAULT"
android:key="@string/CHOOSE_PRE_INSTALLED_MODEL_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Choose pre-installed models" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/ENABLE_CUSTOM_SETTINGS_KEY"
android:summaryOn="Enable"
android:summaryOff="Disable"
android:title="Enable custom settings"/>
<EditTextPreference
android:key="@string/MODEL_PATH_KEY"
android:defaultValue="@string/MODEL_PATH_DEFAULT"
android:title="Model Path" />
<EditTextPreference
android:key="@string/LABEL_PATH_KEY"
android:defaultValue="@string/LABEL_PATH_DEFAULT"
android:title="Label Path" />
<EditTextPreference
android:key="@string/IMAGE_PATH_KEY"
android:defaultValue="@string/IMAGE_PATH_DEFAULT"
android:title="Image Path" />
</PreferenceCategory>
<PreferenceCategory android:title="CPU Settings">
<ListPreference
android:defaultValue="@string/CPU_THREAD_NUM_DEFAULT"
android:key="@string/CPU_THREAD_NUM_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Thread Num"
android:entries="@array/cpu_thread_num_entries"
android:entryValues="@array/cpu_thread_num_values"/>
<ListPreference
android:defaultValue="@string/CPU_POWER_MODE_DEFAULT"
android:key="@string/CPU_POWER_MODE_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Power Mode"
android:entries="@array/cpu_power_mode_entries"
android:entryValues="@array/cpu_power_mode_values"/>
</PreferenceCategory>
<PreferenceCategory android:title="Input Settings">
<ListPreference
android:defaultValue="@string/INPUT_COLOR_FORMAT_DEFAULT"
android:key="@string/INPUT_COLOR_FORMAT_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Input Color Format: BGR or RGB"
android:entries="@array/input_color_format_entries"
android:entryValues="@array/input_color_format_values"/>
</PreferenceCategory>
</PreferenceScreen>
package com.baidu.paddle.lite.demo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.injected.testOnly=false
#Thu Aug 22 15:05:37 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
# Copyright (c) 2021 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 argparse
import codecs
import os
import sys
import cv2
import tqdm
import yaml
import numpy as np
import paddle
from paddle.inference import create_predictor, PrecisionType
from paddle.inference import Config as PredictConfig
from paddleseg.cvlibs import manager
from paddleseg.utils import get_sys_env, logger
LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(LOCAL_PATH, '..', '..'))
manager.BACKBONES._components_dict.clear()
manager.TRANSFORMS._components_dict.clear()
import ppmatting.transforms as T
from ppmatting.utils import get_image_list, mkdir, estimate_foreground_ml
def parse_args():
parser = argparse.ArgumentParser(description='Deploy for matting model')
parser.add_argument(
"--config",
dest="cfg",
help="The config file.",
default=None,
type=str,
required=True)
parser.add_argument(
'--image_path',
dest='image_path',
help='The directory or path or file list of the images to be predicted.',
type=str,
default=None,
required=True)
parser.add_argument(
'--trimap_path',
dest='trimap_path',
help='The directory or path or file list of the triamp to help predicted.',
type=str,
default=None)
parser.add_argument(
'--batch_size',
dest='batch_size',
help='Mini batch size of one gpu or cpu.',
type=int,
default=1)
parser.add_argument(
'--save_dir',
dest='save_dir',
help='The directory for saving the predict result.',
type=str,
default='./output')
parser.add_argument(
'--device',
choices=['cpu', 'gpu'],
default="gpu",
help="Select which device to inference, defaults to gpu.")
parser.add_argument(
'--fg_estimate',
default=True,
type=eval,
choices=[True, False],
help='Whether to estimate foreground when predicting.')
parser.add_argument(
'--cpu_threads',
default=10,
type=int,
help='Number of threads to predict when using cpu.')
parser.add_argument(
'--enable_mkldnn',
default=False,
type=eval,
choices=[True, False],
help='Enable to use mkldnn to speed up when using cpu.')
parser.add_argument(
'--use_trt',
default=False,
type=eval,
choices=[True, False],
help='Whether to use Nvidia TensorRT to accelerate prediction.')
parser.add_argument(
"--precision",
default="fp32",
type=str,
choices=["fp32", "fp16", "int8"],
help='The tensorrt precision.')
parser.add_argument(
'--enable_auto_tune',
default=False,
type=eval,
choices=[True, False],
help='Whether to enable tuned dynamic shape. We uses some images to collect '
'the dynamic shape for trt sub graph, which avoids setting dynamic shape manually.'
)
parser.add_argument(
'--auto_tuned_shape_file',
type=str,
default="auto_tune_tmp.pbtxt",
help='The temp file to save tuned dynamic shape.')
parser.add_argument(
"--benchmark",
type=eval,
default=False,
help="Whether to log some information about environment, model, configuration and performance."
)
parser.add_argument(
"--model_name",
default="",
type=str,
help='When `--benchmark` is True, the specified model name is displayed.'
)
parser.add_argument(
'--print_detail',
default=True,
type=eval,
choices=[True, False],
help='Print GLOG information of Paddle Inference.')
return parser.parse_args()
def use_auto_tune(args):
return hasattr(PredictConfig, "collect_shape_range_info") \
and hasattr(PredictConfig, "enable_tuned_tensorrt_dynamic_shape") \
and args.device == "gpu" and args.use_trt and args.enable_auto_tune
class DeployConfig:
def __init__(self, path):
with codecs.open(path, 'r', 'utf-8') as file:
self.dic = yaml.load(file, Loader=yaml.FullLoader)
self._transforms = self.load_transforms(self.dic['Deploy'][
'transforms'])
self._dir = os.path.dirname(path)
@property
def transforms(self):
return self._transforms
@property
def model(self):
return os.path.join(self._dir, self.dic['Deploy']['model'])
@property
def params(self):
return os.path.join(self._dir, self.dic['Deploy']['params'])
@staticmethod
def load_transforms(t_list):
com = manager.TRANSFORMS
transforms = []
for t in t_list:
ctype = t.pop('type')
transforms.append(com[ctype](**t))
return T.Compose(transforms)
def auto_tune(args, imgs, img_nums):
"""
Use images to auto tune the dynamic shape for trt sub graph.
The tuned shape saved in args.auto_tuned_shape_file.
Args:
args(dict): input args.
imgs(str, list[str]): the path for images.
img_nums(int): the nums of images used for auto tune.
Returns:
None
"""
logger.info("Auto tune the dynamic shape for GPU TRT.")
assert use_auto_tune(args)
if not isinstance(imgs, (list, tuple)):
imgs = [imgs]
num = min(len(imgs), img_nums)
cfg = DeployConfig(args.cfg)
pred_cfg = PredictConfig(cfg.model, cfg.params)
pred_cfg.enable_use_gpu(100, 0)
if not args.print_detail:
pred_cfg.disable_glog_info()
pred_cfg.collect_shape_range_info(args.auto_tuned_shape_file)
predictor = create_predictor(pred_cfg)
input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])
for i in range(0, num):
data = np.array([cfg.transforms(imgs[i])[0]])
input_handle.reshape(data.shape)
input_handle.copy_from_cpu(data)
try:
predictor.run()
except:
logger.info(
"Auto tune fail. Usually, the error is out of GPU memory, "
"because the model and image is too large. \n")
del predictor
if os.path.exists(args.auto_tuned_shape_file):
os.remove(args.auto_tuned_shape_file)
return
logger.info("Auto tune success.\n")
class Predictor:
def __init__(self, args):
"""
Prepare for prediction.
The usage and docs of paddle inference, please refer to
https://paddleinference.paddlepaddle.org.cn/product_introduction/summary.html
"""
self.args = args
self.cfg = DeployConfig(args.cfg)
self._init_base_config()
if args.device == 'cpu':
self._init_cpu_config()
else:
self._init_gpu_config()
self.predictor = create_predictor(self.pred_cfg)
if hasattr(args, 'benchmark') and args.benchmark:
import auto_log
pid = os.getpid()
gpu_id = None if args.device == 'cpu' else 0
self.autolog = auto_log.AutoLogger(
model_name=args.model_name,
model_precision=args.precision,
batch_size=args.batch_size,
data_shape="dynamic",
save_path=None,
inference_config=self.pred_cfg,
pids=pid,
process_name=None,
gpu_ids=gpu_id,
time_keys=[
'preprocess_time', 'inference_time', 'postprocess_time'
],
warmup=0,
logger=logger)
def _init_base_config(self):
self.pred_cfg = PredictConfig(self.cfg.model, self.cfg.params)
if not self.args.print_detail:
self.pred_cfg.disable_glog_info()
self.pred_cfg.enable_memory_optim()
self.pred_cfg.switch_ir_optim(True)
def _init_cpu_config(self):
"""
Init the config for x86 cpu.
"""
logger.info("Using CPU")
self.pred_cfg.disable_gpu()
if self.args.enable_mkldnn:
logger.info("Using MKLDNN")
# cache 1- different shapes for mkldnn
self.pred_cfg.set_mkldnn_cache_capacity(10)
self.pred_cfg.enable_mkldnn()
self.pred_cfg.set_cpu_math_library_num_threads(self.args.cpu_threads)
def _init_gpu_config(self):
"""
Init the config for nvidia gpu.
"""
logger.info("using GPU")
self.pred_cfg.enable_use_gpu(100, 0)
precision_map = {
"fp16": PrecisionType.Half,
"fp32": PrecisionType.Float32,
"int8": PrecisionType.Int8
}
precision_mode = precision_map[self.args.precision]
if self.args.use_trt:
logger.info("Use TRT")
self.pred_cfg.enable_tensorrt_engine(
workspace_size=1 << 30,
max_batch_size=1,
min_subgraph_size=300,
precision_mode=precision_mode,
use_static=False,
use_calib_mode=False)
if use_auto_tune(self.args) and \
os.path.exists(self.args.auto_tuned_shape_file):
logger.info("Use auto tuned dynamic shape")
allow_build_at_runtime = True
self.pred_cfg.enable_tuned_tensorrt_dynamic_shape(
self.args.auto_tuned_shape_file, allow_build_at_runtime)
else:
logger.info("Use manual set dynamic shape")
min_input_shape = {"x": [1, 3, 100, 100]}
max_input_shape = {"x": [1, 3, 2000, 3000]}
opt_input_shape = {"x": [1, 3, 512, 1024]}
self.pred_cfg.set_trt_dynamic_shape_info(
min_input_shape, max_input_shape, opt_input_shape)
def run(self, imgs, trimaps=None, imgs_dir=None):
self.imgs_dir = imgs_dir
num = len(imgs)
input_names = self.predictor.get_input_names()
input_handle = {}
for i in range(len(input_names)):
input_handle[input_names[i]] = self.predictor.get_input_handle(
input_names[i])
output_names = self.predictor.get_output_names()
output_handle = self.predictor.get_output_handle(output_names[0])
args = self.args
for i in tqdm.tqdm(range(0, num, args.batch_size)):
# warm up
if i == 0 and args.benchmark:
for _ in range(5):
img_inputs = []
if trimaps is not None:
trimap_inputs = []
trans_info = []
for j in range(i, i + args.batch_size):
img = imgs[j]
trimap = trimaps[j] if trimaps is not None else None
data = self._preprocess(img=img, trimap=trimap)
img_inputs.append(data['img'])
if trimaps is not None:
trimap_inputs.append(data['trimap'][
np.newaxis, :, :])
trans_info.append(data['trans_info'])
img_inputs = np.array(img_inputs)
if trimaps is not None:
trimap_inputs = (
np.array(trimap_inputs)).astype('float32')
input_handle['img'].copy_from_cpu(img_inputs)
if trimaps is not None:
input_handle['trimap'].copy_from_cpu(trimap_inputs)
self.predictor.run()
results = output_handle.copy_to_cpu()
results = results.squeeze(1)
for j in range(args.batch_size):
trimap = trimap_inputs[
j] if trimaps is not None else None
result = self._postprocess(
results[j], trans_info[j], trimap=trimap)
# inference
if args.benchmark:
self.autolog.times.start()
img_inputs = []
if trimaps is not None:
trimap_inputs = []
trans_info = []
for j in range(i, i + args.batch_size):
img = imgs[j]
trimap = trimaps[j] if trimaps is not None else None
data = self._preprocess(img=img, trimap=trimap)
img_inputs.append(data['img'])
if trimaps is not None:
trimap_inputs.append(data['trimap'][np.newaxis, :, :])
trans_info.append(data['trans_info'])
img_inputs = np.array(img_inputs)
if trimaps is not None:
trimap_inputs = (np.array(trimap_inputs)).astype('float32')
input_handle['img'].copy_from_cpu(img_inputs)
if trimaps is not None:
input_handle['trimap'].copy_from_cpu(trimap_inputs)
if args.benchmark:
self.autolog.times.stamp()
self.predictor.run()
results = output_handle.copy_to_cpu()
if args.benchmark:
self.autolog.times.stamp()
results = results.squeeze(1)
for j in range(args.batch_size):
trimap = trimap_inputs[j] if trimaps is not None else None
result = self._postprocess(
results[j], trans_info[j], trimap=trimap)
self._save_imgs(result, imgs[i + j])
if args.benchmark:
self.autolog.times.end(stamp=True)
logger.info("Finish")
def _preprocess(self, img, trimap=None):
data = {}
data['img'] = img
if trimap is not None:
data['trimap'] = trimap
data['gt_fields'] = ['trimap']
data = self.cfg.transforms(data)
return data
def _postprocess(self, alpha, trans_info, trimap=None):
"""recover pred to origin shape"""
if trimap is not None:
trimap = trimap.squeeze(0)
alpha[trimap == 0] = 0
alpha[trimap == 255] = 1
for item in trans_info[::-1]:
if item[0] == 'resize':
h, w = item[1][0], item[1][1]
alpha = cv2.resize(
alpha, (w, h), interpolation=cv2.INTER_LINEAR)
elif item[0] == 'padding':
h, w = item[1][0], item[1][1]
alpha = alpha[0:h, 0:w]
else:
raise Exception("Unexpected info '{}' in im_info".format(item[
0]))
return alpha
def _save_imgs(self, alpha, img_path):
ori_img = cv2.imread(img_path)
alpha = (alpha * 255).astype('uint8')
if self.imgs_dir is not None:
img_path = img_path.replace(self.imgs_dir, '')
else:
img_path = os.path.basename(img_path)
name, ext = os.path.splitext(img_path)
if name[0] == '/' or name[0] == '\\':
name = name[1:]
alpha_save_path = os.path.join(args.save_dir, name + '_alpha.png')
rgba_save_path = os.path.join(args.save_dir, name + '_rgba.png')
# save alpha
mkdir(alpha_save_path)
cv2.imwrite(alpha_save_path, alpha)
# save rgba image
mkdir(rgba_save_path)
if args.fg_estimate:
fg = estimate_foreground_ml(ori_img / 255.0, alpha / 255.0) * 255
else:
fg = ori_img
fg = fg.astype('uint8')
alpha = alpha[:, :, np.newaxis]
rgba = np.concatenate([fg, alpha], axis=-1)
cv2.imwrite(rgba_save_path, rgba)
def main(args):
imgs_list, imgs_dir = get_image_list(args.image_path)
if args.trimap_path is None:
trimaps_list = None
else:
trimaps_list, _ = get_image_list(args.trimap_path)
if use_auto_tune(args):
tune_img_nums = 10
auto_tune(args, imgs_list, tune_img_nums)
predictor = Predictor(args)
predictor.run(imgs=imgs_list, trimaps=trimaps_list, imgs_dir=imgs_dir)
if use_auto_tune(args) and \
os.path.exists(args.auto_tuned_shape_file):
os.remove(args.auto_tuned_shape_file)
if args.benchmark:
predictor.autolog.report()
if __name__ == '__main__':
args = parse_args()
main(args)
# 数据准备
当需要对自定义的数据集进行训练的时候,需要按照相应的格式进行准备。我们提供了两种数据形式,一种为离线合成,一种为在线合成。
## 离线合成
如果图像已经实现离线合成或者不需要合成,需按照如下模型整理数据结构。
```
dataset_root/
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha/
|
|--train.txt
|
|--val.txt
```
其中,fg目录下存放原图,另外fg目录下的图象名称需和alpha目录下的名称一一对应, 且两者的分辨率需保持一致。
train.txt和val.txt的内容如下
```
train/fg/14299313536_ea3e61076c_o.jpg
train/fg/14429083354_23c8fddff5_o.jpg
train/fg/14559969490_d33552a324_o.jpg
...
```
## 在线合成
数据读取支持在线合成,即输入网络的原图通过已有的前景图、alpha和背景图进行在线合成。类似[Deep Image Matting](https://arxiv.org/pdf/1703.03872.pdf)论文里使用的数据集Composition-1k,则数据集应整理成如下结构:
```
Composition-1k/
|--bg/
|
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha/
| |--trimap/ (如果存在)
|
|--train.txt
|
|--val.txt
```
其中,fg目录存放前景图片,bg存放背景图片。
train.txt的内容如下:
```
train/fg/fg1.jpg bg/bg1.jpg
train/fg/fg2.jpg bg/bg2.jpg
train/fg/fg3.jpg bg/bg3.jpg
...
```
其中第一列为前景图像,第二列为背景图。
val.txt的内容如下, 如果不存在对应的trimap,则第三列可不提供,代码将会自动生成。
```
val/fg/fg1.jpg bg/bg1.jpg val/trimap/trimap1.jpg
val/fg/fg2.jpg bg/bg2.jpg val/trimap/trimap2.jpg
val/fg/fg3.jpg bg/bg3.jpg val/trimap/trimap3.jpg
...
```
# Dataset Preparation
When training for custom dataset, you need to prepare dataset in the appropriate format.
We provide two forms of dataset, one for offline composition and one for online composition.
## Offline composition
If the images have been composited offline or do not need to be composited, the dataset should be organized as follows.
```
dataset_root/
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha/
|
|--train.txt
|
|--val.txt
```
where, fg folder stores the original images. The image name in the fg folder must correspond to that in the alpha folder one by one,
and the resolution must be the same for the correspond image in the two folders.
train.txt and val.txt contents are as follows.
```
train/fg/14299313536_ea3e61076c_o.jpg
train/fg/14429083354_23c8fddff5_o.jpg
train/fg/14559969490_d33552a324_o.jpg
...
```
## Online composition
Data reading support online composition, that is, the image input network composited online by the foreground, alpha, and background images,
which like the Composition-1k dataset used in [Deep Image Matting](https://arxiv.org/pdf/1703.03872.pdf) .
The dataset should be organized as follows:
```
Composition-1k/
|--bg/
|
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha/
| |--trimap/ (如果存在)
|
|--train.txt
|
|--val.txt
```
where, the fg folder stores the foreground images and the bg folder stores the background images.
The contents of train.txt is as follows:
```
train/fg/fg1.jpg bg/bg1.jpg
train/fg/fg2.jpg bg/bg2.jpg
train/fg/fg3.jpg bg/bg3.jpg
...
```
where, the first column is the foreground images and the second column is the background images.
The contents of val.txt are as follows. If trimap does not exist in dataset, the third column is not needed and the code will generate trimap automatically.
```
val/fg/fg1.jpg bg/bg1.jpg val/trimap/trimap1.jpg
val/fg/fg2.jpg bg/bg2.jpg val/trimap/trimap2.jpg
val/fg/fg3.jpg bg/bg3.jpg val/trimap/trimap3.jpg
...
```
# 全流程开发
## 目录
* [环境配置](#环境配置)
* [数据集准备](#数据集准备)
* [模型选择](#模型选择)
* [训练](#训练)
* [评估](#评估)
* [预测](#预测)
* [背景替换](#背景替换)
* [导出部署](#导出部署)
## 环境配置
#### 1. 安装PaddlePaddle
版本要求
* PaddlePaddle >= 2.0.2
* Python >= 3.7+
由于图像抠图模型计算开销大,推荐在GPU版本的PaddlePaddle下使用。
推荐安装10.0以上的CUDA环境。安装教程请见[PaddlePaddle官网](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/linux-pip.html)
#### 2. 下载PaddleSeg仓库
```shell
git clone https://github.com/PaddlePaddle/PaddleSeg
```
#### 3. 安装
```shell
cd PaddleSeg/Matting
pip install -r requirements.txt
```
## 数据集准备
利用MODNet开源的[PPM-100](https://github.com/ZHKKKe/PPM)数据集作为我们教程的示例数据集。自定已数据集请参考[数据集准备](data_prepare_cn.md)
下载已经准备好的PPM-100数据集:
```shell
mkdir data && cd data
wget https://paddleseg.bj.bcebos.com/matting/datasets/PPM-100.zip
unzip PPM-100.zip
cd ..
```
数据集结构目录如下:
```
PPM-100/
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha
|
|--train.txt
|
|--val.txt
```
**注意** : 该数据集仅仅作为教程演示,无法利用其训练得到一个收敛的模型。
## 模型选择
Matting项目支持配置化直接驱动,模型配置文件均放置于[configs](../configs/)目录下,大家可根据实际情况选择相应的配置文件进行训练、预测等流程。
该教程中使用[configs/quick_start/ppmattingv2-stdc1-human_512.yml](../configs/quick_start/ppmattingv2-stdc1-human_512.yml)模型配置文件进行教学演示。
## 训练
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/train.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--do_eval \
--use_vdl \
--save_interval 500 \
--num_workers 5 \
--save_dir output
```
**note:** 使用--do_eval会影响训练速度及增加显存消耗,根据需求进行开闭。
打开的时候会根据SAD保存历史最佳模型到`{save_dir}/best_model`下面,同时会在该目录下生成`best_sad.txt`记录下此时各个指标信息及iter.
`--num_workers` 多进程数据读取,加快数据预处理速度
更多参数信息请运行如下命令进行查看:
```shell
python tools/train.py --help
```
如需使用多卡,请用`python -m paddle.distributed.launch`进行启动
## 评估
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/val.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--save_dir ./output/results \
--save_results
```
`--save_result` 开启会保留图片的预测结果,可选择关闭以加快评估速度。
你可以直接下载我们提供的模型进行评估。
更多参数信息请运行如下命令进行查看:
```shell
python tools/val.py --help
```
## 预测
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/predict.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--image_path data/PPM-100/val/fg/ \
--save_dir ./output/results \
--fg_estimate True
```
如模型需要trimap信息,需要通过`--trimap_path`传入trimap路径。
`--fg_estimate False` 可关闭前景估计功能,可提升预测速度,但图像质量会有所降低
你可以直接下载我们提供的模型进行预测。
更多参数信息请运行如下命令进行查看:
```shell
python tools/predict.py --help
```
## 背景替换
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/bg_replace.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--image_path path/to/your/image \
--background path/to/your/background/image \
--save_dir ./output/results \
--fg_estimate True
```
如模型需要trimap信息,需要通过`--trimap_path`传入trimap路径。
`--background`可以传入背景图片路劲,或选择('r','g','b','w')中的一种,代表红,绿,蓝,白背景, 若不提供则采用绿色作为背景。
`--fg_estimate False` 可关闭前景估计功能,可提升预测速度,但图像质量会有所降低
**注意:** `--image_path`必须是一张图片的具体路径。
你可以直接下载我们提供的模型进行背景替换。
更多参数信息请运行如下命令进行查看:
```shell
python tools/bg_replace.py --help
```
## 导出部署
### 模型导出
```shell
python tools/export.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--save_dir output/export \
--input_shape 1 3 512 512
```
如果模型(比如:DIM)需要trimap的输入,需要增加参数`--trimap`
更多参数信息请运行如下命令进行查看:
```shell
python tools/export.py --help
```
### 应用部署
```shell
python deploy/python/infer.py \
--config output/export/deploy.yaml \
--image_path data/PPM-100/val/fg/ \
--save_dir output/results \
--fg_estimate True
```
如模型需要trimap信息,需要通过`--trimap_path`传入trimap路径。
`--fg_estimate False` 可关闭前景估计功能,可提升预测速度,但图像质量会有所降低
更多参数信息请运行如下命令进行查看:
```shell
python deploy/python/infer.py --help
```
# Full Development
## Contents
* [Installation](#Installation)
* [Dataset preparation](#Dataset-preparation)
* [Model selection](#Model-selection)
* [Training](#Training)
* [Evaluation](#Evaluation)
* [Prediction](#Prediction)
* [Background Replacement](#Background-Replacement)
* [Export and Deployment](#Export-and-Deployment)
## Installation
#### 1. Install PaddlePaddle
Versions
* PaddlePaddle >= 2.0.2
* Python >= 3.7+
Due to the high computational cost of model, PaddleSeg is recommended for GPU version PaddlePaddle.
CUDA 10.0 or later is recommended. See [PaddlePaddle official website](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/linux-pip.html) for the installation tutorial.
#### 2. Download the PaddleSeg repository
```shell
git clone https://github.com/PaddlePaddle/PaddleSeg
```
#### 3. Installation
```shell
cd PaddleSeg/Matting
pip install -r requirements.txt
```
## Dataset preparation
Using MODNet's open source [PPM-100](https://github.com/ZHKKKe/PPM) dataset as our demo dataset for the tutorial.
Custom dataset refer to [dataset preparation](data_prepare_en.md).
Download the prepared PPM-100 dataset.
```shell
mkdir data && cd data
wget https://paddleseg.bj.bcebos.com/matting/datasets/PPM-100.zip
unzip PPM-100.zip
cd ..
```
The dataset structure is as follows.
```
PPM-100/
|--train/
| |--fg/
| |--alpha/
|
|--val/
| |--fg/
| |--alpha
|
|--train.txt
|
|--val.txt
```
**Note** : This dataset is only used as a tutorial demonstration and cannot be trained to produce a convergent model.
## Model selection
The Matting project supports configurable direct drive, with model config files placed in [configs](../configs/) directory.
You can select a config file based on the actual situation to perform training, prediction et al.
This tutorial uses [configs/quick_start/ppmattingv2-stdc1-human_512.yml](../configs/quick_start/ppmattingv2-stdc1-human_512.yml) for teaching demonstrations.
## Training
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/train.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--do_eval \
--use_vdl \
--save_interval 500 \
--num_workers 5 \
--save_dir output
```
Using `--do_eval` will affect training speed and increase memory consumption, turning on and off according to needs.
If opening the `--do_eval`, the historical best model will be saved to '{save_dir}/best_model' according to SAD. At the same time, 'best_sad.txt' will be generated in this directory to record the information of metrics and iter at this time.
`--num_workers` Read data in multi-process mode. Speed up data preprocessing.
Run the following command to view more parameters.
```shell
python tools/train.py --help
```
If you want to use multiple GPUs,please use `python -m paddle.distributed.launch` to run.
## Evaluation
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/val.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--save_dir ./output/results \
--save_results
```
`--save_result` The prediction results will be saved if turn on. If it is off, it will speed up the evaluation.
You can directly download the provided model for evaluation.
Run the following command to view more parameters.
```shell
python tools/val.py --help
```
## Prediction
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/predict.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--image_path data/PPM-100/val/fg/ \
--save_dir ./output/results \
--fg_estimate True
```
If the model requires trimap information, pass the trimap path through '--trimap_path'.
`--fg_estimate False` can turn off foreground estimation, which improves prediction speed but reduces image quality.
You can directly download the provided model for evaluation.
Run the following command to view more parameters.
```shell
python tools/predict.py --help
```
## Background Replacement
```shell
export CUDA_VISIBLE_DEVICES=0
python tools/bg_replace.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--image_path path/to/your/image \
--background path/to/your/background/image \
--save_dir ./output/results \
--fg_estimate True
```
If the model requires trimap information, pass the trimap path through `--trimap_path`.
`--background` can pass a path of brackground image or select one of ('r', 'g', 'b', 'w') which represent red, green, blue and white. If it is not specified, a green background is used.
`--fg_Estimate False` can turn off foreground estimation, which improves prediction speed but reduces image quality.
**note:** `--image_path` must be a image path。
You can directly download the provided model for background replacement.
Run the following command to view more parameters.
```shell
python tools/bg_replace.py --help
```
## Export and Deployment
### Model Export
```shell
python tools/export.py \
--config configs/quick_start/ppmattingv2-stdc1-human_512.yml \
--model_path output/best_model/model.pdparams \
--save_dir output/export \
--input_shape 1 3 512 512
```
If the model requires trimap information such as DIM, `--trimap` is need.
Run the following command to view more parameters.
```shell
python tools/export.py --help
```
### Deployment
```shell
python deploy/python/infer.py \
--config output/export/deploy.yaml \
--image_path data/PPM-100/val/fg/ \
--save_dir output/results \
--fg_estimate True
```
If the model requires trimap information, pass the trimap path through '--trimap_path'.
`--fg_Estimate False` can turn off foreground estimation, which improves prediction speed but reduces image quality.
Run the following command to view more parameters.
```shell
python deploy/python/infer.py --help
```
# 在线体验
欢迎使用外部开发者基于PP-Matting模型开发的在线抠图应用,“[懒人抠图](https://coolseg.cn)"。除了抠图以外,该网站进一步提供了背景替换,证件照制作等功能。
<p align="center">
<img src="https://user-images.githubusercontent.com/48433081/165077834-c3191509-aeaf-45c8-b226-656174f4c152.gif" width="70%" height="70%">
</p>
**注意**:网站由外部开发者自行开发和维护,可能存在不稳定的问题。推荐大家基于代码[快速体验](./quick_start_cn.md)
# Online experience
Welcome to the online image matting application developed by community developers based on PP-Matting model "[Non-Code Matting](https://coolseg.cn/)".
In addition to matting, the website further provides background replacement, ID photo production et al.
<p align="center">
<img src="https://user-images.githubusercontent.com/48433081/165077834-c3191509-aeaf-45c8-b226-656174f4c152.gif" width="70%" height="70%">
</p>
**Note**: The website is developed and maintained by community developers and may be unstable. It is recommended that you based on [quick start](./quick_start_en.md).
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment