开始大家期待的Pupil Labs Core源码解读计划了,尽量一周一篇。其实这里面就是几何学的天下,还有一点生理学基础,所以几何学是先修课程。
其次我们对于眼球来说就是关注注视点一种数据,丰富的数据可以通过后处理获得。
左图的苹果展示了我们的眼睛是如何呈现图像的,而右图的汽车则展示了我们的大脑如何呈现内容,这里面就展示了注视点的一个例子,这个注视点也可以认为是我们视觉最清晰的地方,这个地方叫黄斑。
可以自己看看,是不是周围是模糊的,如果是全视野清晰请联系我,我抓你去医院。
其实Pupil的核心不难,里面内置了2D追踪,3D追踪用来给2D做一部分的校准,这两个算法有论文还有源码,是之后主要分析的部分。
为什么这个源码看起来这么复杂呢?是因为基础件太多了,首先是GUI的代码混在里面,其实就是按键交互很多。还有就是插件系统,为了扩展性引入的,还有就是数据流不是传统CV那样,而是使用ZeroQ,流向复杂。事实上要快速快发就学插件系统就好,但是为了更大的自由,以及好奇心我还是要读读源码。
按道理说,Linux下的开发最好,但是最新的代码GUI是失去响应的,Mac,Windows正常,这也算我的发现的一个Bug。
因为依赖的库很多,这里使用虚拟环境,这里推荐Python插件
没见过这么好的东西
其次在开发的时候需要注意使用的是develop这个分支
pip freeze > requirements.txt
pip install -r requirements.txt
这个代码是把环境里面使用的库全都抽调出来。
我们追踪的是瞳孔,确保摄像头的视野永远可以把瞳孔都拍到,这个可以作为选型依据。
内置的检测算法,是可以让眼球一直转,然后一个蓝色的圆圈出现,我们后面分析到这个算法。
为了知道某人在看什么,必须建立瞳孔和凝视位置之间的映射。这就是我们所说的校准,校准过程建立了从瞳孔到凝视坐标的映射。
校准就是创建瞳孔位置到凝视位置的函数,这个在文档里面只是有一段操作文档,事实上我查阅资料发现还发了篇论文。
你感觉上面我说的校准过程对吗?如果你说对,那我觉得你有些不求甚解。
对于一个眼球来说,理想的模型我们认为有一束光来指向前方,也就是叫光轴,但是真实看见东西的轴叫视觉轴,这两个东西之间有夹角,校准也是来找到这里的函数关系。
视轴和光轴是有偏角的
漂亮的图耶
最好还是基于几何的校准,这样就是定制化的操作了,也是最先进,也是我的目标。
我们要的是vis,但是捕捉到的是opt,这张图展示了这种差异
1、α角定义:视轴和光轴之间的夹角。
视轴:即眼睛注视某一点时,光线由该固定点到黄斑中心凹的通路。
光轴:即通过眼睛所有光学表面曲率中心的轴。
2、κ角的定义:视轴和瞳孔轴之间的夹角。
瞳孔轴(pupillary axis)是与角膜垂直并连接瞳孔中心的连线。
3、α角和κ角的正常值范围是多少?
α角的正常值为4°≤α≤8°。假如瞳孔轴在视轴的鼻侧,那么κ角为正值,假如瞳孔轴在视轴的颞侧,那么κ角为负值。一般情况下,κ角小于α角。
下面就来粗略的看看一下论文PPT:
校准存在这么多的问题
这项工作被CHI接收
给了一种基于运动的基准方式,你只要看一个标准小范围的移动头部就可以快速校准。
1.基础回归模型应考虑到校准曲面不是平面的。
实际上,这已经是事实,因为目前大多数模型都采用曲线关系来补偿晶状体扭曲和眼睛曲率。
2.相对于基于平面校准的凝视估计,基于表面校准的凝视估计根据物体位置和表面曲率可能表现出更大或更小的视差误差。
3.试图在平面上评估表面校准(反之亦然)将由于引入视差误差而导致结果精度偏差。事实上,这适用于任何两个不同的校准和评估表面(例如,两个不同的平面)
这篇论文会在后面专门的分析。
Pupil Core 的算法自动检测参与者的瞳孔。
它同时运行两个并行检测pipelines :2D 瞳孔检测和 3D 瞳孔检测。
2D 瞳孔检测
2D 检测使用计算机视觉技术在摄像头图像中检测瞳孔位置。这种方法依赖于图像处理算法来识别瞳孔的形状和位置,通常通过边缘检测、轮廓分析以及其他视觉特征提取技术来实现。
3D 瞳孔检测
3D 检测使用眼睛的三维模型,该模型基于对眼睛的观察不断更新。这种方法允许系统补偿 Pupil Core 眼动追踪头戴设备在参与者脸部上的移动(也称为滑动)。
为了建立初始模型,建议在戴上头戴设备时环视视野。这有助于捕捉不同的视角,从而更准确地构建和调整 3D 模型。
并行检测的优势
2D算法是通过插件系统实现的:
在这里
这个是完整的符号树
调试的时候可以在这里打开debug开关
可以在这里找到关于插件的日志
日志展开
coarse_detection:
True: 启用粗略检测,用于快速定位可能的瞳孔区域,然后进行精细检测。
coarse_filter_min 和 coarse_filter_max:
128 和 280: 粗略过滤的强度范围,用于初步筛选可能的瞳孔区域。
intensity_range:
23: 瞳孔与背景之间的强度差异范围,用于区分瞳孔和背景区域。
blur_size:
5: 模糊滤波器的大小,用于减少图像噪声和平滑图像。
canny_treshold、canny_ration 和 canny_aperture:
pupil_size_max 和 pupil_size_min:
200 和 20: 瞳孔尺寸的最大值和最小值,限制检测到的瞳孔大小范围。
strong_perimeter_ratio_range_min strong_perimeter_ratio_range_max:
0.8 和 1.1: 瞳孔边缘强度的最小和最大比率范围,用于筛选边缘强度合适的候选区域。
strong_area_ratio_range_min 和 strong_area_ratio_range_max:
0.6 和 1.1: 瞳孔面积强度的最小和最大比率范围,用于筛选面积强度合适的候选区域。
contour_size_min:
5: 瞳孔轮廓的最小尺寸,排除小于此值的轮廓。
ellipse_roundness_ratio:
0.1: 椭圆形的圆度比率,用于衡量检测到的瞳孔是否接近椭圆形。
initial_ellipse_fit_treshhold:
1.8: 初始椭圆拟合的阈值,用于初步检测瞳孔轮廓。
final_perimeter_ratio_range_min
final_perimeter_ratio_range_max:
0.6 和 1.2: 最终边缘强度的最小和最大比率范围,用于筛选最终检测到的瞳孔边缘。
ellipse_true_support_min_dist:
2.5: 椭圆形支持点的最小距离,用于确定哪些像素点支持椭圆拟合。
support_pixel_ratio_exponent:
2.0: 支持像素比率的指数,用于调整支持点分布的敏感度。
参数的作用
这些参数的配置旨在优化 2D 瞳孔检测过程,包括:
使用建议
emmmmm,还是很复杂的。
https://www.hci.uni-tuebingen.de/assets/pdf/publications/TWE052017.pdf
https://www.youtube.com/watch?v=gYtF3j2Hdl4