ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

眼动数据分析实战:动态AOI如何追踪视频刺激物

眼动数据分析实战:动态AOI如何追踪视频刺激物 “眼动数据分析基础_AOI分析动态刺激物”这个标题里的信息量其实挺大的。很多刚开始接触眼动数据的人第一反应是把静态图片切几个兴趣区AOI然后统计注视时长。这当然没错但一旦刺激物变成视频、动画或者游戏中会移动的画面原先那套“画个框框做统计”的思路直接失效。这里面的坑远比想象中多。我之所以想专门写一篇这类内容是因为前阵子帮一个做视频广告效果研究的朋友处理数据他的实验刺激物是一段45秒的商品展示视频产品在画面里来回移动、缩放、旋转供应商导出的眼动数据里倒是字段齐全但他按老办法给整段视频画了一个固定大框来当AOI结果80%的注视点都落在框外统计数据惨不忍睹。这其实是典型的动态刺激物AOI分析没做对。这篇文章就重点把动态AOI分析的核心思路、实操方法和踩坑经验全部理清楚适合正在做视频类眼动实验、广告视频可用性研究或者准备用眼动数据来评估动态界面的人也包括刚读完眼动实验方法论但对具体数据处理还是有点懵的研究生。1. 为什么要单独聊动态刺激物的AOI分析1.1 静态AOI和动态AOI的差异传统AOI分析里刺激物是静态图片。你在一张网页截图、一张海报或者一张产品图上画几个矩形或者椭圆然后去看注视点落在哪个区域。这种做法的前提是刺激物在整个试次内不动AOI的形状和位置也不变。但动态刺激物完全不是这个逻辑。拿视频广告来举例一个产品从画面左侧移动到右侧然后放大展示细节接着又从后方切换镜头换成另一个角度。如果只在画面上画一个固定位置的AOI产品移动到其他地方时那些注视点全部算作“AOI之外的杂乱注视”数据立刻失真。换句话说动态刺激物意味着AOI本身要做时间维度的变化——从“一张图上的一个框”变成“一段视频里跟着目标走的框”。这个变化看起来只是把坐标改了一下其实牵动整个数据分析链路。比如数据导出的字段可能多了一个“AOI时间戳”或者AOI的状态变成“第2秒到第5秒有效”如果数据结构和算法意识没跟上后面做统计、画图表时就会出各种莫名其妙的错。1.2 动态AOI到底解决了什么现实问题做眼动数据分析的人最关心的往往是“用户到底有没有注意到某个区域”、“注意力在某个区域停留多久”、“用户什么时候开始注意到这个区域”。对于动态刺激物比如视频里的某个广告logo、画面里的某个人脸、界面里会弹出的某个提示框如果不能把AOI跟着目标移动持续追踪那这些问题根本回答不了。更关键的是动态刺激物里还藏着“时间维度”。静态AOI只有空间信息动态AOI必须同时包含空间和时间信息。比如说“被试在商品第一次出现后1秒内有没有注意到它”这个问题如果不把商品在视频中的出现时间、移动位置、消失时间全部对齐完全无法计算。因此动态AOI分析的第一个价值就是让你能回答与时间有关的注意问题第二个价值是让你在画面上元素非常多、位置不断变化的时候还能准确知道被试的注视点是在跟哪个目标互动。1.3 常见工具里动态AOI的起步认知市面上的眼动分析软件里Tobii Pro Lab有动态AOIDynamic AOI功能SR Research的Data Viewer也支持对视频材料做逐帧AOI标注开源工具如PyGaze、pymovements也能配合OpenCV处理动态画面。不同工具的标注方式不同但底层逻辑基本一致给AOI定义一个“生效时间区间”和“空间坐标区间”然后基于时间戳去匹配眼动数据。这里有个容易忽略的点动态AOI不是简单地在视频每一帧画个框而是要把这些框的坐标导出成一张表表里的每一行包含AOI名称、开始时间、结束时间、位置、宽度、高度。只有拿到了这张表后续才能对眼动数据做精确的命中判定。很多工具导出的是逐帧的mask图像或者XML/JSON格式的标注文件本质上都是把“随时间变化的区域”转成数据结构化表达。明白了这一点后面无论用什么软件都不会被界面束缚住。2. 动态AOI方案选型到底该怎么定义和生成AOI这个话题里最容易让人纠结的就是“动态AOI怎么生成”。因为AOI不是天然存在的需要你手动或者半自动地标注出来。方案有好几种从纯人工到全自动各有取舍。2.1 逐帧人工标注的老实办法最朴素的做法是把视频一帧一帧看在每一帧上画AOI。软件的动态AOI功能通常支持在关键帧上标注然后自动插值生成中间帧的AOI。比如你每隔10帧标注一下其余的帧靠软件在四个角之间做线性插值。这个方法的好处是精度高完全由人判断目标位置不依赖检测算法坏处是费人力。我自己的经验是一段30秒的视频每隔15帧标一次标一个矩形的AOI大概需要40分钟到一个小时如果视频里同时要标3个目标三个小时可能就没了。如果实验材料有几十个视频这种工作量必须提前评估。还有一个隐藏坑插值假设了目标的运动是近似匀速直线的。如果目标在第5帧到第15帧之间做了一个急转弯或者跳跃式位置变化线性插值会明显偏离真实位置导致命中率异常。因此我在用人工标注时会在目标运动轨迹变向的位置多补几个关键帧而不是偷懒均匀间隔。2.2 时间切片映射的动态AOI方案更工程化的思路是把动态视频按内容切成若干时间段每个时间段内画面整体结构或者目标位置变化不大将这些时间段分别当作静态场景处理。比如一个教学演示视频里前10秒讲师在画面左侧后15秒讲师走到右侧那么可以切成两段每段单独定义静态AOI。这样做的好处是统计分析更简单因为每个时间段内的AOI是稳定的可以直接沿用静态AOI的算法坏处是边界时间点附近容易出问题。比如讲师转身的时候位置可能恰好处于两者之间刚好在切换点上那一两秒的注视点落在哪个时间段就变成了一件很主观的事。为了减少这种边界误差我惯用的做法是时间切片之间留出200到300毫秒的缓冲区间缓冲区间内的数据不参与AOI命中统计。当然具体留多少要看具体场景的数据采样率和行为变化速度但200毫秒是一个相对安全的起点。2.3 基于自动目标检测的半自动标注如果你面对的视频里目标很明确比如人脸、商品、图标可以考虑用OpenCV或目标检测模型来生成候选框再人工复核修正。这种做法的核心优势是处理一段长视频时能大幅减少人工负担。我曾处理过一段5分钟的游戏录屏动态AOI需要追踪玩家技能释放时的图标位置逐帧手动画框画到怀疑人生后来用了YOLO跑一轮检测把关键帧的候选区域导出来再人工核查了一轮效率提升非常明显。不过自动检测也有自己的麻烦。第一检测模型的置信度阈值需要调否则会频繁丢框或者乱框第二检测到的是“识别结果”而不是“兴趣区域语义”比如你想关注的是商品但画面里同时有镜面反射和手机屏幕里的同款商品检测器可能生成多个候选框必须人工去判断哪个才是真正的目标第三坐标插值和维护的时间成本并不低。补一个细节做自动检测时我强烈建议把检测结果和原始视频一起导出成带时间戳的图片序列再去人工逐张确认而不是直接信检测结果因为目标检测偶尔会在连续几帧内抖动这种抖动在做AOI追踪时会直接造成注视点命中率的剧烈波动。2.4 像素级动态AOI的进阶玩法除了矩形框式的AOI还有一种基于像素mask的动态AOI。具体实现是对视频的每一帧生成一个和画面大小相同的二值图像目标所在区域的像素值为1其余为0。然后再把眼动数据的注视点坐标映射到这张mask上去查对应的像素值。这种方法主要适用于目标形状不规则、不能用矩形框紧凑包裹的场景比如分析Logo、手势、比赛中运动员的身体等。因为矩形框越贴近目标形状注视点落在框内但实际不落在目标上的概率越大造成误判。像素级mask的精度高但数据量很大一段60秒30fps的视频就是1800张mask每张1920x1080分辨率存下来文件可能几百MB甚至上GB后续处理时内存和时间开销都不小。不过如果你做的是精细的视觉注意分析这个成本是值得的。我在Tobii Pro Lab的导出结果里见过这种mask方案也有团队用Python脚本自己生成mask本质上都是把AOI从“人工画框”换成“逐像素标记”。3. 数据对齐与时间戳动态AOI分析里最容易被忽略的地基如果要我给动态AOI分析排一个“最容易翻车环节”的排行时间对齐绝对排在第一位。很多人的AOI画得很准眼动数据也干净偏偏最后所有统计都对不上就是因为时间戳没有对齐好。3.1 视频帧率和眼动采样率之间的错拍问题眼动仪通常在120Hz、250Hz、500Hz甚至1000Hz下采集数据也就是说每秒钟有120到1000个采样点。而视频材料一般是24fps、25fps、30fps或者60fps。这两个频率天然不是一个整数倍关系。比如30Hz的眼动采样率和30fps的视频看起来“都是30”但实际从第一个采样点的时刻开始两者就会逐帧产生相位漂移后面的时间点逐渐对不上。因此拿到数据之后第一步永远是检查时间码是否对齐而不是急着写统计脚本。我的习惯是先画出注视点横坐标随时间变化的曲线再把视频里目标位置的曲线叠加在同一张图上如果两条曲线存在一个固定的滞后或者超前量说明时间戳有一个偏移需要整体修正。如果偏移量在实验过程中是变化的那更麻烦多半是采集设备时钟和视频播放时钟没有同步这种数据基本不能粗暴修正最好重新采集或者从采集软件里找媒体时间戳字段来计算实时偏移。3.2 数据清洗的顺序影响AOI命中结果动态视频刺激下被试头部和眼球运动的交互更复杂眨眼、虹膜丢失、眼睑遮挡都会造成数据缺失。如果你直接在原始数据上做AOI命中统计丢失点可能被误判为“没有看AOI”或者被插值算法错误地插进某个区域从而污染统计结果。我自己的清洗流程是先剔除质量标记为无效或者置信度低于阈值的采样点再做平滑滤波然后才做注视点切分最后再拿注视点去和动态AOI做匹配。顺序不能反。如果将AOI匹配放在清洗前面那些无效点可能会因为落在AOI内而被当成有效注意给聚合指标带来严重偏差。另外需要注意不同软件里“注视点”fixation的定义不同有些默认是平均坐标点有些输出的是持续时间和起止时刻。做动态AOI分析时我建议同时保留原始Gaze点数据和一个基于事件切分的Fixation列表。为什么当AOI很小且移动很快时基于原始点的命中率与基于注视点级别的命中率会差很多前者更能反映瞬时扫视过程中的注意后者更适合计算“持续注意”。3.3 动态AOI的标注表结构到底长啥样一张可直接用于动态AOI分析的标注表至少应该包含以下字段AOI名称、起始时间、结束时间、坐标参考系、位置信息中心点x、中心点y或角点坐标、形状矩形、椭圆、多边形、大小信息宽、高或半径。这里有一个非常容易踩的雷坐标参考系一定要和眼动数据一致。有的软件导出的是“相对于视频左上角”的像素坐标有的则是归一化坐标0到1之间还有的软件会把屏幕坐标和媒体坐标混在一起。如果导入自己的算法时没有统一坐标系画出来的AOI位置会偏得离谱而且这种错误通常不是肉眼能快速看出来的因为偏移量可能是整个画面平移了一小块缩放关系也变了导致看起来只是“差不多对”统计结果却输出一堆错误。另外AOI的起始时间和结束时间建议用毫秒级时间戳不要依赖帧编号。因为视频解码、播放延迟、甚至实验软件在呈现视频时的丢帧都会导致帧编号和真实时间之间的关系不稳定。用毫秒级时间戳可以直接和眼动仪导出的时间戳做匹配这是最通用的口。4. 动态AOI分析的常用指标与统计设计有了对齐后的注视点和动态AOI表接下来才算进入正题计算出能回答研究问题的指标。这里面的指标设计跟静态AOI相比有明显区别要多花一些心思。4.1 动态场景下常用指标怎么重新定义静态AOI最常用的指标是总注视时长、平均注视时长、首次注视到达时间、注视次数等。动态AOI下面这些指标要小心重新定义。拿“首次注视到达时间”来说在静态图片上就是指刺激呈现到被试第一次注视AOI之间的时长但动态视频里如果AOI中途才出现比如某个商品在第10秒才开始进画面你要计算的就应该是“商品第一次进入画面之后到被试第一次注视它用了多长时间”而不是从视频开头算起否则时长会被视频前10秒的其他内容稀释掉。同理“总注视时长”也要考虑AOI的“可见时间”作为分母否则拿一个只出现了3秒的AOI和一个出现了30秒的AOI直接比总时长很容易得出误导性结论。因此动态AOI指标设计的第一原则是每一个时间类指标都要明确时间基线是刺激呈现、AOI出现、还是上一事件结束。4.2 滑窗法在动态AOI分析中的作用动态刺激物有一个静态刺激没有的优势你可以在时间维度上做滑窗分析。比如可以按每100毫秒一个窗口统计每个窗口内注视点落在目标AOI的比例。这样做的好处是能看出“注意力的时间动态”比如看广告时用户是不是一开始注意到商品后面注意力漂移到了背景最后又被文字吸引回来。滑窗宽度需要根据研究问题来设定并没有统一标准。100到250毫秒是常见选择太短会引入大量噪声因为在一次注视过程中注视点本来就会在很小的范围内漂移太长则会抹平时间细节不容易看出注意转移的拐点。我通常的做法是先跑不同窗口宽度看看曲线上关键峰谷是否稳定如果稳定才认为这个滑窗设置是合理的。4.3 动态AOI数据做统计时常见的坑统计分析层面动态AOI数据经常会引入重复测量的时间因素常见做法是把每个试次按时间窗划分这样每个被试每个窗口都有一个指标值形成嵌套结构。如果直接对整段视频的总指标做t检验容易浪费大量时间维度的信息。更合理的方案是用线性混合模型LMM把时间窗作为固定或随机效应来处理因为单个被试的不同时间窗之间有很强的自相关忽视了这一点会让统计显著性变得虚高。另外还有一个容易被忽视的问题多个AOI之间存在空间重叠现象。动态场景里两个物体可能在某一时刻靠得很近或者叠加遮挡这时一个注视点可能会同时命中了两个AOI。处理方式有两种一种是设定优先级决定重叠时哪个AOI优先另一种是把这种重叠区域单独设成一个AOI来计算。我建议避免“一个注视点同时计给两个AOI”的做法因为这会让总注视时长超过总测量时长在报告时很容易被审稿人质疑。我一般用分配法优先按照AOI重叠面积和注视点距离做归属并且把这个规则写进方法部分方便其他人复现。5. 实操案例从标注到统计完整跑一遍动态AOI分析为了不让前面这些理论显得太空我用一个真实处理过的简化案例把全流程串一遍。场景是某产品宣传视频时长45秒30fps视频内容分为三个部分产品A展示1-15秒、产品B展示16-30秒、品牌Logo收尾31-45秒。10名被试佩戴眼动仪观看采样率250Hz。我想回答的问题是被试在第几秒才开始注意到产品B以及产品B出现期间他们的平均注视时长是多少。5.1 标注阶段确定AOI的时间区间和运动轨迹我使用的工具是Tobii Pro Lab的动态AOI功能但就算你用别的软件核心步骤几乎一样。第一步把视频导入软件在时间轴上定位产品B的起始帧大约是第16秒前一点点然后每一帧去看产品B在画面里的位置每隔15帧标记一次位置并微调矩形框。产品B在视频中有一个明显的旋转动作旋转时矩形框的大小会变所以我在旋转开始和旋转结束的地方额外加了关键帧防止插值偏差过大。最后得到一张包含“产品B”的AOI表标注里的起始时间是15932毫秒结束时间是30008毫秒坐标是基于视频分辨率的像素值坐标系为视频左上角原点。这里有一个值得强调的点软件里自动插值出的曲线导出之后要检查一下中间帧的位置是否有突然跳动。我检查的方式是把导出的AOI中心坐标随时间变化画成曲线和视频里目标的实际轨迹放在一起目测比对有差异就回去补关键帧。这一步看起来费时却能避免后期数据的系统性偏移。5.2 数据导入和注视点判定然后将眼动仪导出的原始数据导入Python环境。这里我不走软件的点击按钮而是手动处理数据原因是可以完全掌控坐标转换和过滤规则。原始数据里有timestamp、gaze_point_x、gaze_point_y、confidence等字段。我先剔除confidence低于0.8的点再用一个简单的速度为阈值的滤波器识别扫视和注视。比如可以设定速度阈值低于每秒30度视为注视然后把连续的注视点聚合成注视事件。因为视频分辨率是1920x1080而眼动仪数据经过坐标映射后通常也是视频坐标所以坐标不需要额外转换。如果实验里眼动仪是屏幕坐标而视频全屏播放而且分辨率跟屏幕分辨率一致那也可以直接用如果不一致就必须做等比映射否则AOI位置和注视点坐标会出现整体错位。接着写一个函数判断注视点是否落在动态AOI中。伪代码如下def is_hit(point_x, point_y, time_ms, aoi_table): for _, row in aoi_table.iterrows(): if row[start_ms] time_ms row[end_ms]: if row[shape] rect: left row[x] - row[width] / 2 right row[x] row[width] / 2 top row[y] - row[height] / 2 bottom row[y] row[height] / 2 if left point_x right and top point_y bottom: return True # 如果是椭圆、多边形类似检查 return False实际计算时还要注意一个注视事件可能跨越多个时间点需要按采样点逐一判断再聚合到事件级别。5.3 指标计算与统计结果解读将所有注视点跑完命中判断后我汇总每个被试的数据得到“对产品B的总注视时长”和“首次看到产品B的潜伏期”。由于产品B在约15.9秒时出现我计算潜伏期时用的时间基线是产品B首次出现的时刻潜伏期 首次命中AOI的时刻 - AOI开始时间。结果显示10名被试里8名在产品B出现后的400到1000毫秒内就首次注视到它1名被试到2.5秒后才注意到还有1名在整段产品B展示期间居然一次都没有真正注视到目标区域。这个个体差异立刻提醒我一件事直接用“平均总注视时长”来代表群体会把后面那两名被试的信息藏掉。所以我最后的报告中同时给出中位数和四分位距并且用线性混合模型确认“产品B出现位置是否影响首次注视时间”。整个流程做完之后再把每个被试的注视轨迹做成逐帧动画叠加在视频上用于给需求方做汇报展示。动画里能看到时间轴和AOI框同时移动配合注视点一起运动说服力比单看统计数字强得多。6. 动态AOI分析的常见问题与排查技巧实录最后这部分是我个人积攒的一些现场排坑经验。如果你已经在处理动态AOI数据下面的问题很可能也遇到过。6.1 视频时间戳出现漂移怎么判断和修正有一次我处理数据时发现前半段视频AOI命中率正常后半段命中率越来越差越往后越明显。起初我以为是AOI标注偏了反复检查后确认AOI轨迹是对的。后来把注视点轨迹和AOI轨迹画在同一张图上才发现注视点的横坐标曲线比AOI轨迹整体滞后了约300到400毫秒而且滞后量随视频播放时间递增。这类问题通常源于视频播放器和眼动数据采集系统之间没有合理的时钟同步导致偏移不断累积。如果偏移量是相对稳定的可以在代码中对注视点时间戳整体加上或减去一个固定偏移量重新匹配如果偏移量是随时间线性增长的可以考虑用线性插值做全局时间校准但这只是补救措施最好还是回到实验采集流程里检查刺激呈现程序和眼动记录之间是否用了统一的系统时钟。6.2 目标物体太小导致命中率异常低动态视频里如果AOI目标本身很小比如一个小Logo、一个界面右下角的图标即便被试确实看了它由于注视点本身存在精度噪声判定结果仍然可能显示为“未命中”。这只是测量误差不代表被试没在看。我通常的处理方法是先区分“AOI很小”和“AOI根本没被看”两种情况。可以通过查看注视点相对于AOI中心的距离分布来判断如果大量注视点都聚集在AOI边缘附近但不在框内说明是精度误差导致的漏判如果注视点分布在整个画面里比较均匀那可能就是真的没有关注这个区域。针对前者一个可行方案是适当扩大AOI尺寸比如把矩形框向外扩展10到20个像素但要记录好扩大的逻辑并在报告里说明判断标准。另一种更严格的做法是不改AOI改用“注视点与AOI中心距离小于阈值”的方式定义命中这也是很多研究音视频注意力时采用的方式。6.3 多AOI重叠或遮挡时怎么处理命中归属动态视频中目标之间互相遮挡是家常便饭。比如视频里一个人从产品前走过挡住产品几百毫秒这时AOI边界要不要跟随人的运动而变化又比如两个AOI在某一时刻发生了重叠一个注视点同时落在两个框内该算谁我目前的经验是在标注阶段就临时修改AOI的起始和结束时间把遮挡发生的区间割裂出来让该AOI在遮挡期间暂时失效也就是AOI时间轴是断裂的而不是必须连续的。这么做的好处是计算总注视时长时不会把遮挡期间无法产生的注视误判为“用户没有注意”。至于重叠命中除了一开始提到的优先级分配法还可以在预处理时把两个AOI合并成一个“重叠区AOI”专门计算重叠区的注意力占比。这在广告品牌研究中非常实用因为经常出现品牌Logo和产品同时出现在画面里这时候你其实很想知道被试是不是真的在同时把两者看进去了。6.4 动态视频AOI分析的可复现性最后说一个偏工作习惯的经验动态AOI分析一定要把标注表、脚本、版本号和视频文件做归档。静态AOI分析可以靠截图快速复现动态AOI分析因为涉及时间戳、轨迹插值、坐标映射这些步骤任何一步出问题都会导致整个结果无法重现。所以建议标注表用CSV/JSON保存不用软件自带私有格式脚本里固定随机种子和模块版本最好放一个requirements.txt或者environment.yml视频材料则记录原始帧率和编码方式。很多时候过了几个月回看自己之前做的项目要不是当时留了这些痕迹根本搞不清楚某一步是怎么处理的。另外动态AOI的标注工作量大如果实验包含多个批次的视频在正式标注之前最好先做一个标注一致性测试。找两个人分别标同一段视频的AOI然后比较命中率差异差异如果超过5%到10%肯定是标注规则不够清晰。这个测试听起来麻烦但能帮你省下后面大量反复返工的时间。我个人在实际操作中的体会是动态AOI分析本质上不是在“模仿静态AOI”而是重新建立一套涉及“空间时间事件语义”的分析逻辑。它比静态分析多了很多要操心的地方但只要把时间对齐、AOI定义规则和数据归属规则这三点管住整个分析工作就会顺滑很多。最后再分享一个小技巧正式分析前先随便抽取一名被试的数据把注视点动画和动态AOI框叠在原视频上完整看一遍。这个检查虽然原始却比任何统计数据都更能帮你发现坐标错位、时间漂移和标注遗漏这类低级问题。看完这一遍几乎可以避开90%的动态AOI处理事故。
返回列表