You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于关键帧高效填充视频传感器数据数组

问题

现有数组:

arr = [[180, 210, 240, 270, 300],[38.7, 38.4, 38.2, 37.9,37.7]]

其中存储了视频帧编号及对应帧的传感器采集值。视频分析程序需要获取每帧的传感器值,但传感器为避免负载仅按大间隔采样,需实现一个计算成本低的函数返回未采样帧的传感器值,视频起始分析帧未知。

填充规则如下:

  • 以相邻采样帧的中间位置为分界,中间区域使用对应采样值(例如帧195-225使用帧210的数值)
  • 单个视频的采样间隔固定,不同视频可不同
  • 传感器采样始于视频中途(示例中为第3秒),采样前所有帧用首个采样值,采样结束后所有帧用最后一个采样值(例如f(0)=f(180)、f(350)=f(300))

不想每次查询都进行二分查找,也考虑过预先生成全步长数组,但担心内存占用与查询性能问题。以下是预填充数组的尝试代码:

sparse_data = [[180, 210, 240, 270, 300],[38.7, 38.4, 38.2, 37.9,37.7]]
delta = sparse_data[0][1] - sparse_data[0][0]
fr_max = sparse_data[0][-1] + delta
fr_min = sparse_data[0][0]
cur_sparse_idx = 1
self.magn_data = np.zeros(fr_max, dtype=np.float32)
    for i in range(fr_max):
        if i <= (fr_min + delta//2):
            self.magn_data[i] = sparse_data[1][0]
        elif i > fr_max: 
            self.magn_data[i] = sparse_data[1][-1]
        else:
            if (i+delta//2) % delta == 0: cur_sparse_idx += 1
            self.magn_data[i] = sparse_data[1][cur_sparse_idx]

请问是否有更优实现方案?


更优实现方案

方案一:数学映射直接计算(无内存占用)

直接通过帧号的数学运算定位对应采样值,完全避免预生成数组的内存开销,单次查询计算成本极低:

def get_sensor_value(frame_num, sparse_data):
    frames = sparse_data[0]
    values = sparse_data[1]
    delta = frames[1] - frames[0]
    half_delta = delta // 2

    # 采样前的帧,返回首个采样值
    if frame_num <= frames[0] + half_delta:
        return values[0]
    # 采样结束后的帧,返回最后一个采样值
    if frame_num >= frames[-1] - half_delta:
        return values[-1]
    
    # 偏移帧号后,用整除直接定位采样索引
    adjusted_frame = frame_num - half_delta
    idx = (adjusted_frame - frames[0]) // delta
    return values[idx + 1]

核心逻辑是将分界点对齐到采样间隔的整数倍,用整除运算直接锁定对应采样值,无需循环或二分查找,性能最优。

方案二:优化预生成数组(numpy向量化操作)

如果必须预生成数组,放弃Python循环,改用numpy向量化操作,速度提升数倍:

import numpy as np

sparse_data = [[180, 210, 240, 270, 300],[38.7, 38.4, 38.2, 37.9,37.7]]
frames = np.array(sparse_data[0])
values = np.array(sparse_data[1])
delta = frames[1] - frames[0]
half_delta = delta // 2

# 按需设置最大覆盖帧范围
max_frame = frames[-1] + delta
all_frames = np.arange(max_frame)

# 计算每个帧对应的采样索引,自动处理边界
adjusted = all_frames - half_delta
idx = np.clip((adjusted - frames[0]) // delta + 1, 0, len(values)-1)
magn_data = values[idx].astype(np.float32)

利用numpy的广播和向量化特性,避免Python层级的循环,生成数组的效率远高于原代码,逻辑也更简洁。

方案三:按需缓存(LRU缓存)

如果查询的帧号重复率较高,结合方案一的计算逻辑加LRU缓存,兼顾性能与内存:

from functools import lru_cache

# 转成tuple保证可哈希,用于缓存
frames_tuple = tuple(sparse_data[0])
values_tuple = tuple(sparse_data[1])
delta = frames_tuple[1] - frames_tuple[0]
half_delta = delta // 2

@lru_cache(maxsize=1024)
def get_sensor_value(frame_num):
    if frame_num <= frames_tuple[0] + half_delta:
        return values_tuple[0]
    if frame_num >= frames_tuple[-1] - half_delta:
        return values_tuple[-1]
    adjusted_frame = frame_num - half_delta
    idx = (adjusted_frame - frames_tuple[0]) // delta
    return values_tuple[idx + 1]

缓存命中率高时,性能接近直接数组查询,内存占用远小于预生成全量数组。

内容的提问来源于stack exchange,提问作者Raphael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 04:15:38