Android程序员怎么从零到一开发一个自己的AI小程序并上线

引言

一个android端的程序员,经常会冒出一些好玩的点子,特别是现在AI技术发展的那么快,想过把自己的一些好玩的idea做成app,但是目前国内app上线的流程非常麻烦,需要申请软件著作,还有一大堆审核。所以我想先做小程序吧,既能承载我需要的功能,也不需要非常麻烦的审核。(其实后面微信小程序上线也碰到一些问题)

源起

一直以来对中国传统文化感兴趣,特别是对汉服挺感兴趣的,但是又舍不得钱自己去买汉服穿,想着要是能结合AI能力,让自己或者朋友能很方便的体验到穿汉服的乐趣那该多好。怎么才能让别人很方便的体验到汉服呢?首先想到的是用AI的换脸技术,先找到一批/生成一批中国各个朝代的底图,然后一键换上自己的脸。

简单流程

流程比较简单,但是这样的话可玩性太差了,最好对底图进行分类,让用户有可以有不同的选择,比如性别分类:小孩,男子,女子。社会地位分类:帝王、公主、皇后、文臣、武将、平民等,还有朝代分类。根据这种想法给了三个不同的分类方式,方便用户选择不同的角色进行体验。

朝代 角色 性别
商周 神话 孩童
帝后 女子
皇室 男子
三国 文臣
隋唐 武将
... 平民
民国 妖魔

除了上面的三种分类之外,对于每一个角色,也可能有不同的服装,简单的例子:古代官员 有朝服 有便服。并且对于同一个角色应该设置不同镜头的底图,比如远景 近景 中景 方便用户选择。

梳理之后的流程图如下:

设计和实现

源起里面已经把想要的主要功能梳理清楚了,可以提供给用户选择不同朝代、不同地位、不同性别的底图进行换脸然后生成自己想要的图片。根据上面的主要功能给出数据结构设计和技术选型。

  1. 技术选型

由于之前一直做的客户端开发,熟悉的语言是java/kotlin没有接触过微信小程序相关的,所以在网上搜了一波,最后选择uniapp来做小程序,选择uniapp的原因:

  • 使用vue语法比较简单,大概看了一两晚 基本上能够动手写。
  • uniapp提供了多端能力,后面要做抖音小程序或者原生的app方便。
  • 最重要的是可以使用unicloud能力,使用云函数,(不熟悉后台开发的福音)而且每月的费用比较低,我选的是5/月最低的。

明确使用uniapp来开发小程序后,前端/后端一个人就可以搞定了,使用unicloud云,不用自己部署服务器,对之前客户端开发的人来说也很容易上手。

  1. 数据库设计

由于换脸是依赖底图的,并且还有朝代、性别、社会地位等区别。

  1. 角色数据表
字段 类型 描述
name string 姓名(花木兰)
dynasty string 朝代(隋唐/宋朝等)
role string 角色(皇帝/平民等)
gender int 性别(男/女/儿童)
image_list string[] 底图列表
intro string 角色介绍
use_count int 用户使用次数
  1. 分类数据表

因为要对角色进行通过朝代、性别、地位分类,所以需要抽出一个分类表

字段 类型 描述
category string dynasty/gender/social用来区分大类
image string 分类的封面图片
title string 隋唐

3、换脸能力接入

如何接入换脸能力呢?可以参考这个图像流,具体的如何接入,可以私聊我。

实现效果

1、首页
2、详情页
3、生成结果页
4、生成海报

引导弹框

上新角色时如何让用户快速的看到角色,或者上新功能时如何让用户快速的体验新功能,这块做了一个引导弹框管理类,用来管理弹框。

1、引导弹框
2、引导弹框管理设计

当有新功能/新角色上线时 引导用户去体验,如果要做成可配置化,就需要解藕,当不同活动上线的时候也可以使用。

活动弹框包含两个部分,第一个是活动图片,第二个是关闭按钮,图片可以通过下发来配置,但是图片的点击跳转,最好也能够通过配置下发,关闭按钮的逻辑是统一的,点击之后就关闭当前弹框。

  • 弹框展示逻辑

    • 对每个用户同一个弹框只展示一次,用户点击/包括关闭/跳转之后都不再展示。
    • 弹框是否展示逻辑保存在本地,如果用户移除了小程序,下次打开小程序时还是会展示。(不放服务端)
  • 弹框数据结构

    id image type routerUrl times priority
    弹框的唯一标识 活动图片 1:功能dialog2:新角色dialog 跳转详情页的路径 弹框频次默认1次 弹框展示的优先级/优先级越高,越先展示
  • 弹框列表

    • dialog_list,当配置了多个弹框时,会根据优先级从前往后遍历弹框,找到未使用的弹框进行弹出。(频控逻辑:一天只弹一个弹框)
dialog1 dialog2 dialog3 ... dialogn
3、实现
  1. 弹框管理器
javascript 复制代码
//用于弹框的频控管理类
export function canShowDialogById(id) {
        //判断弹框是否可以展示
        const list = uni.getStorageSync('dialog_id_list') || [];
        // 判断 list 中是否包含 id
        const isIdInList = list.includes(id);
        // 如果 id 存在于 list 中,则返回 false;否则返回 true
        return !isIdInList;

}
//保存弹框展示
export function saveDialogTimeById(id) {
        uni.setStorageSync('dialog_id_list', id);

}
export function getDialogItem(list) {
        if (!list) {
                return null;
        }
        // 使用 find 方法查找符合条件的 item
        const foundItem = list.find(item => {
                return item && item._id && canShowDialogById(item._id);
        });
        console.log("get dialog item", foundItem);
        return foundItem || null;
}
  1. 弹框类
xml 复制代码
<template>
        <view class="mask"></view>
        <view class="modal">
                <image class="modal-image" :src="dialogItem.image" mode="widthFix" @click="gotoDetail"></image>
                <image class="close-button" src="/static/images/icon_close.png" @click="closeModal"></image>
        </view>
</template>

<script>
        export default {
                name: "custom-dialog",
                props: {
                        dialogItem: {
                                type: Object,
                                required: true
                        }
                },
                data() {
                        return {

                        };
                },
                methods: {
                        closeModal() {
                                console.log("close modal");
                                this.$emit('closeModal');
                        },
                        gotoDetail() {
                                this.$emit('gotoDetail');
                        },
                }
        }
</script>

<style>
        .mask {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: rgba(0, 0, 0, 0.5);
                z-index: 9999;
        }

        .modal {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                width: 80vw;
                /* 宽度为屏幕宽度的80% */
                text-align: center;
                z-index: 19999;
        }

        .modal-image {
                width: 100%;
                height: auto;
                /* 图片高度自适应 */
                z-index: 19999;
        }

        .close-button {
                margin-top: 20px;
                /* 调整关闭按钮与图片间距 */
                width: 40px;
                /* 调整关闭按钮的大小 */
                height: 40px;
                /* 调整关闭按钮的大小 */
                display: block;
                margin: 0 auto;
                z-index: 19999;
                /* 将关闭按钮水平居中 */
        }
</style>

推荐角色

当用户生成当前角色后,给用户推荐其他角色,让整个流程更加完善,提高用户体验,不然用户生成一个角色之后又要返回去选其他角色

1、通过算法推荐,可以动态调整。

2、直接指定,方便配置下发。

1、推荐算法

1、活动角色

如果是活动角色,从活动列表中获取同性别角色。如果没有同性别角色,获取其他性别角色。

2、其他角色

优先找同朝代,同身份、同性别的角色,如果没有同身份的角色、找同性别不同身份的角色,如果没有同性别、不同身份的角色 查找其他朝代同性别、同身份的角色。

暂时无法在飞书文档外展示此内容

3、朝代关联关系

朝代 关联
清朝 民国
明朝 宋朝
... ...

4、推荐角色剔除

对用户已经生成过的角色不再推荐,从推荐列表中进行剔除,不然达不到让用户体验多个角色的目标。

2、手动配置推荐角色

直接在数据库中关联下发推荐的角色,下发的推荐角色不可以更改,但是可以定制化推荐。

perl 复制代码
{
    "dynasty": "商周",
    "dynasty_label": "商周",
    "gender": "male",
    "image_list": [
        "https://env-00jxh1m2drwc.normal.cloudstatic.cn/hot-style/%E5%95%86/%E5%95%86%E5%91%A8-%E5%A7%AC%E5%8F%9101.png",
        "https://env-00jxh1m2drwc.normal.cloudstatic.cn/hot-style/%E5%95%86/%E5%95%86%E5%91%A8-%E5%A7%AC%E5%8F%9102.png"
    ],
     "recommend_list": [
        "1",
        "2"
    ],
    "intro": "姬发",
    "name": "姬发",
    "role": "武将"
    "count":0
}
3、新增角色生成次数数据

每个角色生成时,上报一条生成数据,用于推荐算法的使用,推荐时可以从其他用户使用最多的角色里面进行选择。新增count字段。用于统计角色生成次数

perl 复制代码
{
    "dynasty": "商周",
    "dynasty_label": "商周",
    "gender": "male",
    "image_list": [
        "https://env-00jxh1m2drwc.normal.cloudstatic.cn/hot-style/%E5%95%86/%E5%95%86%E5%91%A8-%E5%A7%AC%E5%8F%9101.png",
        "https://env-00jxh1m2drwc.normal.cloudstatic.cn/hot-style/%E5%95%86/%E5%95%86%E5%91%A8-%E5%A7%AC%E5%8F%9102.png"
    ],
    "intro": "姬发",
    "name": "姬发",
    "role": "武将"
    "count":0
}
4、随机推荐算法

用户已经使用过,如何推荐,用户未使用过,如何推荐。

  1. 根据选择偏好比例推荐

    1. 根据用户选择历史人物的性别和朝代比例,结合用户的选择偏好,给出推荐列表。
  2. 避免重复推荐

    1. 确保推荐的历史人物不与用户已选择过的历史人物角色重复。

广告接入

广告接入采用尽量少打扰用户的方式,用户进入时不会看到广告,只有其他操作时才让用户看广告。

场景 场景截图 广告类型 广告样式 时机 频控 对应代码
列表页 原生广告-横幅 用户下滑获取更多时,插入广告,首页默认展示3个底图,上滑时 是否可以在第5个位置放广告?其他页面类似。
合成中 原生广告-格子 合成时放在合成文案的下面 每次合成时都展示 // wxml文件
开始合成 激励广告 用户点击开始穿越的时候展示只有看完广告之后才可以开始穿越,不然不可以穿越 看一次广告可以穿越几次?

小程序上线碰到的问题

1、小程序备案

由于没有公司,也不想做个人小程序,所以弄了个人工商的小程序,按照微信的收费工商的一年300元。万能淘宝可以解决,懂的都懂。

2、算法备案

由于小程序涉及到换脸功能,需要AI算法备案,这个当时愁死了,但是最后还是解决了,也没花啥钱,在淘宝上问了一家开口5888元,最后不到100元搞定。

最后

喜欢的同学可以扫码体验一下,有想交流的也可以留言。

相关推荐
qq229511650214 分钟前
微信小程序的汽车维修预约管理系统
微信小程序·小程序·汽车
我要洋人死27 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人39 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人39 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍