未验证 提交 25a9268c 编写于 作者: jm_12138's avatar jm_12138 提交者: GitHub

Add the AnimeGAN modules

上级 54364d4e
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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
## 模型概述
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
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
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
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.
先完成此消息的编辑!
想要评论请 注册