首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >App设计:消息推送和界面路由跳转

App设计:消息推送和界面路由跳转

作者头像
用户1172465
发布于 2018-01-08 06:30:56
发布于 2018-01-08 06:30:56
3.1K00
代码可运行
举报
文章被收录于专栏:everhadeverhad
运行总次数:0
代码可运行

概要

app消息推送、显示通知栏,点击跳转页面是很一般的功能了,下面以个推为例演示push集成,消息处理模块及app内部路由模块的简单设计。

推送

推送sdk集成

集成sdk步骤根据文档一步步做就行了,一般包括lib引入,AndroidManifest.xml配置,gradle配置,拷贝资源和java文件等。 需要注意的,自己应该做一层封装,因为像图片,统计,推送等第三方api,如果有替换升级等需求,那么封装一层来确保自己代码的更少变动也是蛮必要的。

服务端推送消息的操作是非UI操作,个推接入后在一个IntentService中收到透传消息(透明传输消息):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public void onReceiveMessageData(Context context, GTTransmitMessage msg) {
    try {
        String payload =  new String(msg.getPayload());      
        PushManager.handlePushMsg(context, payload);
    } catch (Exception ex) {
      // log it.
    }
}

payload就是收到的push消息,一般是约定好的json文本。 下面是一个基本示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  title:"通知标题",
  content:"通知内容",
  payload: {
    type:"page",
    extra:{
      path:"/article/articleDetail",
      params:{
        "id":"10086"
      }      
    }
  }
}

一般的推送都需要立即显示通知的,所以会有通知的信息。当然也可以是不带通知的推送。 这里payload里面携带了点击推送后的操作数据,type="page"表示此推送需要执行一个跳转。 path是跳转到的(以下路由表示相同含义)页面的路径——类似url那样的格式,抽象了具体界面。params包括了跳转相关参数,比如这里需要打开文章详情页,那么传递了文章id。

web中的url跳转机制非常值得借鉴。

消息&处理

程序设计中,有一种模式:命令模式,将操作和具体的执行分开。安卓系统中的输入事件的处理,Handler+Message机制等,都是类似的。 Msg用来抽象一个消息,而对应的有Handler来处理它。 这样的好处是命令被对象化,之后对它的处理可以利用多态等特性,命令的处理或许要经历多个阶段(Stage),这样可以动态组合不同的Handler完成对同一个Msg的处理。

如果仅仅是简单的switch+static method去实现的话,随着业务增加,是无法胜任变化的。如果有实现涉及到“消息处理”类似功能的话,不同消息不同处理的大前提,多重处理的需要,会让switch泛滥成灾的,而msg+handler仅需要一次switch选择合适的Handler,之后的处理是链式的,不会有再次switch的需要的。

推送处理

可以思考下“消息+处理”这类功能的设计方案。 下面分PushMessage和PushHandler两个抽象,分别是推送消息和对应处理。 这里的思路借鉴了安卓中Handler的机制——Handler+Message这样的设计。

此外,源码ViewRootImpl、InputStage对输入事件的处理也可以借鉴。

PushMessage

类PushMessage其实就是个bean,它对后台推送的消息进行表示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class PushMessage implements Serializable {
  private String title;
  private String content;
  private Payload payload;
  ...
}

PushHandler

每一个PushHandler处理一个PushMessage。这里是一个基类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * PushMsgHandler基类
 * ,PushMsgHandler用来处理“某一个”PushMessage
 */

public abstract class BasePushMsgHandler {
    protected PushMessage mMessage;

    public BasePushMsgHandler(PushMessage message) {
        mMessage = message;
    }

    public abstract void handlePushMsg();
}

handlePushMsg()用来供子类完成具体的消息处理。 这里假设业务功能上,需要一类推送是弹通知,并处理通知点击后的路由操作——界面跳转。 这里引入另一个模块——路由模块,路由模块完成界面跳转相关操作。 像Arouter这样的开源库就是做这类事情的——不论web还是移动app,都会碰到接收并响应界面跳转指令的功能。 接下来继续自己尝试实现路由功能。 因为路由模块和推送不是相关的——路由命令(或者称为消息)的发出不一定是推送,也可以是其它界面中的按钮等,知道路由模块和推送模块需要分别设计很重要。

有一部分推送是需要执行路由的,对这类推送的处理就是得到其对应的路由命令,之后交给路由模块去处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class BaseRoutePushHandler extends BasePushMsgHandler {
    public BaseRoutePushHandler(PushMessage message) {
        super(message);
    }

    @Override
    public void handlePushMsg(Context context) {
        BaseRouteMsg msg = getRouteMsg();
        if (msg != null) {
            RouterManager.navigate(context, msg);
        }
    }

    public abstract BaseRouteMsg getRouteMsg();
}

BaseRoutePushHandler重写handlePushMsg()完成routeMsg——路由命令的push消息的处理。getRouteMsg()供子类获取到路由命令的消息对象,之后交给RouterManager去处理。

路由模块

路由模块实现app内不同界面之间的跳转导航。设计上,RouteMsg表示一个具体的路由命令,之后会有一个(或多个——如果对命令的处理是链式的话?)RouteHandler来处理此路由消息。

路由消息

鉴于URL对不同web界面的定位导航优势,为系统中不同的跳转定义路由path是很不错的想法。 甚至可以定位到界面中的tab子界面,如果直接去关联Activity等,那么耦合非常严重。

RouteMsg设计上只用来表达路由命令,它包含路由path和额外参数。为了面向对象化,参数是有含义的强类型,而不是queryParams那样的基本类型key-value集合,要知道key的命名本身就是一种依赖,那么还不如定义key对应的java属性更直接些。 RouteMsg也是一个bean,当然可以跨进程,这里实现Parcelable当然更好,简单点就实现Serializable标记接口即可。

基类BaseRouteMsg定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class BaseRouteMsg implements Serializable {
    private static int mIdSeed;
    static {
        // 设置mIdSeed初始值:
        // 允许0.1s一个的间隔,不会有超过8*100天的msg还没被处理
        long stamp = System.currentTimeMillis() / 100;
        mIdSeed  = (int) (stamp % (8 * 24 * 3600 * 1000));
    }
    private final int mMsgId = mIdSeed++;

    /**
     * 获取路由对应的path
     * @return route path
     * @see RouteMap
     */
    public abstract String getPath();

    /**
     * 消息编号,递增唯一(方便跨进程)。
     */
    public final int getMsgId() {
        return mMsgId;
    }
}

其中getPath()方法要求每个具体的路由消息声明其对应的跳转路径。子类可以定义其它任意属性——可以被序列化即可。

作为示例,下面是文章详情界面的跳转路由消息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ArticleDetailMsg extends BaseRouteMsg {
    private int mArticleId;

    @Override
    public String getPath() {
        return RouteMap.PATH_ARTICLE_DETAIL;
    }

    public int getArticleId() {
        return mArticleId;
    }

    public void setArticleId(int articleId) {
        this.mArticleId = articleId;
    }
}

RouteMap

对应每个RouteMsg对象需要有RouteHandler来处理它,这里引入路由表的概念——RouteMap,它定义了所有的path常量以及获取不同path对应RouteHandler的方法(工厂方法)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public final class RouteMap {
   public static final String PATH_ARTICLE_DETAIL = "articleDetail";

   public static BaseRouter getRouter(String path) {
        switch (path) {
            case RouteMap.PATH_ARTICLE_DETAIL:
                return new ArticleDetailRouter();
            default:
              return null;
        }
  }
}

getRouter(path)根据path返回处理它的RouteHandler,并且RouteMap定义了所有可能的路由path。BaseRouter就是处理某个path对应路由消息的Handler。

BaseRouter

基类BaseRouter是抽象的路由消息处理器。将路由模块作为框架设计,需要尽可能使用抽象的东西,允许变更及扩展。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class BaseRouter<T> {
    protected T mRouteMsg;

    /**
     * 路由操作的前置判断
     * @return 是否继续前往目标界面
     */
    public boolean canRoute(Context context) {
        return true;
    }

    /**
     * 执行导航到目标界面
     *
     * @return 导航成功?
     */
    public abstract boolean navigate(Context context);

    public void setRouteMsg(T msg) {
        mRouteMsg = msg;
    }
}

对于mRouteMsg可能更应该是构造函数参数,而且藐似不应该被setter篡改。这里为了可能的方便性(目前不知道是什么),决定还是作为普通的属性对待。 注意Context是android中的上帝对象,可以肯定导航操作需要它,但为了弱化它和RouteHandler的依赖关系(或许是生命周期)仅作为参数提供,而非字段。

方法canRoute(context)用来做导航操作的前置判断,因为路由可能涉及登录判断等环境问题,这个逻辑需要子类去重写,如果没特殊要求,这里默认返回true。

方法navigate(context)是具体的导航操作,如打开某个Activity。

推送-通知-路由处理流程

上面分别介绍了推送和路由模块的大体设计,那么收到一个推送消息,弹出通知,用户点击通知后的跳转,这一系列操作是如何贯彻的呢?接下来就看看。

响应推送消息

在sdk提供的IntentService.onReceiveMessageData()中收到透传消息,这里的代码是依赖服务器返回的数据格式的,即json和PushMessage对应,第一步将push消息转为java对象,接着交给PushManager去处理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在PushIntentService.java中,这是sdk提供的接收推送消息的地方
public void onReceiveMessageData(Context context, GTTransmitMessage msg) {
    try {
        String payload =  new String(msg.getPayload());
         PushMessage message = PushMessage.build(payload);
        PushManager.handlePushMsg(context, message);
    } catch (Exception ex) {
    }
}

// PushManager.handlePushMsg()
public static void handlePushMsg(Context context, PushMessage message) throws Exception {
  BasePushMsgHandler pushHandler = PushHandlerManager.getPushHandler(message);

  if (pushHandler != null) {
      BaseRouteMsg routeMsg = pushHandler.getRouteMsg();

      if (routeMsg != null) {
          NotifiyManager.notifyRouteMsg(context, message.getTitle()
                  , message.getContent(), routeMsg);
      }
  }
}

这里使用一个Manaher类来完成对PushMessage的一般处理逻辑。因为需求假定push都需要谈通知,并且通知点击后执行路由,那么先得到一个routeMsg,之后调用NotifiyManager.notifyRouteMsg()来发送通知。 通知以类似Intent的方式携带了之后的路由消息数据。

弹出通知

安卓中发送通知到通知栏是很简单的操作,需要注意的是:

  1. 使用NotificationCompat.Builder 来避免兼容问题。
  2. 建议使用String tag来区分不同的通知。

使用tag区分通知

使用tag来发送通知的notify()方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Post a notification to be shown in the status bar. If a notification with
 * the same tag and id has already been posted by your application and has not yet been
 * canceled, it will be replaced by the updated information.
 *
 * @param tag A string identifier for this notification.  May be {@code null}.
 * @param id An identifier for this notification.  The pair (tag, id) must be unique
 *        within your application.
 * @param notification A {@link Notification} object describing what to
 *        show the user. Must not be null.
 */
public void notify(String tag, int id, Notification notification)

因为id是一个int整数,很难做到对不同业务通知进行唯一区分。 使用tag,因为是一个可以组合的字符串,那么格式就比较灵活了,例如可以使用uri这种格式,或者其它任意你能够轻松用来区分不同业务模块不同通知的格式来产生tag作为通知的标识。

通知点击效果

有关Notification的完整用法这里不去展开,为了能在点击通知之后做一些控制——比如判断用户是否登录等,可以让通知的点击行为是打开一个Service,而不是跳转到某个Activity。

这样的好处是不至于去修改Activity的代码来插入通知跳转的各种逻辑,当然必要的处理有时是必须的——比如Activity打开后清除对应通知。但这类工作可以做的更一般化,让Activity提供最少的逻辑,比如提供管理的跳转path,这样清除通知(或需要撤销的其它路由命令)的动作就可以框架去做了。这部分的功能目前不打算提供,但的确是一个需要考虑的必要功能。

下面的代码展示了点击通知启动Service的操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void sendRouteNotification(Context context, String title, String content,
                                          String notificationTag, BaseRouteMsg msg) {
    Intent startIntent = RouteIntentService.getIntentOfActionDoRoute(context, msg);
    PendingIntent pendingIntent = PendingIntent.getService(context, DEFAULT_SERVICE_REQUEST_CODE,
            startIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder =
            new NotificationCompat.Builder(context)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle(title)
                    .setContentText(content)
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent);

    NotificationManager notifyMgr =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    notifyMgr.notify(notificationTag, NOTIFICATION_ID, builder.build());
}

类RouteIntentService是继承IntentService的业务类,它响应所有来源(包括此处的通知)的路由命令。下面看它是如何工作的。

响应通知点击

在RouteIntentService.java中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RouteIntentService.onHandleIntent()
@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        final String action = intent.getAction();
        if (ACTION_DO_ROUTE.equals(action)) {
            BaseRouteMsg routeMsg = (BaseRouteMsg) intent.getSerializableExtra(EXTRA_ROUTE_MSG);
            handleActionDoRoute(routeMsg);
        }
    }
}

// RouteIntentService.onHandleIntent()
/**
 * 处理路由跳转命令
 * @param routeMsg
 */
private void handleActionDoRoute(BaseRouteMsg routeMsg) {
    boolean jumpDone = false;
    try {
        if (routeMsg != null) {
            jumpDone = RouterManager.navigate(this, routeMsg);
        }
    } catch (Exception e) {
    }

    if (!jumpDone) {
        RouterManager.openApp(this);
    }
}

从intent中获取到发送通知时设置的routeMsg,交给RouterManager去处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在RouterManager.navigate()
/**
 * 导航到目标界面
 *
 * @param msg 路由信息
 * @return 是否完成跳转
 */
public static boolean navigate(Context context, BaseRouteMsg msg) {
    BaseRouter router = RouteMap.getRouter(msg.getPath());

    if (router == null || !router.canJump(context)) {
        return false;
    }

    router.setRouteMsg(msg);
    return router.navigate(context);
}

调用RouteMap.getRouter()获取到对应routeMsg的处理器——router。 router.canJump()用来对当前导航做前置判断,默认返回true。 router.navigate(context)执行具体的跳转逻辑。

作为示例,文章详情界面的路由器如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ArticleDetailRouter extends BaseRouter<ArticleDetailMsg> {

    @Override
    public boolean navigate(Context context) {
        if (mRouteMsg == null) {
            return false;
        }
        ArticleDetailActivity.launchActivity(context, mRouteMsg.getArticleId());
        return true;
    }
}

小结

本文整理了实现“推送、通知、页面跳转”功能的一个简单设计。 Message+Handler模式是一个典型的编程模型。类似Task+Schedulers(异步任务+线程池)那样,体现一种数据和处理的分离思想。 如果后续有更多的关于推送、路由的要求,优先选择改进框架去满足一般需求。 面向抽象编程,不要直接对具体业务编程。

TODO:demo代码后续补上。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-04-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
【深度学习自动上色,数月工作几秒完成】开源神经网络图片上色技术解析
【新智元导读】本文是作者对Reddit社区用户Amir Avni深度学习上色机器人的实现,看完本文后,你也能打造媲美大师级着色效果的自动上色神经网络应用。此外,还有一个好处,即使失败了(例如本文头图,见上),你也可以说这是艺术:) 如今,上色都是人手工用Photoshop做的,一张图片要花好几个月才能完成,需要进行大量调查研究,光是其中的一张脸就需要多达20层图层。但是,基于深度神经网络的自动着色机器人,可以几秒钟就实现PS几个月的效果,而且成效越来越惊人。 下面,我们将分三个步骤展示如何打造你自己的着色神
新智元
2018/03/22
2K0
【深度学习自动上色,数月工作几秒完成】开源神经网络图片上色技术解析
用AI给黑白照片上色,复现记忆中的旧时光
【导读】我们知道,深度学习几乎已经应用在每一个领域,但如果我们能够构建一个基于深度学习的模型,让它能够给老照片着色,重现我们童年的旧回忆,这该多么令人激动啊!那么我们要怎么做呢?本文的作者将为大家介绍一个教程,通过深度学习方法为黑白老照片自动上色,带我们重新忆起那段老时光!
AI科技大本营
2018/09/28
1.9K0
用AI给黑白照片上色,复现记忆中的旧时光
keras学习笔记-黑白照片自动着色的神经网络-Alpha版
如今,上色都是人手工用Photoshop做的,一张图片要花好几个月才能完成,需要进行大量调查研究,光是其中的一张脸就需要多达20层图层。但是,基于深度神经网络的自动着色机器人,可以几秒钟就实现PS几个月的效果,而且成效越来越惊人。 下面,我们将分三个步骤展示如何打造你自己的着色神经网络。第一部分讲解核心逻辑。我们将构建一个40行代码的神经网络,作为“Alpha”着色机器人,这个代码片段实际上没有太多的魔法,但可以让你熟悉基本操作。 然后,我们将创建一个可以泛化的神经网络——“Beta”版本。Beta机器人能
用户1332428
2018/03/09
1.4K0
keras学习笔记-黑白照片自动着色的神经网络-Alpha版
教程 | 百行代码构建神经网络黑白图片自动上色系统
选自freecodecamp 作者:Emil Wallnér 机器之心编译 使用神经网络对图片进行风格化渲染是计算机视觉领域的热门应用之一。本文将向你介绍一种简单而有效的黑白图片上色方法,仅需 100 行代码,你也可以搭建自己的神经网络,几秒钟内让计算机自动完成手动工作需要几个月的任务。 今年 7 月,Amir Avni 用神经网络向 Reddit 的 Colorization 社区宣战——那是一个为历史黑白照片上色的版面,用户们通常使用的工具是 Photoshop。 社区用户们惊讶于 Amir 的深度
机器之心
2018/05/10
1.8K0
keras学习笔记-黑白照片自动着色的神经网络-Beta版
Alpha版本不能很好地给未经训练的图像着色。接下来,我们将在Beta版本中做到这一点——将上面的将神经网络泛化。 以下是使用Beta版本对测试图像着色的结果。 特征提取器 我们的神经网络要做的是发现
用户1332428
2018/03/09
7080
keras学习笔记-黑白照片自动着色的神经网络-Beta版
前端慌不慌?用深度学习自动生成HTML代码
选自Floydhub 作者:Emil Wallner 机器之心编译 如何用前端页面原型生成对应的代码一直是我们关注的问题,本文作者根据 pix2code 等论文构建了一个强大的前端代码生成模型,并详细解释了如何利用 LSTM 与 CNN 将设计原型编写为 HTML 和 CSS 网站。 项目链接:https://github.com/emilwallner/Screenshot-to-code-in-Keras 在未来三年内,深度学习将改变前端开发。它将会加快原型设计速度,拉低开发软件的门槛。 Tony Be
机器之心
2018/05/10
2K0
深度实践:如何用神经网络给黑白照片着色
现如今,将图片彩色化是通常用Photoshop处理的。一幅作品有时候需要用一个月的时间来着色。可能单单一张脸就需要20层的粉色、绿色和蓝色阴影才能让它看起来恰到好处。为了了解这一过程,你可以看看下面这
AiTechYun
2018/03/06
1.6K0
深度实践:如何用神经网络给黑白照片着色
深度学习第3天:CNN卷积神经网络
这张图显示了一个滤波器的某时刻的运作过程,最左边的是原图,中间是滤波器,最右边是结果,它会进行一个内积运算,图中也展示了这个过程
Nowl
2024/01/18
3030
深度学习第3天:CNN卷积神经网络
手把手搭建一个【卷积神经网络】
本文介绍卷积神经网络的入门案例,通过搭建和训练一个模型,来对10种常见的物体进行识别分类;使用到CIFAR10数据集,它包含10 类,即:“飞机”,“汽车”,“鸟”,“猫”,“鹿”, “狗”,“青蛙”,“马”,“船”,“卡车” ;共 60000 张彩色图片;通过搭建和训练卷积神经网络模型,对图像进行分类,能识别出图像是“汽车”,或“鸟”,还是其它。
一颗小树x
2021/05/12
1.5K0
手把手搭建一个【卷积神经网络】
换脸原理,使用GAN网络再造ZAO应用:可变自动编解码器基本原理
从本节开始,我们介绍一种人工智能实现无缝变脸的网络名为可变自动编解码器,英文名称:variational autoencoder。在前面章节中我们曾介绍过,很多事物看起来似乎很复杂,但只要抓住其关键变量,那就等同于抓住事物的本质,例如一个圆柱体,它的关键变量就是底部圆的半径,和高度,掌握了这两个变量的信息,我们可以轻易的将圆柱构造出来。
望月从良
2019/10/15
7980
换脸原理,使用GAN网络再造ZAO应用:可变自动编解码器基本原理
Lenet神经网络解读及其代码实现
  手写字体识别模型LeNet5诞生于1994年,是最早的卷积神经网络之一。LeNet5通过巧妙的设计,利用卷积、参数共享、池化等操作提取特征,避免了大量的计算成本,最后再使用全连接神经网络进行分类识别,这个网络也是最近大量神经网络架构的起点。虽然现在看来Lenet基本实际用处不大,而且架构现在基本也没人用了,但是可以作为神经网络架构的一个很好的入门基础。
墨明棋妙27
2022/08/24
4050
Lenet神经网络解读及其代码实现
TensorFlow快餐教程:程序员快速入门深度学习五步法
作者简介:刘子瑛,阿里巴巴操作系统框架专家;CSDN 博客专家。工作十余年,一直对数学与人工智能算法相关、新编程语言、新开发方法等相关领域保持浓厚的兴趣。乐于通过技术分享促进新技术进步。 作为一个程序员,我们可以像学习编程一样学习深度学习模型开发。我们以 Keras 为例来说明。 我们可以用 5 步 + 4 种基本元素 + 9 种基本层结构,这 5-4-9 模型来总结。 5步法: 1. 构造网络模型 2. 编译模型 3. 训练模型 4. 评估模型 5. 使用模型进行预测 4种基本元素:
用户1737318
2018/07/20
5360
基于卷积神经网络的垃圾分类
自今年7月1日起,上海市将正式实施 《上海市生活垃圾管理条例》。垃圾分类,看似是微不足道的“小事”,实则关系到13亿多人生活环境的改善,理应大力提倡。
云微
2023/02/11
9990
基于卷积神经网络的垃圾分类
拿来就能用!简单 Python 代码实现建筑识别
在人工智能的发展越来越火热的今天,其中最具有代表性的便是图像识别,其应用比比皆是,如车站的人脸识别系统,交通的智能监控车牌号系统等。卷积神经网络作为图像识别的首选算法,其对于图像的特征提取具有很好的效果,Keras 框架作为卷积神经网络的典型框架,可创建神经网络层,更容易提取图像特征,从而达到区分动物的目的,在生产实践中达到辅助的效果。
AI科技大本营
2021/02/05
1.5K0
【机器学习】神经网络的无限可能:从基础到前沿
在当今人工智能的浪潮中,神经网络作为其核心驱动力之一,正以前所未有的速度改变着我们的世界。从图像识别到自然语言处理,从自动驾驶到医疗诊断,神经网络的应用无处不在。本文旨在深入探讨神经网络的各个方面,从基础概念到最新进展,带领读者一窥其背后的奥秘与魅力。
破晓的历程
2024/08/20
3560
全网流行的黑白照片上色技术,看看飞桨开发者是如何实现的
我们都知道,有很多经典的老照片,受限于那个时代的技术,只能以黑白的形式传世。尽管黑白照片别有一番风味,但是彩色照片有时候能给人更强的代入感。本项目通过通俗易懂的方式简单实现黑白照片着色并对部分照片取得不错的着色效果。
用户1386409
2020/11/06
5990
全网流行的黑白照片上色技术,看看飞桨开发者是如何实现的
如何捕获一只彩色卓别林?黑白照片AI上色教程很友好 | 哈佛大触
方栗子 编译自 GitHub 量子位 出品 | 公众号 QbitAI △ 老照片的手动着色魔法 妈妈小时候已经有彩色照片了,不过那些照片,还是照相馆的人类手动上色的。 几十年之后,人们已经开始培育深度
量子位
2018/07/20
9420
越来越卷,教你使用Python实现卷积神经网络(CNN)
https://blog.csdn.net/weixin_44510615/article/details/117409037
润森
2022/09/22
2.9K0
越来越卷,教你使用Python实现卷积神经网络(CNN)
使用自动编解码器网络实现图片噪音去除
在前面章节中,我们一再看到,训练或使用神经网络进行预测时,我们需要把数据转换成张量。例如要把图片输入卷积网络,我们需要把图片转换成二维张量,如果要把句子输入LSTM网络,我们需要把句子中的单词转换成one-hot-encoding向量。
望月从良
2018/12/17
7750
使用神经网络解决拼图游戏
在一个排列不变性的数据上神经网络是困难的。拼图游戏就是这种类型的数据,那么神经网络能解决一个2x2的拼图游戏吗? 什么是置换不变性(Permutation Invariance)? 如果一个函数的输出
deephub
2020/08/04
1.6K0
使用神经网络解决拼图游戏
推荐阅读
相关推荐
【深度学习自动上色,数月工作几秒完成】开源神经网络图片上色技术解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验