Skip to content

Commit 8f97b36

Browse files
committed
add DJL 3 article
1 parent e1b8058 commit 8f97b36

File tree

2 files changed

+40
-43
lines changed

2 files changed

+40
-43
lines changed

Diff for: contents/Java/DJL/3/0.gif

1.33 MB
Loading

Diff for: contents/Java/DJL/3/content.md

+40-43
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
# 用PyTorch和DJL做涂鸦识别的小游戏
1+
# 用 Java 做个“你画手机猜”的小游戏
22

33
> 本文适合有 Java 基础的人群
44
5-
![](https://raw.githubusercontent.com/aws-samples/djl-demo/master/android/img/rabbit.gif)
5+
![](0.gif)
66

77
作者:**DJL-Lanking**
88

99
HelloGitHub 推出的[《讲解开源项目》](https://github.com/HelloGitHub-Team/Article)系列。有幸邀请到了亚马逊 + Apache 的工程师:Lanking( https://github.com/lanking520 ),为我们讲解 DJL —— 完全由 Java 构建的深度学习平台,本文为系列的第三篇。
1010

1111
## 一、前言
1212

13-
在2018年时,Google 推出了《猜画小歌》应用:玩家可以直接与AI进行你画我猜的游戏。通过画出一个房子或者一个猫,AI 会推断出各种物品被画出的概率。它的实现得益于深度学习模型在其中的应用,通过深度神经网络的归纳,曾经令人头疼的绘画识别也变得易如反掌。现如今,只要使用一个简单的图片分类模型,我们便可以轻松的实现绘画识别。试试看这个在线涂鸦小游戏吧:
13+
在 2018 年时,Google 推出了《猜画小歌》应用:玩家可以直接与 AI 进行你画我猜的游戏。通过画出一个房子或者一个猫,AI 会推断出各种物品被画出的概率。它的实现得益于深度学习模型在其中的应用,通过深度神经网络的归纳,曾经令人头疼的绘画识别也变得易如反掌。现如今,只要使用一个简单的图片分类模型,我们便可以轻松的实现绘画识别。试试看这个在线涂鸦小游戏吧:
1414

1515
> 在线涂鸦小游戏:https://djl.ai/website/demo.html#doodle
1616
17-
在当时,大部分机器学习计算任务仍旧需要依托网络在云端进行。随着算力的不断增进,机器学习任务已经可以直接在边缘设备部署,包括各类运行安卓系统的智能手机。但是,由于安卓本身主要是用 Java ,部署基于 Python 的各类深度学习模型变成了一个难题。为了解决这个问题,AWS开发并开源了 DeepJavaLibrary (DJL),一个为 Java 量身定制的深度学习框架。
17+
在当时,大部分机器学习计算任务仍旧需要依托网络在云端进行。随着算力的不断增进,机器学习任务已经可以直接在边缘设备部署,包括各类运行安卓系统的智能手机。但是,由于安卓本身主要是用 Java ,部署基于 Python 的各类深度学习模型变成了一个难题。为了解决这个问题,AWS 开发并开源了 DeepJavaLibrary (DJL),一个为 Java 量身定制的深度学习框架。
1818

19-
在这个文章中,我们将尝试通过PyTorch预训练模型在在安卓平台构建一个涂鸦绘画的应用。由于总代码量会比较多,我们这次会挑重点把最关键的代码完成。你可以后续参考我们完整的项目进行构建。
19+
在这个文章中,我们将尝试通过 PyTorch 预训练模型在安卓平台构建一个涂鸦绘画的应用。由于总代码量会比较多,我们这次会挑重点把最关键的代码完成。你可以后续参考我们完整的项目进行构建。
2020

2121
> 涂鸦应用完整代码:https://github.com/aws-samples/djl-demo/tree/master/android
2222
@@ -41,27 +41,27 @@ dependencies {
4141

4242
## 三、构建应用
4343

44-
### 第一步:创建Layout
44+
### 3.1 第一步:创建 Layout
4545

46-
我们可以先创建一个 View class 以及 layout (如下图)来构建安卓的前端显示界面。
46+
我们可以先创建一个 View class 以及 layout(如下图)来构建安卓的前端显示界面。
4747

4848
![](1.png)
4949

50-
如上图所示,你可以在主界面创建两个 `View` 目标。 `PaintView` 是用来让用户画画的,在右下角 `ImageView` 是用来展示用于深度学习推理的图像。同时我们预留一个按钮来进行画板的清空操作。
50+
如上图所示,你可以在主界面创建两个 `View` 目标。`PaintView` 是用来让用户画画的,在右下角 `ImageView` 是用来展示用于深度学习推理的图像。同时我们预留一个按钮来进行画板的清空操作。
5151

52-
### 第二步: 应对绘画动作
52+
### 3.2 第二步: 应对绘画动作
5353

5454
在安卓设备上,你可以自定义安卓的触摸事件响应来应对用户的各种触控操作。在我们的情况下,我们需要定义下面三种时间响应:
5555

56-
* touchStart: 感应触碰时触发
57-
* touchMove: 当用户在屏幕上移动手指时触发
58-
* touchUp: 当用户抬起手指时触发
56+
* touchStart感应触碰时触发
57+
* touchMove当用户在屏幕上移动手指时触发
58+
* touchUp当用户抬起手指时触发
5959

6060
与此同时,我们用 paths 来存储用户在画板所绘制的路径。现在我们看一下实现代码。
6161

62-
#### 重写 `OnTouchEvent``OnDraw` 方法
62+
#### 3.2.1 重写 `OnTouchEvent``OnDraw` 方法
6363

64-
现在我们重写 `onTouchEvent` 来应对各种响应:
64+
现在我们重写 `onTouchEvent` 来应对各种响应
6565

6666
```java
6767
@Override
@@ -91,7 +91,7 @@ public boolean onTouchEvent(MotionEvent event) {
9191

9292
如上面代码所示,你可以添加一个 `runInference` 方法在 `MotionEvent.ACTION_UP` 事件响应上。这个方法是用来在用户绘制完后对结果进行推理。在之后的几步中,我们会讲解它的具体实现。
9393

94-
我们同样需要重写 `onDraw` 方法来展示用户绘制的图像:
94+
我们同样需要重写 `onDraw` 方法来展示用户绘制的图像
9595

9696
```java
9797
@Override
@@ -111,7 +111,7 @@ protected void onDraw(Canvas canvas) {
111111

112112
真正的图像会保存在一个 `Bitmap` 上。
113113

114-
#### touchStart
114+
#### 3.2.2 操作开始(touchStart
115115

116116
当用户触碰行为开始时,下面的代码会建立一个新的路径同时记录路径中每一个点在屏幕上的坐标。
117117

@@ -126,11 +126,11 @@ private void touchStart(float x, float y) {
126126
}
127127
```
128128

129-
#### touchMove
129+
#### 3.2.3 手指移动(touchMove
130130

131131
在手指移动中,我们会持续记录坐标点然后将它们构成一个 quadratic bezier. 通过一定的误差阀值来动态优化用户的绘画动作。只有差别超出误差范围内的动作才会被记录下来。
132132

133-
> quadratic bezier 文档: https://developer.android.com/reference/android/graphics/Path#quadTo(float,%20float,%20float,%20float)
133+
> quadratic bezier 文档: https://developer.android.com/reference/android/graphics/Path
134134
135135
```java
136136
private void touchMove(float x, float y) {
@@ -148,7 +148,7 @@ private void touchMove(float x, float y) {
148148
}
149149
```
150150

151-
#### touchUp
151+
#### 3.2.4 操作结束(touchUp
152152

153153
当触控操作结束后,下面的代码会绘制一个路径同时计算最小长方形目标框。
154154

@@ -159,31 +159,31 @@ private void touchUp() {
159159
}
160160
```
161161

162-
### 第三步: 开始推理
162+
### 3.3 第三步:开始推理
163163

164164
为了在安卓设备上进行推理任务,我们需要完成下面几个任务:
165165

166-
* 从URL读取模型
166+
* 从 URL 读取模型
167167
* 构建前处理和后处理过程
168168
* 从 PaintView 进行推理任务
169169

170-
为了完成以下目标,我们尝试构建一个 `DoodleModel` class 。在这一步,我们将介绍一些完成这些任务的关键步骤。
170+
为了完成以下目标,我们尝试构建一个 `DoodleModel` class。在这一步,我们将介绍一些完成这些任务的关键步骤。
171171

172-
#### 读取模型
172+
#### 3.3.1 读取模型
173173

174-
DJL内建了一套模型管理系统。开发者可以自定义储存模型的文件夹。
174+
DJL 内建了一套模型管理系统。开发者可以自定义储存模型的文件夹。
175175

176176
```java
177177
File dir = getFilesDir();
178178
System.setProperty("DJL_CACHE_DIR", dir.getAbsolutePath());
179179
```
180180

181-
通过更改 `DJL_CACHE_DIR` 属性, 模型会被存入相应路径下.
181+
通过更改 `DJL_CACHE_DIR` 属性模型会被存入相应路径下
182182

183-
下一步可以通过定义 Criteria 从指定 URL 处下载模型. 下载的 zip 文件内包含:
183+
下一步可以通过定义 Criteria 从指定 URL 处下载模型下载的 zip 文件内包含
184184

185-
* doodle_mobilenet.pt: PyTorch 模型
186-
* synset.txt: 包含分类任务中所有类别的名称
185+
* `doodle_mobilenet.pt`PyTorch 模型
186+
* `synset.txt`包含分类任务中所有类别的名称
187187

188188
```java
189189
Criteria<Image, Classifications> criteria =
@@ -194,9 +194,9 @@ Criteria<Image, Classifications> criteria =
194194
.build();
195195
return ModelZoo.loadModel(criteria);
196196
```
197+
上述代码同时定义了 translator,它会被用来做图片的前处理和后处理。
197198

198-
上述代码同时定义了 translator 。translator 会被用来做图片的前处理和后处理。
199-
最后,如下述代码创建一个 `Model` 并用它创建一个 `Predictor`:
199+
最后,如下述代码创建一个 `Model` 并用它创建一个 `Predictor`
200200

201201
```java
202202
@Override
@@ -212,13 +212,13 @@ protected Boolean doInBackground(Void... params) {
212212
}
213213
```
214214

215-
更多关于模型加载的信息,请参阅如何加载模型.
215+
更多关于模型加载的信息,请参阅如何加载模型
216216

217-
> DJL模型加载文档: http://docs.djl.ai/docs/load_model.html
217+
> DJL 模型加载文档:http://docs.djl.ai/docs/load_model.html
218218
219-
#### 用Translator定义前处理和后处理
219+
#### 3.3.2 用 Translator 定义前处理和后处理
220220

221-
在DJL中, 我们定义了 Translator 接口进行前处理和后处理。在 DoodleModel 中我们定义了 ImageClassificationTranslator 来实现 Translator:
221+
在 DJL 中,我们定义了 Translator 接口进行前处理和后处理。在 DoodleModel 中我们定义了 ImageClassificationTranslator 来实现 Translator
222222

223223
```java
224224
ImageClassificationTranslator.builder()
@@ -227,12 +227,11 @@ ImageClassificationTranslator.builder()
227227
.optApplySoftmax(true).build());
228228
```
229229

230-
下面我们详细阐述 translator 所定义的前处理和后处理如何被用在模型的推理步骤中。当你创建 translator 时,内部程序会自动加载 `synset.txt` 文件得到做分类任务时所有类别的名称。当模型的predict()方法被调用时,内部程序会先执行所对应的 translator 的前处理步骤,而后执行实际推理步骤,最后执行 translator 的后处理步骤。对于前处理,我们会将 Image转化NDArray,用于作为模型推理过程的输入。对于后处理,我们对推理输出的结果(NDArray)进行 softmax 操作。最终返回结果为 Classifications 的一个实例。
231-
更多关于 translator 的工作原理以及如何个性化 Translator 的信息,请参阅 Inference with your model。
230+
下面我们详细阐述 translator 所定义的前处理和后处理如何被用在模型的推理步骤中。当你创建 translator 时,内部程序会自动加载 `synset.txt` 文件得到做分类任务时所有类别的名称。当模型的 `predict()` 方法被调用时,内部程序会先执行所对应的 translator 的前处理步骤,而后执行实际推理步骤,最后执行 translator 的后处理步骤。对于前处理,我们会将 Image 转化 NDArray,用于作为模型推理过程的输入。对于后处理,我们对推理输出的结果(NDArray)进行 softmax 操作。最终返回结果为 Classifications 的一个实例。
232231

233-
> 自定义Translator案例: http://docs.djl.ai/jupyter/pytorch/load_your_own_pytorch_bert.html
232+
> 自定义 Translator 案例:http://docs.djl.ai/jupyter/pytorch/load_your_own_pytorch_bert.html
234233
235-
#### 用 PaintView 进行推理任务
234+
#### 3.3.3 用 PaintView 进行推理任务
236235

237236
最后,我们来实现之前定义好的 runInference 方法。
238237

@@ -262,13 +261,13 @@ public void runInference() {
262261

263262
恭喜你!我们完成了一个涂鸦识别小程序!
264263

265-
### 可选优化: 输入裁剪
264+
### 3.4 可选优化:输入裁剪
266265

267266
为了得到更高的模型推理准确度,你可以通过截取图像来去除无意义的边框部分。
268267

269268
![](3.png)
270269

271-
上面右侧的图片会比左边的图片有更好的推理结果,因为它所包含的空白边框更少。你可以通过 Bound 类来寻找图片的有效边界,即能把图中所有白色像素点覆盖的最小矩形。在得到x轴最左坐标,y轴最上坐标,以及矩形高度和宽度后,就可以用这些信息截取出我们想要的图形(如右图所示)实现代码如下:
270+
上面右侧的图片会比左边的图片有更好的推理结果,因为它所包含的空白边框更少。你可以通过 Bound 类来寻找图片的有效边界,即能把图中所有白色像素点覆盖的最小矩形。在得到 x 轴最左坐标,y 轴最上坐标,以及矩形高度和宽度后,就可以用这些信息截取出我们想要的图形(如右图所示)实现代码如下:
272271

273272
```java
274273
RectF bound = maxBound.getBound();
@@ -294,6 +293,4 @@ Deep Java Library (DJL) 是一个基于 Java 的深度学习框架,同时支
294293

295294
它同时拥有着强大的模型库支持:只需一行便可以轻松读取各种预训练的模型。现在 DJL 的模型库同时支持高达 70 个来自 GluonCV、 HuggingFace、TorchHub 以及 Keras 的模型。
296295

297-
> 项目地址:https://github.com/awslabs/djl/
298-
299-
在最新的版本中 DJL 0.7.0 添加了对于 MXNet 1.7.0、PyTorch 1.6.0、TensorFlow 2.3.0 的支持。我们同时也添加了 ONNXRuntime 以及 PyTorch 在安卓平台的支持。
296+
> 项目地址:https://github.com/awslabs/djl/

0 commit comments

Comments
 (0)