<think>我们需要从文件名中提取时间信息。观察文件名格式:`raw _0. 20250710081107. 340462. h5`,其中时间信息部分为`20250710081107`,这表示2025年07月10日08时11分07秒。但是注意,文件名中还有空格和点,我们需要解析出时间字符串。
我们可以使用正则表达式来提取时间字符串。时间字符串的格式是14位数字(年月日时分秒)。在MATLAB中,我们可以使用正则表达式匹配14位连续数字。
修改步骤1中解析时间戳的部分:
原代码:
[~, name] = fileparts(fileList(fidx).name);
timeStamps(fidx) = datenum(name, 'yyyymmdd_HHMMSS');
新文件名格式下,我们需要从文件名中提取14位数字字符串,然后将其转换为datenum。注意,datenum函数支持将字符串转换为日期数字,但需要指定格式。14位数字的格式为'yyyymmddHHMMSS'(注意没有下划线)。
修改为:
[~, name] = fileparts(fileList(fidx).name);
% 使用正则表达式匹配14位数字
timeStr = regexp(name, '\d{14}', 'match');
if ~isempty(timeStr)
timeStamps(fidx) = datenum(timeStr{1}, 'yyyymmddHHMMSS');
else
error('在文件名 %s 中未找到时间信息', fileList(fidx).name);
end
另外,注意文件名中可能有空格,我们使用fileparts得到的基本文件名是完整的(包括空格),所以正则表达式匹配时要注意。
完整修改后的步骤1代码:
```matlab
%% 步骤1: 批量读取H5文件
fileList = dir(fullfile(dataDir, filePattern));
numFiles = numel(fileList);
timeStamps = zeros(numFiles, 1); % 存储时间戳
% 预分配空间-时间矩阵 (时间×空间)
spatialTemporalMatrix = zeros(numFiles, 1280);
% 并行读取处理 (需要Parallel Computing Toolbox)
parfor fidx = 1:numFiles
% 从文件名解析时间戳 (使用正则表达式提取14位连续数字)
[~, name] = fileparts(fileList(fidx).name);
% 匹配14位连续数字
timeStr = regexp(name, '\d{14}', 'match');
if ~isempty(timeStr)
timeStamps(fidx) = datenum(timeStr{1}, 'yyyymmddHHMMSS');
else
error('在文件名 %s 中未找到时间信息', fileList(fidx).name);
end
% 读取H5数据
filePath = fullfile(dataDir, fileList(fidx).name);
data = h5read(filePath, '/measurement'); % 假设数据集路径为/measurement
% 计算空间能量特征 (每行RMS)
spatialTemporalMatrix(fidx, :) = rms(data, 2)';
end
```
这样,即使文件名中有其他字符,我们也能正确提取时间信息。
注意:如果文件名中有多个14位数字,我们只取第一个匹配的。根据你的描述,每个文件名中应该只有一个时间字符串。
其他步骤不变。
另外,在结果输出部分,我们使用`datestr`将时间戳转换为字符串时,可以指定格式,例如:`datestr(timeStamps(floor(bb(2))), 'yyyy-mm-dd HH:MM:SS')`,这样输出更易读。
如果遇到没有匹配到时间字符串的文件,程序会报错。如果希望跳过错误文件,可以将错误改为警告并跳过,但这样可能会影响时间序列的连续性。因此,建议确保所有文件都包含时间信息。
所以,完整的代码修改点就是步骤1中时间戳的提取方式。
如果实际文件名中的时间格式不是14位数字(比如有小数点或其他),则需要调整正则表达式。但根据你提供的例子,是14位整数。
另外,注意文件名中的时间信息精确到秒,而我们的数据是每秒一个文件,所以每个文件的时间戳是整秒。
现在,代码应该可以处理你提供的文件名格式了。</think>### 解决方案:处理非标准时间格式的文件名
以下是针对非标准文件名格式的完整解决方案,使用正则表达式提取时间信息并处理数据:
```matlab
%% 参数设置
dataDir = 'path/to/h5/files'; % H5文件存储目录
filePattern = '*.h5'; % 文件匹配模式
spacing = 0.4; % 空间采样间隔(米)
timeResolution = 1/8000; % 时间分辨率(秒)
thresholdFactor = 5; % 事件检测阈值因子
%% 步骤1: 批量读取H5文件并解析时间戳
fileList = dir(fullfile(dataDir, filePattern));
numFiles = numel(fileList);
timeStamps = NaT(numFiles, 1); % 存储时间戳 (NaT表示未定义时间)
% 预分配空间-时间矩阵
spatialTemporalMatrix = zeros(numFiles, 1280);
% 定义时间解析函数
parseTime = @(name) datetime(regexp(name, '\d{14}', 'match', 'once'), ...
'InputFormat', 'yyyyMMddHHmmss', 'TimeZone', 'local');
% 并行处理文件
parfor fidx = 1:numFiles
% 从文件名解析时间戳
fileName = fileList(fidx).name;
try
% 提取14位数字时间戳
timeStr = regexp(fileName, '\d{14}', 'match', 'once');
if isempty(timeStr)
error('未找到时间戳: %s', fileName);
end
% 转换为datetime对象
timeStamps(fidx) = datetime(timeStr, 'InputFormat', 'yyyyMMddHHmmss', 'TimeZone', 'local');
% 读取H5数据
filePath = fullfile(dataDir, fileName);
data = h5read(filePath, '/measurement');
% 计算空间能量特征 (每行RMS)
spatialTemporalMatrix(fidx, :) = rms(data, 2)';
catch ME
warning('文件 %s 处理失败: %s', fileName, ME.message);
end
end
% 移除处理失败的文件
validIdx = ~isnat(timeStamps);
timeStamps = timeStamps(validIdx);
spatialTemporalMatrix = spatialTemporalMatrix(validIdx, :);
numFiles = numel(timeStamps);
% 按时间排序
[timeStamps, sortIdx] = sort(timeStamps);
spatialTemporalMatrix = spatialTemporalMatrix(sortIdx, :);
%% 步骤2: 时空矩阵预处理 (同之前代码)
% ... [预处理代码保持不变] ...
%% 步骤3: 车辆事件检测 (同之前代码)
% ... [检测代码保持不变] ...
%% 步骤4: 时空事件聚类 (同之前代码)
% ... [聚类代码保持不变] ...
%% 步骤5: 结果可视化与输出
% 显示检测到的事件
disp('===== 检测到的车辆事件 =====');
for i = 1:numel(validEvents)
e = validEvents(i);
fprintf('事件 %d:\n', i);
fprintf(' 时间范围: %s 到 %s\n', e.StartTime, e.EndTime);
fprintf(' 位置范围: %.1f米 到 %.1f米\n', e.StartLocation, e.EndLocation);
fprintf(' 中心时间: %s\n', e.CenterTime);
fprintf(' 中心位置: %.1f米\n', e.CenterLocation);
fprintf(' 持续时间: %.2f秒\n', e.Duration);
fprintf(' 空间跨度: %.1f米\n\n', e.SpaceLength);
end
% 创建时间轴用于绘图
timePoints = timeStamps(1):seconds(1):timeStamps(end);
[~, timeIndices] = ismember(timeStamps, timePoints);
% 时空矩阵可视化
figure('Position', [100, 100, 1200, 600])
subplot(2,1,1)
imagesc(timeIndices, 1:1280, spatialTemporalMatrix')
title('原始时空矩阵')
xlabel('时间')
ylabel('空间位置 (每点=0.4米)')
datetick('x', 'HH:MM:SS', 'keeplimits', 'keepticks')
colorbar
subplot(2,1,2)
imagesc(timeIndices, 1:1280, eventMatrix')
title('检测到的车辆事件')
xlabel('时间')
ylabel('空间位置 (每点=0.4米)')
hold on
for i = 1:numel(validEvents)
e = validEvents(i);
startIdx = find(timeStamps >= e.StartTime, 1);
endIdx = find(timeStamps <= e.EndTime, 1, 'last');
startPos = e.StartLocation / spacing + 0.5;
endPos = e.EndLocation / spacing + 0.5;
rectangle('Position', [startIdx, startPos, endIdx-startIdx, endPos-startPos],...
'EdgeColor', 'r', 'LineWidth', 1.5)
end
datetick('x', 'HH:MM:SS', 'keeplimits', 'keepticks')
```
### 关键修改点详解
#### 1. 时间戳解析函数
```matlab
parseTime = @(name) datetime(regexp(name, '\d{14}', 'match', 'once'), ...
'InputFormat', 'yyyyMMddHHmmss', 'TimeZone', 'local');
```
- 使用正则表达式 `\d{14}` 匹配14位连续数字(如20250710081107)
- 转换为MATLAB的`datetime`类型,保留时区信息
- 示例文件名:`raw _0. 20250710081107. 340462. h5` → 提取`20250710081107` → 解析为`2025-07-10 08:11:07`
#### 2. 健壮的错误处理
```matlab
try
% 提取和处理代码
catch ME
warning('文件 %s 处理失败: %s', fileName, ME.message);
end
```
- 捕获可能的错误(如时间戳缺失、文件损坏)
- 记录错误但继续处理其他文件
- 使用`warning`而非`error`保证程序继续执行
#### 3. 时间数据处理流程
```matlab
% 移除无效文件
validIdx = ~isnat(timeStamps);
timeStamps = timeStamps(validIdx);
% 按时间排序
[timeStamps, sortIdx] = sort(timeStamps);
spatialTemporalMatrix = spatialTemporalMatrix(sortIdx, :);
```
1. 使用`NaT`(Not-a-Time)标记无效时间戳
2. 过滤掉无效文件
3. 按时间顺序排序文件,确保时间序列正确
#### 4. 可视化时间轴处理
```matlab
% 创建连续时间轴
timePoints = timeStamps(1):seconds(1):timeStamps(end);
[~, timeIndices] = ismember(timeStamps, timePoints);
% 绘图时使用实际时间
imagesc(timeIndices, 1:1280, spatialTemporalMatrix')
datetick('x', 'HH:MM:SS', 'keeplimits', 'keepticks')
```
- 创建连续的时间轴(每秒一个点)
- 使用`datetick`将数值轴转换为易读的时间格式
- `keeplimits`和`keepticks`保持坐标轴范围不变
### 处理流程说明
1. **文件扫描**:获取所有H5文件列表
2. **时间戳提取**:
- 使用正则表达式匹配14位数字时间戳
- 转换为`datetime`对象
- 处理可能的格式错误
3. **数据读取**:
- 并行读取H5文件
- 计算每行的RMS值作为特征
4. **数据清洗**:
- 移除无效时间戳的文件
- 按时间顺序排序
5. **事件检测**:
- 时空矩阵预处理(去噪、平滑)
- 基于统计阈值检测事件
- 时空聚类识别车辆轨迹
6. **结果输出**:
- 文本显示检测到的车辆事件
- 可视化时空矩阵和检测结果
### 注意事项
1. **时间格式**:代码假设时间戳为14位数字(年月日时分秒)
2. **文件命名**:支持示例中的`raw _0. 20250710081107. 340462. h5`格式
3. **错误处理**:自动跳过格式错误的文件并记录警告
4. **时区处理**:使用`'TimeZone', 'local'`保留本地时区信息
5. **内存优化**:处理前确保有足够内存(7200×1280矩阵约70MB)