前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第五课:推理结果的可视化

第五课:推理结果的可视化

作者头像
刘盼
发布2018-03-16 11:56:05
8260
发布2018-03-16 11:56:05
举报
文章被收录于专栏:人人都是极客

处理推理结果

在上一课时中,已经通过 Inference 获取到了识别结果,存放在三个数组里:

代码语言:javascript
复制
    float[] boxes = new float[100 * 4];
    float[] scores = new float[100];
    float[] classes = new float[100];

那么数据的结构是这样的,第一个识别物体的类别是 classes[0],分数为 scores[0],物体的位置(top、left、bottom、right)为(boxes[0]、boxes[1]、boxes[2]、boxes[3])依次类推。 但是要注意的是物体的位置的值是 Normalized 的,还需要特殊处理一下。

Normalize 也叫标准化、正则化,或者归一化,是机器学习中的一个重要概念,在这里不做更多的深入的探讨,只需要记住它的作用是把一个数值按照一定算法投影到(0,1] 这个区间里面,这是一个在机器学习中会经常碰到的术语。

因为物体位置的数值是 Normalized 的,它们都是(0,1]区间里面的小数,而我们输入的图片是 300×300 的尺寸,所以需要把这些值都乘以 300 来获取它在图片里面的真实位置。那么现在可以得出,在输出数据中第 i(i 从 0 开始)个识别得物体的数据为:

  • 分数: scores[i]
  • 物体名称: labels[classes[i]] (labels 为之前从labels.txt中读取的标签数组)
  • 物体位置:(boxes[i] * 300, boxes[i + 1] * 300, boxes[i+ 2] * 300, boxes[i + 3] *300)

接下来我们需要把得分低的输出项剔除掉,这个分数是(0,1]之间的一个数(看,也是 Normalized 的),越高越好。如果模型推理出来一个物体是人,但是得分只有 0.1,那么实际上有可能这个物体不是人。所以我们需要有一个分数的阈值,大于这个阈值的识别结果才被认为是正确的。这个阈值的选择是一个经验问题,在这里选择 0.6 作为分数的阈值,这样就把那些我们认为识别度不够的结果排除了。同时之前为 100 个识别结果分配了存储空间,如果识别结果中的物体小于 100,那么有一些数组元素就是空值(0),这样的话我们把这些空值也排除掉了。

接下来就开始写代码了,在这里写了一个类来封装识别的结果:

代码语言:javascript
复制
    public class DetectionResult {
       private String label;
       private Float score;
       private RectF box;
       public DetectionResult(String label, Float score, RectF location) {
        this.label = label;
        this.score = score;
        this.box = location;
       }
       public String getLabel() {
        return label;
       }
       public Float getScore() {
        return score;
       }
       public RectF getBox() {
        return box;
       }
    }

这个类代表一个单独的被识别出来的物体,接下来根据识别结果来生成 DetectionResult 的 List:

代码语言:javascript
复制
    List<DetectionResult> results = new ArrayList<>();
    for (int i = 0; i < classes.length; i++) {
         if (scores[i] > 0.6f) {
              RectF box = new RectF(
                     boxes[4 * i + 1] * 300,
                     boxes[4 * i] * 300,
                     boxes[4 * i + 3] * 300,
                     boxes[4 * i + 2] * 300);
              results.add(new DetectionResult(labels.get((int) classes[i]), scores[i], box));
            }
    }

注意,RectF 构造函数接受的参数是(left、top、right、bottom),而我们 boxes 数组中的位置是(top、left、bottom、right),传参的时候顺序不要弄错了。

推理结果的可视化

现在有了识别物体的位置和名称,我们只需要在原始图片的相应位置上面画上边框,写上名称就可以啦!

首先将原始图片 copy 一份,然后在这个 copy 上面画上边框,写上名称:

代码语言:javascript
复制
final Bitmap copiedImage = originImage.copy(Bitmap.Config.ARGB_8888, true);

获取 Canvas 对象,设置边框的宽度和颜色,设置显示名称的字体大小和颜色:

代码语言:javascript
复制
    final Canvas resultCanvas = new Canvas(copiedImage);
    final Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(5.0f);
    Paint textPaint = new Paint();
    textPaint.setColor(Color.WHITE);
    textPaint.setStyle(Paint.Style.FILL);
    textPaint.setTextSize((float) (0.04 * copiedImage.getWidth()));

在往 Canvas 上面画图之前,不要忘了输入给模型的是一个根据原始图片经过转换而得到的 300×300 的图片,所以我们识别结果里面的位置指的是物体在这个 300×300 的图片上的位置,如果把这个位置画在原图上面,显然是不正确的。

还记得之前我们转换原始图片时是使用一个矩阵(Matrix)来转换的吗? 现在只需要把这个矩阵 Invert 一下,然后再在我们识别出来物体的位置矩形上面用这个矩阵进行转换,就可以得到物体在原始图片上的位置了!代码如下:

代码语言:javascript
复制
    Matrix inputToOrigin = new Matrix();
    originToInput.invert(inputToOrigin);

获取 Invert 的矩阵之后,就可以依次把识别结果在原图上用方块标识出来了:

代码语言:javascript
复制
    for (DetectionResult result : results) {
        RectF box = result.getBox();
        inputToOrigin.mapRect(box);
        resultCanvas.drawRect(box, paint); 
        resultCanvas.drawText(result.getLabel(), box.left, box.top, textPaint);                               
    }

使用 mapRect 方法对矩形框进行转换,同时在框的左上角写上物体的名称,然后调用:

代码语言:javascript
复制
imageView.setImageBitmap(copiedImage);

将结果显示在 ImageView 上面。

效果展示

这样就完成了任务,没有任何机器学习基础的我们在 Android 上面实现了一个可以识别静态图片中的物体的应用,来看一下效果吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人人都是极客 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 处理推理结果
  • 推理结果的可视化
  • 效果展示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档