基于MapReduce对视频中的人数进行统计

104 views

查阅了很多资料,发现很少有在MapReduce平台上处理视频的,主要是因为有以下几个难点:

  1. HDFS中没有对视频格式支持。在HDFS中,主要的数据类型有IntWriteable、DoubleWriteble、Text、SequeceFile。如果你想支持其他类型的数据,那么你就需要自己定义Writeable,所以,你如果要处理视频,那么你就需要自己针对视频定义一个Writeable。
  2. 视频数据进行分块解析。一个视频10G,你把它分成128M一份,那你读取视频的时候该如何进行解码?
  3. 无法对数据进行按行处理。在Map过程中,通过对每一块的数据进行按行处理,来实现并行。但是视频保存在HDFS中是二进制文件,按行读取出来的数据有意义吗?
  4. 跨平台困难。Hadoop是基于JAVA开发的,理所当然的可以进行跨平台的操作,然而对视屏进行解析的依赖包如Opencv、Javacv、FFMPEG,这些都不是省油灯。这些包大多无法进行跨平台,这就意味着你运行代码的每一台机器上面都要配置相应的环境。

那怎么搞?没搞头?对于当前的问题,无法解决就选择接受,有办法解决就去解决。基于此,针对视频中的人数统计功能,我设计了如下的解决方法:

视频识别人数解决方法

首先我们在本地将视屏切割成一帧一帧的图片,同时生成时间戳文件。时间戳文件记载每张图片所在的时间,图片的路径、图片的宽度和图片的高度。在本地生成图片和时间戳文件的同时,我们可以将文件上传至HDFS。这样针对视频的处理,变成了针对时间戳文件的处理。

第二步,对于时间戳文件的每一行记录:<时间点,文件名,图片宽度,图片高度>可以直接作为Map的输入,因此,每个Map处理一张图片。如何得到图片中的人头数量?简单就是识别图片中的人脸数量,用Opencv就好,虽然不得不吐槽Opencv跨平台是个坑,需要手动配置链接库,但是没办法啊,基本上java所有的CV库都用到了Opencv,JavaCV也不例外。利用Opencv的人脸检测,我们可以得到图片中的人脸数量,就是当前时刻的人头的数量,从而输出<时间,人头数>作为Reduce的输入。

第三步:Reduce会得到同一时间单位,如一秒内的人头数迭代器,也就是<时间, Interator<人头数>>。我们假设在单位时间内人头的数量不会有太大的变化,因此,我们对迭代器里面的人头取平均,就可以得到当前单位时间的人头数量。

经过上述三步,我们就可以获得视频中的人头数量。不过上述解决办法是有缺陷的:

  • 图片数据一般比较小,不利于HDFS大数据处理的优势。
  • Opencv跨平台一个永远的坑。
  • 本地视频视屏切割是速度的瓶颈,导致不能实现流处理。

有兴趣的话,可以看一下代码链接:
https://gitee.com/chashuju/derfei

最后想了一想,人数统计根本用不到视频,用WIFI探针就好了,毕竟一人一个手机,简单,高效。好吧,又白干了。

Rating: 5.0/5. From 1 vote.
Please wait...