人脸识别卡顿优化

2,290 阅读3分钟

前言

最近公司的应用需要接入人脸识别功能,经过筛选,选择了虹软的人脸识别SDK。本文以虹软android SDK 3.0版本为基础,记录一下卡顿的解决过程,这里先感谢一下虹软的工程师,在解决的过程中帮了我很多忙。

问题

下载虹软官方demo测试,使用手机摄像头进行人脸识别,在人脸超过20人时,移动手机,相机有明显的卡顿的现象。

分析

卡顿的原因一般有如下可能:

  1. 主线程任务过多,阻塞导致卡顿
  2. CPU中任务过多,影响了主线程
  3. 内存抖动严重,频繁的gc

对以上原因一一分析:

  1. demo中调用人脸识别的方法是在主线程中进行的,人脸少的时候,不存在卡顿现象,人脸多的时候,卡顿现象出现。猜测可能和人脸识别中的方法有关,人脸过多时导致人脸追踪耗时增加,从而引起了卡顿。
  2. 通过命令行监控手机CPU的使用现象,在人脸少与人脸多的情况下都是20%左右,CPU并没有占用过多,所以这里不是导致卡顿的原因。
  3. 通过检测人脸识别时的log,应用程序并没有频繁的gc,所以这里也不是导致卡顿的现象。

经过以上的分析,总结一下,卡顿的原因是因为人脸过多时导致人脸追踪耗时增加而导致的,所以我们从这个方法入手想解决方案。

解决方案

既然是因为主线程的任务过多,阻塞导致了卡顿,那太简单了,我们把人脸识别的方法放在线程里面跑不就行了吗,so easy!!!修改代码后再次运行,卡顿现象消失了。

但是新的问题又出现了,人脸框一直在闪烁,体验非常不好。经过分析代码,发现之前的demo中程序是这么走的:

  1. 清除人脸框的操作
  2. 进行人脸识别
  3. 绘制新的人脸框

这样操作在主线程中没有问题,但是我们现在把人脸识别放在了子线程中运行,这样就导致了在清除人脸框后,没有及时绘制新的人脸框,导致了闪烁的现象出现。所以这里我们把清除人脸框的操作放在绘制新的人脸框之前来做:

  1. 先在子线程中进行人脸识别
  2. 回到主线程中,清除人脸框
  3. 绘制新的人脸框

修改后测试,闪烁问题修复了。

但是但是又有新问题出现了,人脸识别长时间后程序会异常闪退,经过分析log,是oom,我们现在来分析解决下oom的问题。

OOM分析

由于相机视频数据帧一直不断在向线程池中添加新的的任务,时间长了,来不及处理这些任务,就会导致内存溢出。因此我们这里选择线程池的执行策略,当任务队列满时,扔掉最先进入队列的任务,这样就不会导致内存溢出。贴段代码:

    int corePoolSize = 1;
    int maxPoolSize = 1;
    long keepAliveTime = 5;
    BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);
    //拒绝策略1:将抛出 RejectedExecutionException.
    RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
    ThreadPoolExecutor executor;
    
    private void initExecutor(){
        executor = new ThreadPoolExecutor

                (corePoolSize, maxPoolSize,

                        keepAliveTime, TimeUnit.SECONDS,

                        queue, handler);
    }

这里线程池中只有一个线程在处理人脸识别,任务队列我这里设置的10个,超出时就会抛出。经过测试,解决了oom的问题。

以上就是这次虹软人脸识别sdk中卡顿优化过程。有任何错误,欢迎大家指正。