文章目录
1 引言
在当今人工智能快速发展的时代,图像处理和风格化技术正在广泛应用于各类场景,从个人头像美化到社交媒体内容创作,AI技术赋予了图像全新的表达方式。基于此,华为云推出了FunctionGraph与ModelArts相结合的智能动漫化头像处理方案。FunctionGraph作为无服务器计算服务,提供了灵活的编程环境,而ModelArts则为AI模型的训练、部署和管理提供了强大支持。通过将这两者结合,开发者无需关注底层资源配置,仅需编写简单的代码即可实现头像的动漫化风格转换。这项技术不仅操作简便,还具有广泛的应用前景,为内容创作者、社交媒体用户和开发者提供了高效的AI解决方案。
2 背景介绍
2.1 华为云FunctionGraph与ModelArts简介
大体实验步骤说明:
① 安装FunctionGraph插件;
② 创建函数;
③ 部署函数;
④ 函数配置委托;
⑤ 函数配置触发器;
⑥ 函数添加依赖包;
⑦ 订阅模型并部署;
⑧ 制作动漫头像。
3 项目准备
3.1 注册与登录华为云账号
进入开发者空间,领取云主机
4 实验步骤
4.1 首先我们配置云主机
进入云桌面
4.2 安装FunctionGraph插件
这里我们可以选择两种安装方式!
方式一:在线安装
进入云主机 ,打开CodeArts IDE,点击左侧“扩展”搜索“CodeArts FunctionGraph”点击安装该插件。
方式二:本地安装
前往鲲鹏社区官网下载插件CodeArts FunctionGraph到云主机,下载地址为:CodeArts IDE 插件市场 。
这里我们采用方式一!
4.3 创建函数
接下来按照步骤即可
选择Http Function函数。
选择Hello World
打开工程目录,创建新文件夹:templates
在templates中创建文件index.html
html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FunctionGraph 动漫头像制作</title>
<style>
body {
font-family: Arial, sans-serif;
background: repeating-linear-gradient(45deg, #ddd 0 2px, transparent 2px 4px), repeating-linear-gradient(-45deg, #ddd 0 2px, transparent 2px 4px);
text-align: center;
}
h1 {
color: #333;
}
p.description {
color: #666;
}
#upload-button {
padding: 15px 30px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 20px;
margin-top: 20px;
}
.image-container {
display: flex;
margin-top: 50px;
justify-content: center;
align-items: center;
}
.image-box {
margin: 0 40px;
padding: 0;
width: 500px;
height: 500px;
display: flex;
flex-direction: row;
position: relative;
letter-spacing: .3px;
padding: 10px;
border-radius: 10px;
transition: background-color .3s ease-in-out;
display: flex;
justify-content: center;
align-items: center;
background-color: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
#original-image-box, #preview-container {
border: 2px dashed #6dcff6;
border-radius: 10px;
width: 480px;
height: 480px;
}
.but-box {
margin: 0px 30px;
padding: 0;
width: 500px;
display: flex;
justify-content: center;
font-size: 30px;
font-weight: 700;
}
.image-box img {
height: 100%;
max-width: 100%;
}
.error-message {
color: red;
margin-top: 10px;
}
.size-warning {
font-size: 20px;
color: orange;
margin-top: 10px;
}
button {
padding: 20px 40px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 20px;
}
h1 {
font-size: 40px;
}
.triangle-arrow {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 30px solid blue;
}
.loading-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.1);
display: none;
justify-content: center;
align-items: flex-end;
z-index: 999;
}
.loading-text {
font-size: 30px;
color: red;
}
</style>
</head>
<body>
<h1>动漫风格头像制作案例:用户上传自拍照片,调用华为云上算力,一键生成动漫风格人物头像。</h1>
<input type="file" id="image-input" style="display: none;">
<button id="upload-button">请上传照片</button>
<p class="size-warning">上传小于 6MB 的图片。</p>
<p class="error-message" id="size-error"></p>
<div class="image-container">
<div class="image-box">
<div id="original-image-box">
</div>
</div>
<div class="triangle-arrow"></div>
<div class="image-box">
<div id="preview-container">
</div>
</div>
</div>
<div class="image-container">
<div class="but-box">
原图
</div>
<div class="but-box">
效果图
</div>
</div>
<div class="loading-mask" id="loading-mask">
<p class="loading-text">照片生成中...</p>
</div>
<script>
const uploadButton = document.getElementById('upload-button');
const imageInput = document.getElementById('image-input');
const originalImageBox = document.getElementById('original-image-box');
const imagePreview = document.getElementById("preview-container");
const sizeError = document.getElementById('size-error');
const sizeWarning = document.querySelector('.size-warning');
const loadingMask = document.getElementById('loading-mask');
uploadButton.addEventListener('click', () => {
imageInput.click();
});
imageInput.addEventListener('change', () => {
const file = imageInput.files[0];
if (file) {
if (file.size > 6 * 1024 * 1024) {
sizeError.textContent = '图片大小不能超过 6MB。';
sizeWarning.textContent = '';
return;
}
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
originalImageBox.innerHTML = '';
originalImageBox.appendChild(img);
if (!file) {
console.log("!file ")
return;
}
const formData = new FormData();
formData.append("image", file);
loadingMask.style.display = 'flex';
fetch("/carton/upload", {
method: "POST",
body: formData,
})
.then((response) => response.text())
.then((data) => {
let parsedObject;
try {
parsedObject = JSON.parse(data);
} catch (error) {
console.error('JSON 解析错误:', error);
parsedObject = null; // 或者其他默认值,根据你的需求设置
}
const animeImgElement = document.createElement('img');
animeImgElement.src = "data:image/png;base64," +
parsedObject.results[0];
imagePreview.innerHTML = '';
imagePreview.appendChild(animeImgElement);
loadingMask.style.display = 'none';
})
.catch((error) => {
loadingMask.style.display = 'none';
console.error(error);
alert("处理失败");
});
}
});
</script>
</body>
</html>
删除index.js,创建新文件app.py
修改app.py内容如下
from flask import Flask, request, render_template
import requests
import os
MODEL_ART_API = os.getenv('MODEL_ART_API')
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/carton/upload', methods=['POST'])
def upload_file():
if 'image' not in request.files:
return 'No file uploaded.', 400
file = request.files['image']
if file.filename == '':
return 'Filename is empty.', 400
resp = model_art_pic_carton(file)
print(resp)
return resp.json()
def model_art_pic_carton(file):
payload = {}
files=[ ('images',(file.filename,file,'image/png'))]
headers = {
'x-auth-token': get_token_from_fg_header()
}
response = requests.request("POST", MODEL_ART_API, headers=headers, data=payload, files=files,verify=False)
return response
# 从FunctionGraph平台发送的请求里获取鉴权token
# 需要先配置委托 并且 在高级设置打开传入秘钥开关
def get_token_from_fg_header():
return request.headers.get("X-Cff-Auth-Token")
if __name__ == '__main__':
app.run(debug=True,port=8000,host="0.0.0.0")
# 从FunctionGraph平台发送的请求里获取鉴权token
# 需要先配置委托 并且 在高级设置打开传入秘钥开关
def get_token_from_fg_header():
return request.headers.get("X-Cff-Auth-Token")
if __name__ == '__main__':
app.run(debug=True,port=8000,host="0.0.0.0")
修改bootstrap文件内容如下:
/opt/function/runtime/python3.6/rtsp/python/bin/python3 $RUNTIME_CODE_ROOT/app.py
4.4 部署函数
回到插件页面,选择部署函数
选择新建的函数下的yml文件
部署环境选择“华北-北京四
之后就部署成果了,点击“选择要展示的Region”,选择“华北-北京四”,可以看到该区域下刚部署好的函数:carton-generation,右键选择函数,点击浏览器打开,跳转到函数详情界面
4.5 函数配置委托
这里我简单的贴图,具体流程请查看官方文档
4.6 函数配置触发器
点击“创建触发器”,选择“触发器类型”,选择“分组”(如果没有分组需先创建),选择“安全认证”,设置“后端超时”。
4.7 函数添加依赖包
返回“函数工作流”管理界面,选择“依赖包管理”,点击“创建依赖包”。
这里有些同学可能找不到,我们从上面搜索即可
填写“依赖包名称”,代码包上传方式为“从OBS上传文件”,将OBS链接粘贴到“OBS链接URL”中(OBS URL:https://functionstorage-cn-north-4.obs.cn-north-4.myhuaweicloud.com/applications/depdency/flask-2_0_1-1.zip )
运行时语言为“Python3.9”。
进入函数详情页底部,点击“添加依赖包”。这里有些人可能也找不到,下图可以帮你更快找到
4.8 订阅模型并部署AI应用
编辑环境变量
4.9 制作动漫头像
访问URL
网上下载一个美女图片
体验完别忘了关机哦
5 总结与心得
本文粗略的介绍了如何利用华为云的FunctionGraph和ModelArts服务,实现智能化的动漫头像生成。通过FunctionGraph的无服务器计算特性,开发者无需管理底层计算资源,只需关注代码逻辑,而ModelArts则提供了强大的AI模型支持,使得图像风格化处理变得简单高效。文章详细讲解了上传头像、调用ModelArts模型进行动漫化处理的具体步骤,并展示了处理后的效果。这样的AI风格化技术不仅可以应用于个人头像,还具有广泛的商业应用前景,如内容创作、社交媒体和游戏等多个领域。这一解决方案展示了华为云AI生态系统的便捷和强大,同时也让开发者认识到云端AI服务的高效性和灵活性,是推动AI技术应用落地的良好范例。
我正在参加【有奖征文 第34期】华为开发者空间一行代码快速上云,更有开发者周边等你拿!
链接:https://bbs.huaweicloud.com/blogs/438987