Java版人脸跟踪三部曲之二:开发设计

这篇具有很好参考价值的文章主要介绍了Java版人脸跟踪三部曲之二:开发设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如何开发Java版人脸跟踪应用?本篇给出了设计大纲,并解释了相关的重要知识点

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本篇是《Java版人脸跟踪三部曲》系列的第二篇,前文体验了人脸跟踪的效果,想要编码实现这样的效果,咱们需要做好设计工作,也就是本篇的任务
  • 本篇主要包含以下内容:
  1. 核心逻辑
  2. 重要知识点:HSV、HUE
  3. 重要知识点:反向投影
  4. 重要知识点:CamShift
  5. 重要知识点:JavaCV的API支持
  6. 如何开局?
  7. 前文的完整功能分析
  8. 异常处理
  9. 期待下一篇的实战

核心逻辑

  • 本篇没有编码和操作实战,会略显枯燥,所以提前小结人脸跟踪核心逻辑,如此就算您受不了欣宸的啰嗦提前关闭网页,好歹也能带走些干货:
  • 如下图所示,人脸跟踪的核心逻辑,其实就是先拿人脸直方图hist,然后将每一帧都转为hist的概率分布图(也叫反向投影),再用MeanShift算法在图上做迭代计算,结果就是人脸位置:
    Java版人脸跟踪三部曲之二:开发设计
  • 拿到每一帧的人脸位置后,在人脸上添加一个矩形框,此时,在预览窗口看到的效果就是视频中人脸上始终有矩形框,实现了跟踪的效果
  • 虽然尽可能简短的讲完了核心逻辑,但此时的您可能有一些疑问,例如:
  1. Hue分量是啥?
  2. 反向投影是啥?
  3. MeanShift又是啥?
  4. 前文提到过CamShift,这会儿咋又不提了?
  • 没错,上面几个疑问就是人脸跟踪功能依赖的关键技术,接下来咱们都简单了解一下吧

重要知识点:HSV、HUE

  • HSV:如下图,HSV是一种直观的颜色空间,把色调分布到一个圆盘上,Hue表示角度,所以Hue的值就代表一个具体的色调,然后,Saturation看做饱和度(我的感觉是添加黑色),把Value看做亮度(我的感觉是添加白色),刚才提到的Hue分量,其实就是指Hue的值,(Saturation和Value的值在后面的算法中不会用到)
    Java版人脸跟踪三部曲之二:开发设计
  • 再来仔细看看圆盘中Hue的值对应的色调:
    Java版人脸跟踪三部曲之二:开发设计

重要知识点:反向投影

  • 在使用JavaCV的CamShift算法API时,最重要的入参就是反向投影,每一帧最终都会被转成反向投影,也就是前面提到的用人脸Hue分量的直方图将第X帧转化成色彩概率分布图
  • 反向投影图是用输入图像的某一位置上像素值(多维或灰度)对应在直方图的一个bin上的值来代替该像素值
  • 反向投影在OpenCV中会经常见到,一般使用场景是在一个图像中查找特定图像的最匹配点或区域,或者说定位目标图像出现在指定图像的位置
  • 来看看用一张图片制作反向投影的过程,如下所示,先根据人脸得到直方图,然后对每一张图片都用这个直方图去计算出反向投影图(也就是拿着人脸直方图,去每一帧图片中计算人脸在此图片中的色彩概率分布),JavaCV为我们准备好了API(Imgproc.calcBackProject),我们只需准备好API所需参数即可:
    Java版人脸跟踪三部曲之二:开发设计
  • 有了上面的流程,就能对每帧图片做反向投影,得到人脸在这张图片上的概率分布图,然后用MeanShitf算法对这个概率分布图做迭代计算,直到其收敛或者到达最大迭代次数,确定人脸在图片上的位置

重要知识点:CamShift算法

  • 实现人脸跟踪的关键是CamShift,全称ContinuouslyAdaptive Mean Shift,即连续自适应的MeanShift算法
  • Mean Shift算法是一种无参密度估计算法,不需要任何先验知识而完全依靠特征空间中样本点的计算其密度函数值,在很多领域都有成功应用,例如图像平滑、图像分割、物体跟踪等,本篇不会展开细说Mean Shift算法,就用下面这幅图简单说说,
    Java版人脸跟踪三部曲之二:开发设计
  1. 上图每个圆心是一个质心,
  2. 以质心为原点画一个圆圈,圆圈内有很多红点
  3. 圆圈内每个点与圆心构成一个向量,把圆圈内向量相加,得到新的向量就是meanshift向量,即黄色箭头
  4. 以meanshift向量的重点为圆心,再画一个圆圈,在此圆圈内执行步骤3
  5. 不断重复上述过程,着该向量移动便能找到密度最大处,就是最终结果
  • 向量-> 移动 -> 向量 -> 移动,这和梯度下降有些相似之处啊
  • 以上就是meanshif算法,而将meanshift算法扩展到连续图像序列,就是camshift,它将视频的连续帧做meanshift
    计算,用上一帧结果作为下一帧meanshift算法搜索窗的初始值,来调整下一帧的中心位置和窗体大小,如此迭代下去,就可以实现对目标的跟踪。
  • 对应到OpenCV的实现中,就是输入一个图像(probImage),再输入一个开始迭代的窗口(window),以及迭代条件(criteria),而输出,就是迭代完成的位置(RotatedRect);

重要知识点:JavaCV对CamShift的支持

  • 关于核心功能的理论已经聊得七七八八了,再来看看JavaCV对核心知识点提供了哪些具体的API支持,如下表所示,前面涉及到的关键技术都覆盖到了:
序号 API 作用
1 Imgproc.cvtColor 从摄像头拿到的帧,其颜色空间是RGB格式的,需要转为HSV格式
2 Core.mixChannels 将HSV图片的Hue分量提取到另一个Mat中
3 Imgproc.calcHists 生成直方图
4 Imgproc.calcBackProject 生成反向投影
5 Video.CamShift 在反向投影图上执行CamShift计算
  • 至此,核心技术算是分析完了,但仅有核心技术是不够的,需要有主程序、分支逻辑、异常处理等诸多努力,才能实现完整的功能,接下来就以开发者的视角,开始咱们的开发设计
  • 首先要搞清楚的是:如何确定最初的那个人脸?

如何开局?

  • 在设计过程中,咱们要面临的第一个问题就是如何开局?换句话说:从哪里拿到人脸,用于生成直方图,并找好位置作为下一帧做CamShift计算的起始位置
  • 如果您之前在网上搜索过CamShift的文章,会发现大多都是用户用鼠标在预览窗口选定一个区域,然后程序取这个区域作为跟踪对象
  • 但是,欣宸这里不会沿用上述手动选择的方式,如果您之前看过《JavaCV的摄像头实战》系列,会发现该系列经常用到JavaCV提供的人脸检测功能,因此,咱们继续使用这个人脸检测功能来开局
  • 简单来说,当程序运行后,如果摄像头中出现了人脸,那么该人脸就被自动作为跟踪对象,会被计算Hue直方图,并且人脸位置也是下一帧做CamShift计算的起始位置
  • 为了简单起见,假设摄像头中只会出现一个人脸,代码处理也只针对一个人脸的场景
  • 如果您想了解人脸检测的更多细节,请参考《JavaCV的摄像头实战之八:人脸检测》

前文的完整功能分析(重要)

  • 咱们在前文体验的是一个功能完整的java应用,为了编码实现这个应用,自然是要先分析一下这个应用的主要流程
  • 来看看完整的应用主流程,如下图,检测到人脸后,就用此人脸生成直方图,对之后的每一帧都用反向投影+CamShift计算人脸位置,如果位置有效就表示跟踪成功,在图上添加矩形框,如果位置无效,表示跟踪失败(例如人已经离开摄像头),此时再不断的检测每一帧有没有人脸,一旦检测到,就重复前面的直方图和CamShift计算逻辑:
    Java版人脸跟踪三部曲之二:开发设计
  • 以上就是主流程了,也就是大部分时间中应用的运行状态,相信此刻的您已经受够了这些文字和图表,迫不及待的想要敲打键盘,写出自己心目中的人脸跟踪应用,但我还是要强行劝您一句:咱们把异常流程也梳理和罗列一下,否则程序运行的时候会出现各种灵异现象,十分钟写代码,一小时查问题...

异常处理

  • 在实际运行过程中,可能会遇到以下六个问题:
  1. 提前准备必要文件之一,opencv在windows环境的动态链接库,下载地址(不用积分):

Java版人脸跟踪三部曲之二:开发设计

  1. 提前准备必要文件之二,人脸检测的模型文件,下载地址:https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml
  2. native方法异常:BGR实例转为javacv的RGBA时,opencv_imgproc.cvtColor可能抛出异常,所以要注意捕获,避免程序退出
  3. JavaCV中,最常用的类来自org.bytedeco.opencv.opencv_core这个包,然而,在计算直方图、反向投影、CamShift的时候,大部分参数又来自org.opencv.core这个包,因此从摄像头取得的帧相关的数据对象,都要转换成另一个包下面的同名对象,才能顺利的执行人脸跟踪操作
  4. 人脸跟踪的时候,如何判断跟丢了?正常情况下,CamShift返回的是一个有效的矩形,人不再出现的帧,CamShift计算其反向投影的时候,返回的矩形的长和宽都小于等于零,但实际测试的时候,发现人脸消失后,CamShift还可能返回一个很小的矩形,这显然是必须要丢弃的,因此,判断是否跟丢的逻辑,我这里就改成:长或者宽比上一次的变化率是否超过百分八十,实测效果尚可,您也可以自行调整这个参数
  5. 假设人脸检测的结果是50*60的矩形,能将整个人脸包括在此矩形中,但CamShift计算得到的矩形就未必是50*60了,一般高度会更大,导致将人脸之下的脖子也包括进来,而且头发上面会包括进来,此刻,您可以按照自己的业务需求来调整这个矩形,我这里是将位置向下移动(不把头发包括进来),再把宽度的值设置成高度,这样看起来与人脸检测的结果比较接近,调整前后的效果如下图所示:
    Java版人脸跟踪三部曲之二:开发设计
  • 以上就是之前的开发过程中遇到的典型问题,可见如果没有事先准备,怕是每个问题都能将爱学习的您折磨得痛苦不堪...

期待下一篇的实战

  • 至此,图文并茂的设计篇已全部完成,和愉快的编码相比,这种设计和准备工作既枯燥且辛苦,但却是一个功能健全的应用不可或缺的一部分,只希望本篇能为您提供足够的理论知识信息,让咱们在下一篇的编码实战中做到胸有成竹,下笔如有神助
  • 下一篇:《Java版人脸跟踪三部曲之三:编码实战》,敬请期待~

欢迎关注博客园:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...文章来源地址https://www.toymoban.com/news/detail-528482.html

到了这里,关于Java版人脸跟踪三部曲之二:开发设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaCV人脸识别三部曲之三:识别和预览

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 《视频中的人脸保存为图片》 《训练》 《识别和预览》 作为《JavaCV人脸识别三部曲》的终篇,今天咱们要开发一个实用的功能:有人出现在摄像头中时,应用程序在预览窗口标注出此人的身份,效

    2024年02月11日
    浏览(39)
  • LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本文是《LeetCode952三部曲》系列之二,在前文中,咱们详细分析了解题思路,然后按照思路写出了代码,在LeetCode提交成功,成绩如下图所示,137ms,超过39% 不得不说这个成绩很不理想,于是今天咱们

    2024年02月10日
    浏览(39)
  • 【Docker学习三部曲】—— 入门篇

    1️⃣ 什么是 docker ? Docker 是 一种运行应用程序的平台,它可以使应用程序在容器中不受环境差异的影响进行部署和运行 。Docker 的流行度越来越高,是因为它可以帮助在不同的开发者和开发团队之间实现代码的共享和协同开发,并且大大 简化了应用程序的部署,提高了可移

    2023年04月20日
    浏览(48)
  • 【Docker学习三部曲】——进阶篇

    1️⃣ 什么是 Docker-Compose ? Docker Compose 是 Docker 官方提供的 一个用于定义和运行多个容器的工具 ,它采用了声明式的语法定义单个应用程序的多个容器以及它们之间的相互关系和依赖关系。 使用 Docker Compose ,您可以通过一个配置文件来管理多个 Docker 容器,从而更轻松地部署

    2023年04月25日
    浏览(40)
  • vscode上的git三部曲+git pull操作

    git三部曲:git add .、git commit -m \\\'\\\'、git push,命令在连接远程仓库的本地仓库路径下的终端执行。 vscode上的可视化操作如下:  1、对仓库里的文件做更改,让仓库操作的地方有变化。 2、 点击+号,让文件进入缓存,此步骤相当于终端执行命令git add .  3、在这里输入信息并点击

    2024年02月11日
    浏览(39)
  • Go语言基准测试(benchmark)三部曲之一:基础篇

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos Go的标准库内置的testing框架提供了基准测试(benchmark)功能,可以用来验证本地方法在串行或者并行执行时的基准表现,帮助开发者了解代码的真实性能情况,例如一个方法执行一次的平均耗时,还能

    2024年02月06日
    浏览(48)
  • 大模型 Dalle2 学习三部曲(二)clip学习

    clip论文比较长48页,但是clip模型本身又比较简单,效果又奇好,正所谓大道至简,我们来学习一下clip论文中的一些技巧,可以让我们快速加深对clip模型的理解,以及大模型对推荐带来革命性的变化。 首选我们来看看clip的结构,如图clip结构比较直观,训练的时候把文本描述

    2024年02月09日
    浏览(38)
  • 【C++系列P4】‘类与对象‘-三部曲——[类](2/3)

     前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! 【 \\\'类与对象\\\'-三部曲】的大纲主要内容如下 : 如标题所示,本章是【 \\\'类与对象\\\'-三部曲】三章中的第二章节—— 类章节 ,主要内容如下: 目录 一.类 1.类的组成与计算类的大小(含结构体内存对齐规则) 二. 空类的大小

    2024年02月08日
    浏览(40)
  • 数据结构:堆的三部曲(二)top K问题

    top k问题解决的是获取前几个最值的问题。 我们知道 堆的功能主要是选数,选出最大值或者最小值 。那么我们每次获取堆顶元素后,再将剩余元素调整成堆,就可以选出次大的数,如果我们只想要前k个最大值或者最小值,就只需要获取堆顶元素k次,调整k次。比如王者荣耀

    2024年02月02日
    浏览(40)
  • Go语言基准测试(benchmark)三部曲之三:提高篇

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos -《Go语言基准测试(benchmark)三部曲》已近尾声,经历了《基础篇》和《内存篇》的实战演练,相信您已熟练掌握了基准测试的常规操作以及各种参数的用法,现在可以学习一些进阶版的技能了,在面

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包