产品应用实践:智能头像动漫化处理案例介绍【华为开发者空间】

举报
郑小健 发表于 2024/12/17 12:51:54 2024/12/17
【摘要】 本实验聚焦于利用华为云的FunctionGraph和ModelArts平台,构建一个智能头像动漫化处理应用。该应用允许用户上传自己的头像图片,并通过调用部署在ModelArts上的深度学习模型,将这些图片转换为具有独特风格的动漫头像。本文不仅会详细介绍技术架构与实现步骤,还将深入探讨部署流程,确保读者能够全面理解并实际操作。

概述

本实验聚焦于利用华为云的FunctionGraph和ModelArts平台,构建一个智能头像动漫化处理应用。该应用允许用户上传自己的头像图片,并通过调用部署在ModelArts上的深度学习模型,将这些图片转换为具有独特风格的动漫头像。本文不仅会详细介绍技术架构与实现步骤,还将深入探讨部署流程,确保读者能够全面理解并实际操作。
实验流程图
【流程说明】:根据官方文档介绍,本实验的步骤主要分成以下八个:
① 安装FunctionGraph插件;
② 创建函数;
③ 部署函数;
④ 函数配置委托;
⑤ 函数配置触发器;
⑥ 函数添加依赖包;
⑦ 订阅模型并部署;
⑧ 制作动漫头像。

技术架构详解

  1. FunctionGraph:

    • FunctionGraph是华为云提供的无服务器计算服务,支持多种编程语言(如Python、Node.js等),使得开发者可以专注于业务逻辑开发,而无需关心服务器管理和扩展。
    • 在本项目中,我们使用Python编写函数来处理HTTP请求,解析上传的图片文件,并调用ModelArts API进行图像处理。
  2. ModelArts:

    • ModelArts是一个一站式AI开发平台,提供从数据标注到模型训练、部署的一整套工具和服务。
    • 我们选择了预训练的“人像动漫化”模型,并对其进行微调以更好地适应特定需求。之后,我们将此模型部署为在线推理服务,供FunctionGraph调用。
  3. API Gateway:

    • API Gateway用于创建、发布、维护和监控API,它能有效地管理API的安全性、访问控制和流量限制。
    • 在本案例中,API Gateway充当了前端接口层,负责接收用户的请求,并将其转发给后端的FunctionGraph函数。
  4. OBS (Object Storage Service):

    • OBS提供了高可靠性和高性能的对象存储服务,适用于存储静态资源,如图片、视频等。
    • 用户上传的原始图片以及生成的动漫化结果都将保存在OBS中,以便后续查看或下载。
  5. IAM (Identity and Access Management):

    • IAM用于定义和管理对华为云资源的访问权限,确保只有授权用户才能执行特定操作。
    • 在部署过程中,我们需要设置适当的IAM策略,以保证安全性和合规性。

部署流程详细说明

环境准备
  • 注册华为云账号: 如果还没有华为云账号,请先注册一个新账号,并完成实名认证。华为云有免费体验赠送的云主机哟,这里我们需要进入云主机。

  • 打开CodeArts IDE: 进入云主机后 ,打开CodeArts IDE.
    打开CodeArts IDE

  • 安装FunctionGraph插件: 点击右侧“扩展”搜索“CodeArts FunctionGraph”点击安装该插件。

  • 创建函数: 打开插件,在插件窗口点击“…”选择“创建函数”,选择Http Function函数。

  • 选择Hello World: 这里根据引导直接选择Hello World即可。

  • 定义函数名: 这里我们定义函数名为carton-generation。

  • 选择工程路径: 选择工程路径,选择后插件会在该路径下创建carton-generation工程。

  • 创建新文件夹: 打开工程目录,创建新文件夹:templates。

  • 创建文件: 在templates中创建文件index.html。

  • 编辑代码: 编辑index.html代码,如下图所示(这里我参照了官方引导代码,就不复制下来了):

    *这里代码有点长,还用不习惯这里的格式排布,大家可以复制代码到IDE去重新整理下:

<!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>
  • 删除app.py: 删除index.js,创建新文件app.py

  • 修改app.py代码: 修改app.py内容如下:(这里我代码就不复制下来了)。

  • 修改bootstrap文件内容: 修改bootstrap文件内容如下,这可一定不要忘记改了。
    /opt/function/runtime/python3.6/rtsp/python/bin/python3 $RUNTIME_CODE_ROOT/app.py

  • 部署函数: 接下来我们就可以回到插件页面,选择部署函数。部署的时候我们选择新建的函数下的yml文件。

  • 地区选择: 地区的话选择部署环境选择“华北-北京四”。

  • 部署等待:等待部署成功。

    点击“选择要展示的Region”,选择“华北-北京四”,可以看到该区域下刚部署好的函数:
    carton-generation

  • 打开函数: 接下来右键选择函数,点击浏览器打开,跳转到函数详情界面。

  • 函数配置委托: 打开创建委托页面地址:
    https://console.huaweicloud.com/iam/?agencyId=9525e901e4a44845bf64b4aec74d7be7&region=cn-north-4&locale=zh-cn#/iam/agencies/create
    输入委托名称、委托类型选择“云服务”、云服务选择“函数工作流FunctionGraph”。

  • 配置权限:配置权限,选择ModelArts FullAccess(这里可以直接搜索)。

  • 完成授权:完成授权后会出现以下结果:

  • 函数配置委托:回到浏览器函数详情界面,点击“设置”,选择“权限”,“函数配置委托”选择提前创建好的委托,点击“保存”。

  • 函数配置触发器: 点击“创建触发器”,选择“触发器类型”,选择“分组”(如果没有分组需先创建),选择“安全认证”,设置“后端超时”。

  • 函数添加依赖包1: 返回“函数工作流”管理界面,选择“依赖包管理”,点击“创建依赖包”。

  • 函数添加依赖包2: 填写“依赖包名称”,代码包上传方式为“从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”。

  • 添加依赖包:进入函数详情页底部,点击“添加依赖包”。选择“私有依赖包”,依赖包名称如图所示。

  • 订阅模型并部署AI应用:在华为云控制台点击搜索框搜索“ModelArts ”,点击“ModelArts”,选择“AI Gallery”。

  • 头像动漫化模型:导航栏选择“模型”,搜索框输入“动漫”,选择“头像动漫化模型”。

  • ModelArts部署:进入详情页,点击“部署”,选择“ModelArts”。

  • ModelArts云服务:选择ModelArts的云服务区域。

  • 创建委托:跳转到订阅应用列表,如果页面提示需要创建委托,根据指引创建即可。

  • 部署:委托创建成功后订阅应用列表,点击“部署”。准备就绪后,点击右侧弹窗“部署”按钮,选择“在线服务”。

  • 资源配置:资源池选择“公共资源池”,AI应用及配置选择“订阅应用”,选择AI应用及版本,计算节点规格选择“[限时免费]CPU:1核4GB”,勾选“我已阅读并同意以上内容”,点击“下一步”。

  • 提交部署:点击“提交”(调后需要耐心等待部署进度)。

  • 运行服务:确认服务处于运行中状态,复制API接口公网地址备用。

  • 环境变量:回到函数页面,设置环境变量,键:MODEL_ART_API,值:刚刚复制的API接口公网地址。

  • 制作动漫头像:到这里函数和AI应用就已经部署好了,可以复制URL到浏览器打开web页面开始制作动漫头像。

  • 来看看效果吧:至此该实验已完成,我们看看动漫头像效果吧!

结果与影响

通过本次实践,我们不仅成功构建了一个高效、易用的智能头像动漫化处理应用,还展示了云计算与AI技术相结合的强大潜力。该方案不仅可以应用于社交媒体、游戏等领域,还可以进一步探索更多基于AI的图像处理应用场景,为用户提供更加个性化和有趣的互动体验。同时,借助华为云提供的丰富工具集和服务,开发者可以在短时间内完成复杂项目的开发与部署,降低了技术门槛的同时也提升了项目的灵活性和响应速度。

这篇文章我尽可能详尽地描述了如何结合FunctionGraph和ModelArts来实现智能头像动漫化处理的应用,特别是针对部署流程进行了详细的说明。希望这些信息能帮助您更深入地理解和实施该项目。

我正在参加【有奖征集 第34期】华为开发者空间一行代码快速上云,参与视频、文章投稿赢2000元开发者礼包。
链接:https://bbs.huaweicloud.com/blogs/438987

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。