Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
changxl.
paddlehub
提交
25a9268c
P
paddlehub
项目概览
changxl.
/
paddlehub
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
paddlehub
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
25a9268c
编写于
11月 16, 2020
作者:
jm_12138
提交者:
GitHub
11月 16, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add the AnimeGAN modules
上级
54364d4e
变更
36
隐藏空白更改
内联
并排
Showing
36 changed file
with
3591 addition
and
0 deletion
+3591
-0
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/README.md
...dules/image/style_transfer/animegan_v1_hayao_60/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/model.py
...odules/image/style_transfer/animegan_v1_hayao_60/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/module.py
...dules/image/style_transfer/animegan_v1_hayao_60/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/processor.py
...es/image/style_transfer/animegan_v1_hayao_60/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/README.md
...dules/image/style_transfer/animegan_v2_hayao_64/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/model.py
...odules/image/style_transfer/animegan_v2_hayao_64/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/module.py
...dules/image/style_transfer/animegan_v2_hayao_64/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/processor.py
...es/image/style_transfer/animegan_v2_hayao_64/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/README.md
...dules/image/style_transfer/animegan_v2_hayao_99/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/model.py
...odules/image/style_transfer/animegan_v2_hayao_99/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/module.py
...dules/image/style_transfer/animegan_v2_hayao_99/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/processor.py
...es/image/style_transfer/animegan_v2_hayao_99/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/README.md
...les/image/style_transfer/animegan_v2_paprika_54/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/model.py
...ules/image/style_transfer/animegan_v2_paprika_54/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/module.py
...les/image/style_transfer/animegan_v2_paprika_54/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/processor.py
.../image/style_transfer/animegan_v2_paprika_54/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/README.md
...les/image/style_transfer/animegan_v2_paprika_74/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/model.py
...ules/image/style_transfer/animegan_v2_paprika_74/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/module.py
...les/image/style_transfer/animegan_v2_paprika_74/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/processor.py
.../image/style_transfer/animegan_v2_paprika_74/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/README.md
...les/image/style_transfer/animegan_v2_paprika_97/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/model.py
...ules/image/style_transfer/animegan_v2_paprika_97/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/module.py
...les/image/style_transfer/animegan_v2_paprika_97/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/processor.py
.../image/style_transfer/animegan_v2_paprika_97/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/README.md
...les/image/style_transfer/animegan_v2_paprika_98/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/model.py
...ules/image/style_transfer/animegan_v2_paprika_98/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/module.py
...les/image/style_transfer/animegan_v2_paprika_98/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/processor.py
.../image/style_transfer/animegan_v2_paprika_98/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/README.md
...les/image/style_transfer/animegan_v2_shinkai_33/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/model.py
...ules/image/style_transfer/animegan_v2_shinkai_33/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/module.py
...les/image/style_transfer/animegan_v2_shinkai_33/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/processor.py
.../image/style_transfer/animegan_v2_shinkai_33/processor.py
+133
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/README.md
...les/image/style_transfer/animegan_v2_shinkai_53/README.md
+127
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/model.py
...ules/image/style_transfer/animegan_v2_shinkai_53/model.py
+67
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/module.py
...les/image/style_transfer/animegan_v2_shinkai_53/module.py
+72
-0
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/processor.py
.../image/style_transfer/animegan_v2_shinkai_53/processor.py
+133
-0
未找到文件。
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V1 图像风格转换模型
模型可将输入的图像转换成Hayao风格
模型权重转换自AnimeGAN V1官方开源项目
模型所使用的权重为Hayao-60.ckpt
模型详情请参考
[
AnimeGAN V1 开源项目
](
https://github.com/TachibanaYoshino/AnimeGAN
)
## 模型安装
```
shell
$hub
install
animegan_v1_hayao_60
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/10175bb964e94ce18608a84b0ab6ebfe154b523df42f44a3a851b2d91dd17a63
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v1_hayao_60'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v1_hayao_60
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v1_hayao_60"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGAN
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v1_hayao_60.model
import
Model
from
animegan_v1_hayao_60.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v1_hayao_60"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v1_hayao_60"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V1_Hayao_60
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v1_hayao_60"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v1_hayao_60/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Hayao风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Hayao-64.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_hayao_64
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/49620341f1fe4f00af4d93c22694897a1ae578a235844a1db1bbb4bd37bf750b
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_hayao_64'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_hayao_64
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_hayao_64"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_hayao_64.model
import
Model
from
animegan_v2_hayao_64.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_hayao_64"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_hayao_64"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Hayao_64
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_hayao_64"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_hayao_64/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Hayao风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Hayao-99.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_hayao_99
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/16195e03d7e0412d990349587c587a26d9ae9e2ed1ec4fa1b4dc994e948d1f7d
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_hayao_99'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_hayao_99
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_hayao_99"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_hayao_99.model
import
Model
from
animegan_v2_hayao_99.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_hayao_99"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_hayao_99"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Hayao_99
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_hayao_99"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_hayao_99/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Paprika风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Paprika-54.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_paprika_54
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/08ee95c94e0b4d4e8b2855a6ed40af5853b40c0047b3421aaa2f7c877fac5130
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_paprika_54'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_paprika_54
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_paprika_54"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_paprika_54.model
import
Model
from
animegan_v2_paprika_54.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_paprika_54"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_paprika_54"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Paprika_54
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_paprika_54"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_paprika_54/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Paprika风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Paprika-74.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_paprika_74
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/6574669d87b24bab9627c6e33896528b4a0bf5af1cd84ca29655d68719f2d551
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_paprika_74'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_paprika_74
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_paprika_74"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_paprika_74.model
import
Model
from
animegan_v2_paprika_74.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_paprika_74"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_paprika_74"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Paprika_74
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_paprika_74"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_paprika_74/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Paprika风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Paprika-97.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_paprika_97
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/3b962a18a22e43028cc5530db1c5adb1a42e6aae4bb74b8598ee30ed52b59c8b
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_paprika_97'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_paprika_97
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_paprika_97"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_paprika_97.model
import
Model
from
animegan_v2_paprika_97.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_paprika_97"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_paprika_97"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Paprika_97
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_paprika_97"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_paprika_97/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Paprika风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Paprika-98.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_paprika_98
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/495436a627ef423ab572536c5f2ba6d0eb99b1ce098947a5ac02af36e7eb85f7
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_paprika_98'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_paprika_98
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_paprika_98"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_paprika_98.model
import
Model
from
animegan_v2_paprika_98.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_paprika_98"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_paprika_98"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Paprika_98
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_paprika_98"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_paprika_98/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Shinkai风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Shinkai-33.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_shinkai_33
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/776a84a0d97c452bbbe479592fbb8f5c6fe9c45f3b7e41fd8b7da80bf52ee668
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_shinkai_33'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_shinkai_33
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_shinkai_33"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_shinkai_33.model
import
Model
from
animegan_v2_shinkai_33.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_shinkai_33"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_shinkai_33"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Shinkai_33
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_shinkai_33"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_shinkai_33/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/README.md
0 → 100644
浏览文件 @
25a9268c
## 模型概述
AnimeGAN V2 图像风格转换模型
模型可将输入的图像转换成Shinkai风格
模型权重转换自AnimeGAN V2官方开源项目
模型所使用的权重为Shinkai-53.ckpt
模型详情请参考
[
AnimeGAN V2 开源项目
](
https://github.com/TachibanaYoshino/AnimeGANv2
)
## 模型安装
```
shell
$hub
install
animegan_v2_shinkai_53
```
## API 说明
```
python
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
)
```
风格转换API,将输入的图片转换为漫画风格。
转换效果图如下:
![
输入图像
](
https://ai-studio-static-online.cdn.bcebos.com/bd002c4bb6a7427daf26988770bb18648b7d8d2bfd6746bfb9a429db4867727f
)
![
输出图像
](
https://ai-studio-static-online.cdn.bcebos.com/fa4ba157e73c48658c4c9c6b8b92f5c99231d1d19556472788b1e5dd58d5d6cc
)
**参数**
*
images (list
\[
numpy.ndarray
\]
): 图片数据,ndarray.shape 为
\[
H, W, C
\]
,默认为 None;
*
paths (list
\[
str
\]
): 图片的路径,默认为 None;
*
batch
\_
size (int): batch 的大小,默认设为 1;
*
visualization (bool): 是否将识别结果保存为图片文件,默认设为 False;
*
output
\_
dir (str): 图片的保存路径,默认设为 output;
*
min
\_
size (int): 输入图片的短边最小尺寸,默认设为 32;
*
max
\_
size (int): 输入图片的短边最大尺寸,默认设为 1024。
**返回**
*
res (list
\[
numpy.ndarray
\]
): 输出图像数据,ndarray.shape 为
\[
H, W, C
\]
。
## 预测代码示例
```
python
import
cv2
import
paddlehub
as
hub
# 模型加载
# use_gpu:是否使用GPU进行预测
model
=
hub
.
Module
(
'animegan_v2_shinkai_53'
,
use_gpu
=
False
)
# 模型预测
result
=
model
.
style_transfer
(
images
=
[
cv2
.
imread
(
'/PATH/TO/IMAGE'
)])
# or
# result = model.style_transfer(paths=['/PATH/TO/IMAGE'])
```
## 服务部署
PaddleHub Serving可以部署一个在线图像风格转换服务。
## 第一步:启动PaddleHub Serving
运行启动命令:
```
shell
$
hub serving start
-m
animegan_v2_shinkai_53
```
这样就完成了一个图像风格转换的在线服务API的部署,默认端口号为8866。
**NOTE:**
如使用GPU预测,则需要在启动服务之前,请设置CUDA
\_
VISIBLE
\_
DEVICES环境变量,否则不用设置。
## 第二步:发送预测请求
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
```
python
import
requests
import
json
import
cv2
import
base64
def
cv2_to_base64
(
image
):
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
# 发送HTTP请求
data
=
{
'images'
:[
cv2_to_base64
(
cv2
.
imread
(
"/PATH/TO/IMAGE"
))]}
headers
=
{
"Content-type"
:
"application/json"
}
url
=
"http://127.0.0.1:8866/predict/animegan_v2_shinkai_53"
r
=
requests
.
post
(
url
=
url
,
headers
=
headers
,
data
=
json
.
dumps
(
data
))
# 打印预测结果
print
(
r
.
json
()[
"results"
])
```
## 模型相关信息
### 模型代码
https://github.com/TachibanaYoshino/AnimeGANv2
### 依赖
paddlepaddle >= 1.8.0
paddlehub >= 1.8.0
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/model.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
numpy
as
np
from
paddle.fluid.core
import
AnalysisConfig
,
create_paddle_predictor
__all__
=
[
'Model'
]
class
Model
():
# 初始化函数
def
__init__
(
self
,
modelpath
,
use_gpu
):
# 加载模型预测器
self
.
predictor
=
self
.
load_model
(
modelpath
,
use_gpu
)
# 获取模型的输入输出
self
.
input_names
=
self
.
predictor
.
get_input_names
()
self
.
output_names
=
self
.
predictor
.
get_output_names
()
self
.
input_tensor
=
self
.
predictor
.
get_input_tensor
(
self
.
input_names
[
0
])
self
.
output_tensor
=
self
.
predictor
.
get_output_tensor
(
self
.
output_names
[
0
])
# 模型加载函数
def
load_model
(
self
,
modelpath
,
use_gpu
):
# 对运行位置进行配置
if
use_gpu
:
try
:
places
=
os
.
environ
[
"CUDA_VISIBLE_DEVICES"
]
places
=
int
(
places
[
0
])
except
Exception
as
e
:
print
(
'Error: %s. Please set the environment variables "CUDA_VISIBLE_DEVICES".'
%
e
)
use_gpu
=
False
# 加载模型参数
config
=
AnalysisConfig
(
modelpath
)
# 设置参数
if
use_gpu
:
config
.
enable_use_gpu
(
100
,
places
)
else
:
config
.
disable_gpu
()
config
.
enable_mkldnn
()
config
.
disable_glog_info
()
config
.
switch_ir_optim
(
True
)
config
.
enable_memory_optim
()
config
.
switch_use_feed_fetch_ops
(
False
)
config
.
switch_specify_input_names
(
True
)
# 通过参数加载模型预测器
predictor
=
create_paddle_predictor
(
config
)
# 返回预测器
return
predictor
# 模型预测函数
def
predict
(
self
,
input_datas
):
outputs
=
[]
# 遍历输入数据进行预测
for
input_data
in
input_datas
:
self
.
input_tensor
.
copy_from_cpu
(
input_data
)
self
.
predictor
.
zero_copy_run
()
output
=
self
.
output_tensor
.
copy_to_cpu
()
outputs
.
append
(
output
)
# 预测结果合并
outputs
=
np
.
concatenate
(
outputs
,
0
)
# 返回预测结果
return
outputs
\ No newline at end of file
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/module.py
0 → 100644
浏览文件 @
25a9268c
import
os
from
paddlehub
import
Module
from
paddlehub.module.module
import
moduleinfo
,
serving
from
animegan_v2_shinkai_53.model
import
Model
from
animegan_v2_shinkai_53.processor
import
base64_to_cv2
,
cv2_to_base64
,
Processor
@
moduleinfo
(
name
=
"animegan_v2_shinkai_53"
,
# 模型名称
type
=
"CV/style_transfer"
,
# 模型类型
author
=
"jm12138"
,
# 作者名称
author_email
=
"jm12138@qq.com"
,
# 作者邮箱
summary
=
"animegan_v2_shinkai_53"
,
# 模型介绍
version
=
"1.0.0"
# 版本号
)
class
Animegan_V2_Shinkai_53
(
Module
):
# 初始化函数
def
_initialize
(
self
,
use_gpu
=
False
):
# 设置模型路径
self
.
model_path
=
os
.
path
.
join
(
self
.
directory
,
"animegan_v2_shinkai_53"
)
# 加载模型
self
.
model
=
Model
(
self
.
model_path
,
use_gpu
)
# 关键点检测函数
def
style_transfer
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
visualization
=
False
,
min_size
=
32
,
max_size
=
1024
):
# 加载数据处理器
processor
=
Processor
(
images
,
paths
,
batch_size
,
output_dir
,
min_size
,
max_size
)
# 模型预测
outputs
=
self
.
model
.
predict
(
processor
.
input_datas
)
# 结果后处理
results
=
processor
.
postprocess
(
outputs
,
visualization
)
# 返回结果
return
results
# Hub Serving
@
serving
def
serving_method
(
self
,
images
,
**
kwargs
):
# 获取输入数据
images_decode
=
[
base64_to_cv2
(
image
)
for
image
in
images
]
# 图片风格转换
results
=
self
.
style_transfer
(
images_decode
,
**
kwargs
)
# 对输出图片进行编码
encodes
=
[]
for
result
in
results
:
encode
=
cv2_to_base64
(
result
)
encodes
.
append
(
encode
)
# 返回结果
return
encodes
hub_module/modules/image/style_transfer/animegan_v2_shinkai_53/processor.py
0 → 100644
浏览文件 @
25a9268c
import
os
import
cv2
import
time
import
base64
import
numpy
as
np
__all__
=
[
'base64_to_cv2'
,
'cv2_to_base64'
,
'Processor'
]
def
check_dir
(
dir_path
):
# 目录检查函数
if
not
os
.
path
.
exists
(
dir_path
):
os
.
makedirs
(
dir_path
)
elif
os
.
path
.
isfile
(
dir_path
):
os
.
remove
(
dir_path
)
os
.
makedirs
(
dir_path
)
def
base64_to_cv2
(
b64str
):
# base64转cv2函数
data
=
base64
.
b64decode
(
b64str
.
encode
(
'utf8'
))
data
=
np
.
frombuffer
(
data
,
np
.
uint8
)
data
=
cv2
.
imdecode
(
data
,
cv2
.
IMREAD_COLOR
)
return
data
def
cv2_to_base64
(
image
):
# cv2转base64函数
data
=
cv2
.
imencode
(
'.jpg'
,
image
)[
1
]
return
base64
.
b64encode
(
data
.
tostring
()).
decode
(
'utf8'
)
class
Processor
():
# 初始化函数
def
__init__
(
self
,
images
=
None
,
paths
=
None
,
batch_size
=
1
,
output_dir
=
'output'
,
min_size
=
32
,
max_size
=
1024
):
# 变量设置
self
.
min_size
=
min_size
self
.
max_size
=
max_size
self
.
images
=
images
self
.
paths
=
paths
self
.
batch_size
=
batch_size
self
.
output_dir
=
output_dir
# 获取原始输入数据
self
.
datas
=
self
.
load_datas
()
# 对原始输入数据进行预处理
self
.
input_datas
=
self
.
preprocess
()
# 读取数据函数
def
load_datas
(
self
):
datas
=
[]
# 读取数据列表
if
self
.
paths
is
not
None
:
for
im_path
in
self
.
paths
:
assert
os
.
path
.
isfile
(
im_path
),
"The {} isn't a valid file path."
.
format
(
im_path
)
im
=
cv2
.
imread
(
im_path
)
datas
.
append
(
im
)
if
self
.
images
is
not
None
:
datas
=
self
.
images
# 返回数据列表
return
datas
# 数据预处理函数
def
preprocess
(
self
):
input_datas
=
[]
# 数据预处理
for
i
,
img
in
enumerate
(
self
.
datas
):
# 格式转换
img
=
cv2
.
cvtColor
(
img
,
cv2
.
COLOR_BGR2RGB
)
# 缩放图片
h
,
w
=
img
.
shape
[:
2
]
if
max
(
h
,
w
)
>
self
.
max_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
max_size
,
int
(
h
/
w
*
self
.
max_size
)))
if
h
<
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
max_size
),
self
.
max_size
))
elif
min
(
h
,
w
)
<
self
.
min_size
:
img
=
cv2
.
resize
(
img
,
(
self
.
min_size
,
int
(
h
/
w
*
self
.
min_size
)))
if
h
>
w
else
cv2
.
resize
(
img
,
(
int
(
w
/
h
*
self
.
min_size
),
self
.
min_size
))
# 裁剪图片
h
,
w
=
img
.
shape
[:
2
]
img
=
img
[:
h
-
(
h
%
32
),
:
w
-
(
w
%
32
),
:]
# 归一化
img
=
img
/
127.5
-
1.0
# 新建维度
img
=
np
.
expand_dims
(
img
,
axis
=
0
).
astype
(
'float32'
)
# 加入输入数据列表
input_datas
.
append
(
img
)
# 数据按batch_size切分
input_datas
=
np
.
concatenate
(
input_datas
,
0
)
split_num
=
len
(
self
.
datas
)
//
self
.
batch_size
+
1
if
len
(
self
.
datas
)
%
self
.
batch_size
!=
0
else
len
(
self
.
datas
)
//
self
.
batch_size
input_datas
=
np
.
array_split
(
input_datas
,
split_num
)
# 返回预处理完成的数据
return
input_datas
def
postprocess
(
self
,
outputs
,
visualization
):
results
=
[]
for
im_id
,
output
in
enumerate
(
outputs
):
# 反归一化
image
=
(
output
.
squeeze
()
+
1.
)
/
2
*
255
# 限幅
image
=
np
.
clip
(
image
,
0
,
255
).
astype
(
np
.
uint8
)
# 格式转换
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 可视化
if
visualization
:
# 检查输出目录
check_dir
(
self
.
output_dir
)
# 写入输出图片
cv2
.
imwrite
(
os
.
path
.
join
(
self
.
output_dir
,
'%d_%d.jpg'
%
(
im_id
,
time
.
time
())),
image
)
results
.
append
(
image
)
# 返回结果
return
results
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录