Android RenderScript实现LowPoly效果

2024-03-16 02:10

本文主要是介绍Android RenderScript实现LowPoly效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今日科技快讯

近日,利用银行新规的诈骗手法已出现,大家要注意了!根据银行新规,在ATM机上转账时,除同行同户名的卡,其他均在24小时后才能到账,且24小时内可撤销转账!不法分子以“先转账、再取现”骗取受害者信任,在拿到现金后,便会前往柜台撤销转账!

有网友爆料称,前天一个陌生电话打来订货,不说要什么就说配5000块的货,发了ATM转账凭证过来,然后就不停催发货,打银行客服查询确实有这交易,不过还是多了心眼没发货,到今天了24小时钱也没到账,银行查询是该笔交易已撤销。

作者简介

新的一周开始了,又到了跟大家见面的时候!本篇是 reikyZ 的第二篇投稿,本文包含基本概念的讲解以及RenderScript的基本使用。如果看了本文对这个知识感兴趣的朋友可以访问作者博客,进行更深入的了解。

reikyZ 的博客地址:

http://www.jianshu.com/users/5bf423bcdb88

前言

之前在知乎看到一篇关于 LowPoly  js 实现的贴:

https://www.zhihu.com/question/29856775

觉得效果很棒,就打算在 Android 上实现看看。本来以为一两天就可以搞定,没想到不知不觉耗了一周多,踏坑不少。鉴于内容可能会比较多,所以暂时打算分篇幅介绍实现过程。

LowPoly (低多边形) 这种风格在前两年十分风靡,比较有名的《纪念碑谷》就是采用这种美术风格的游戏。

纪念碑谷

效果

LowPolyAndroid

https://github.com/zzhoujay/LowPolyAndroid

java cost time

这个是由 纯 java 实现的版本,在查找资料时找到的,应该是国内某人写的。用 Nexus5 测试,处理尺寸为 900 * 900 的 bitmap 图片耗时基本在 60~90 s 左右,可见效率确实比较不能忍受。从 Log 的计时器看,在处理两千不到的取样点的情况下,三角化和绘图耗时都在 1s 以内,所以估计主要耗时应该在 Sobel 边缘处理和点列采样的过程中,没有验证,有心的同学可以试试看。需要说明的是,我的实现使用了这位同学的 Delaunay 算法和 canvas 部分的代码(表示感谢!),所以在取样点差不多时,我的效果应该和这个差不多。

LowPoly

https://github.com/CoXier/LowPoly

jni cost time

这个是国外某位使用 jni 实现的版本,是在着手写该篇时才找到的,看到其介绍由 jni 实现,想必肯定会比 java 快,担心如果比 rs 实现快很多,也没必要写出来了。根据测试效果,明显比 java 实现快很多,处理同样的图片,用了7秒多,比 java 快了十倍左右。从效果图上来看,其边缘更加清晰,尖锐三角形也很多,风格与 java 实现的稍有不同,不过这些应该是因为使用不同的三角化算法导致,对耗时影响应该不大。


rs process(微信大小限制,图片压缩了)


rs cost time

最后是使用 RenderScript 实现的,为了方便描述实现过程 Demo 分步骤展示了主要的过程。处理同样的图片,通过计时器可以看到,总耗时大概在 2s以内,效率应该说还是比较能够让人接受的。正如前文提到的,使用了前文同学的 Delaunay 算法和 canvas 部分代码,所以风格应该差不多。不同的是,用 rs 处理了灰度、边缘化和采样的过程,大大节省了时间。

实现原理

根据知乎那个答案,这种效果主要有那么几个步骤:

 1. 首先将原图转为灰度图(不是必须);

 2. 使用灰度图(或原图)查找边缘,获得边缘线图;

 3. 从边缘线上采样,采样率决定后期三角的数量与图片精度;

 4. 使用上步骤得到的采样点列,生成三角化序列;

5. 遍历三角形,使用原图得到的色值填充三角形。

其中,在边缘检测上一般采用 Sobel 算法,即通过 sobel 算子计算某一点的梯度,可以简单理解为某一点与周围点灰度差异度;然后,在三角化处理上,一般采用 Delaunay 算法。

在实现方面,首先 jni 并不是一定会比 java 快的,使用 jni 一般是为了某些特定场景,其中图形处理所需要的大量数学运算就是其一,在 LowPoly 的代码中:

LowPoly.java


可见,除了取色、上色两个步骤,其他步骤都通过调用 native 的 getTriangles 方法处理,其中应该就是负责图形处理的大量运算。

对于 RenderScript,Google 这样描述:

RenderScript

https://developer.android.com/guide/topics/renderscript/compute.html

RenderScript is a framework for running computationally intensive tasks at high performance on Android. RenderScript is primarily oriented for use with data-parallel computation, although serial workloads can benefit as well. The RenderScript runtime parallelizes work across processors available on a device, such as multi-core CPUs and GPUs. This allows you to focus on expressing algorithms rather than scheduling work. RenderScript is especially useful for applications performing image processing, computational photography, or computer vision.

介绍了 RenderScript 主要基于多核 CPU 或者 GPU,主要是为了处理图形运算。早些时候,在手机处理器和图形处理器的性能普遍不高的情况下, rs 似乎并不太引人注意,从网络上少得可怜的资料就可以看出。不过,时至今日,各大手机厂商在硬件的堆砌上似乎一点也没有节制,以及 VR、 AR 等视觉技术的兴起,相信 rs 技术会有更多应用场景。

示例

Github-LowPoly

https://github.com/ReikyZ/LowPoly

基础
配置

app.gradle


RenderScript  在 Android 3.0(API 11)时首次被引入,包名为 android.renderscript;之后又添加了 Support Library android.support.v8.renderscript,最低可以兼容 Android 2.3 (API 9),SDK Tools Version 须要 22.2 及以上, Build Tools Version 须要 18.1 及以上。在应用的 .gradle 配置中需要加上蓝色的两行,以配置支持库。支持库与早先版本的 api 由较大的不同,所以下文都是以使用 Support Library 为基础。

文件目录

在 Android Studio 的 Project 视图中,在 main 目录下创建 rs 目录,用来存放 rs 脚本,在编写好脚本,经过编译后,会在 build  文件目录下分别生成  .bc 格式与 .java  文件,其中 .java 文件就是 .java 让我们可以对 rs 脚本进行反射调用。

语言

RenderScript 以 C99 作为开发语言,不支持调用 NDK 或 C 标准库的 API,但是提供了能够基本满足开发需要的 RenderScript API,包涵了丰富的基本数据类型,例如向量,矩阵,各种数学函数,具体可以参考官方文档。

使用流程

编写脚本

grayed.rs


pragma.rsh

#pragma version(1)
#pragma rs java_package_name(com.reikyz.renderscript)

对于 grayed.rs  这个脚本,首先需要添加两行包信息,这两行信息放在了 pragme.rsh 文件中引入,在有较多的脚本时,也可以把一些自定义的结构体或者函数,通过这样的方式引入,方便管理与复用。

在添加了包信息之后,我们就可以使用 rs 提供的一系列数据类型和函数,grayed.rs 这个脚本的效果是将一个图像灰度化。

调用

MainActivity.java


在编译后,我们就可以通过自动生成的 ScriptC_grayed.java  反射类对 rs 进行初始化和调用。

在 createRS 方法中,首先,获得一个 RenderScript 对象;

根据 bitmap 构建输入、输出的 Allocation 对象,对应 rs 脚本中的两个rs_allocation 对象,这两个对象的尺寸必须相同;

初始化 Grayed 脚本,至此都是一些准备工作;

调用 scriptGrayed.forEach_root(mInAllocation, mOutAllocation) 将分配的 allocation 传入, rs 执行 root 方法;

最后将生成的 输出 allocation 中的图像写入 bitmap 。

在 log 中可以注意到,在调用时 scriptGrayed.forEach_root 这个函数应该早于 “===Script root end===”这行 log 信息,实际却不是这样,因此,可以看出 rs 脚本的 root 方法并不在主线程中。

另外,java 中调用脚本的方式 scriptGrayed.forEach_root,为什么是 each_root 呢?

因为,root 还有一个重载方法 root(const uchar4 *v_in, uchar4 *v_out, uint32_t x, uint32_t y)

grayed.rs


在 grayed.rs 脚本中重载这个方法,需注意的是一个脚本只能重载一个 root 方法,否则编译时就会报错。

MainActivity.java


由于,重载包含坐标的 root 方法对 rs 脚本中的输入、输出 rs_allocation 进行操作,如果在 java 层不进行 set 操作的话,程序运行后会直接崩溃,且不会输出崩溃原因,所以编写 rs 脚本时,须要格外注意代码逻辑。


如图所示,重载的 root 方法很简单地实现了一个马赛克的图像效果。

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

这篇关于Android RenderScript实现LowPoly效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/813965

相关文章

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定