删除 video_results.html

This commit is contained in:
Wang_Run_Ze 2025-06-27 17:12:05 +08:00
parent c35cf7daaf
commit 14418af6bb

View File

@ -1,389 +0,0 @@
{% extends "layout.html" %}
{% block content %}
<div class="container">
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ url_for('index') }}"><i class="bi bi-house"></i> 首页</a></li>
<li class="breadcrumb-item"><a href="{{ url_for('view_report', report_filename=report_filename) }}"><i class="bi bi-file-earmark-text"></i> 检测报告</a></li>
<li class="breadcrumb-item active" aria-current="page"><i class="bi bi-film"></i> {{ video_name }}</li>
</ol>
</nav>
<div class="card">
<div class="card-header bg-dark text-white d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0"><i class="bi bi-camera-video"></i> 视频检测结果: {{ video_name }}</h5>
<a href="{{ url_for('view_report', report_filename=report_filename) }}" class="btn btn-sm btn-outline-light"><i class="bi bi-arrow-left"></i> 返回报告</a>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="video-info-card">
<h6 class="border-bottom pb-2 mb-3"><i class="bi bi-info-circle"></i> 视频信息</h6>
<div class="row">
<div class="col-md-6">
<div class="info-item">
<span class="info-label"><i class="bi bi-film"></i> 视频名称:</span>
<span class="info-value">{{ video_name }}</span>
</div>
</div>
<div class="col-md-6">
<div class="info-item">
<span class="info-label"><i class="bi bi-images"></i> 总帧数:</span>
<span class="info-value">{{ total_frames }}</span>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-6">
<div class="info-item">
<span class="info-label"><i class="bi bi-eye"></i> 检测帧数:</span>
<span class="info-value">{{ frames|length }}</span>
</div>
</div>
<div class="col-md-6">
<div class="info-item">
<span class="info-label"><i class="bi bi-percent"></i> 检测率:</span>
<span class="info-value">
{% if total_frames and frames %}
{{ ((frames|length / total_frames) * 100)|round(2) }}%
{% else %}
-
{% endif %}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="detection-timeline-card">
<h6 class="border-bottom pb-2 mb-3"><i class="bi bi-clock-history"></i> 检测时间线</h6>
<div class="chart-container">
<canvas id="timelineChart"></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header bg-dark text-white d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0"><i class="bi bi-images"></i> 检测到的帧 ({{ frames|length }})</h5>
<div class="btn-group">
<button class="btn btn-sm btn-outline-light" id="grid-view-btn" title="网格视图">
<i class="bi bi-grid"></i>
</button>
<button class="btn btn-sm btn-outline-light active" id="list-view-btn" title="列表视图">
<i class="bi bi-list"></i>
</button>
</div>
</div>
<div class="card-body">
{% if frames %}
<div class="mb-3">
<input type="text" class="form-control" id="frame-search" placeholder="搜索帧 (按帧号或类别)">
</div>
<div id="grid-view" class="row frame-container" style="display: none;">
{% for frame in frames %}
<div class="col-md-4 mb-4 frame-item" data-frame-number="{{ frame.frame_number }}" data-classes="{{ frame.classes|join(' ') }}">
<div class="card h-100">
<div class="card-img-container">
<img src="{{ url_for('frame_image', video_folder=video_folder, frame_file=frame.filename) }}"
class="card-img-top" alt="检测帧 #{{ frame.frame_number }}"
loading="lazy">
</div>
<div class="card-body">
<h6 class="card-title">帧 #{{ frame.frame_number }}</h6>
<p class="card-text">
<small><i class="bi bi-clock"></i> 时间: {{ frame.timestamp }}</small><br>
<small><i class="bi bi-tag"></i> 检测类别:
{% for class in frame.classes %}
<span class="badge bg-primary me-1">{{ class }}</span>
{% endfor %}
</small>
</p>
</div>
<div class="card-footer text-center">
<button class="btn btn-sm btn-primary view-full-image"
data-image-url="{{ url_for('frame_image', video_folder=video_folder, frame_file=frame.filename) }}">
<i class="bi bi-zoom-in"></i> 查看大图
</button>
</div>
</div>
</div>
{% endfor %}
</div>
<div id="list-view" class="frame-container">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th><i class="bi bi-hash"></i> 帧号</th>
<th><i class="bi bi-clock"></i> 时间戳</th>
<th><i class="bi bi-tag"></i> 检测类别</th>
<th><i class="bi bi-image"></i> 预览</th>
<th><i class="bi bi-gear"></i> 操作</th>
</tr>
</thead>
<tbody>
{% for frame in frames %}
<tr class="frame-item" data-frame-number="{{ frame.frame_number }}" data-classes="{{ frame.classes|join(' ') }}">
<td>{{ frame.frame_number }}</td>
<td>{{ frame.timestamp }}</td>
<td>
{% for class in frame.classes %}
<span class="badge bg-primary me-1">{{ class }}</span>
{% endfor %}
</td>
<td>
<img src="{{ url_for('frame_image', video_folder=video_folder, frame_file=frame.filename) }}"
class="img-thumbnail" style="max-height: 50px;" alt="帧 #{{ frame.frame_number }}"
loading="lazy">
</td>
<td>
<button class="btn btn-sm btn-primary view-full-image"
data-image-url="{{ url_for('frame_image', video_folder=video_folder, frame_file=frame.filename) }}">
<i class="bi bi-zoom-in"></i> 查看
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i> 此视频中没有检测到任何帧。
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- 图片查看模态框 -->
<div class="modal fade" id="imageModal" tabindex="-1" aria-labelledby="imageModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="imageModalLabel">检测帧详情</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<img src="" id="modalImage" class="img-fluid" alt="检测帧大图">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 时间线图表
const ctx = document.getElementById('timelineChart').getContext('2d');
// 从帧数据中提取时间线信息
const frameNumbers = [];
const timestamps = [];
const classes = [];
{% for frame in frames %}
frameNumbers.push({{ frame.frame_number }});
timestamps.push('{{ frame.timestamp }}');
classes.push('{{ frame.classes|join(", ") }}');
{% endfor %}
const chart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: '检测帧',
data: frameNumbers.map((frame, index) => ({
x: index,
y: frame
})),
backgroundColor: 'rgba(54, 162, 235, 0.7)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1,
pointRadius: 5,
pointHoverRadius: 7
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: '帧号'
}
},
x: {
title: {
display: true,
text: '检测序号'
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
const index = context.dataIndex;
return [
`帧号: ${frameNumbers[index]}`,
`时间: ${timestamps[index]}`,
`类别: ${classes[index]}`
];
}
}
},
title: {
display: true,
text: '视频检测时间线'
}
}
}
});
// 视图切换
const gridViewBtn = document.getElementById('grid-view-btn');
const listViewBtn = document.getElementById('list-view-btn');
const gridView = document.getElementById('grid-view');
const listView = document.getElementById('list-view');
gridViewBtn.addEventListener('click', function() {
gridView.style.display = 'flex';
listView.style.display = 'none';
gridViewBtn.classList.add('active');
listViewBtn.classList.remove('active');
});
listViewBtn.addEventListener('click', function() {
gridView.style.display = 'none';
listView.style.display = 'block';
listViewBtn.classList.add('active');
gridViewBtn.classList.remove('active');
});
// 帧搜索功能
const frameSearch = document.getElementById('frame-search');
const frameItems = document.querySelectorAll('.frame-item');
frameSearch.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
frameItems.forEach(item => {
const frameNumber = item.getAttribute('data-frame-number');
const classes = item.getAttribute('data-classes').toLowerCase();
if (frameNumber.includes(searchTerm) || classes.includes(searchTerm)) {
item.style.display = '';
} else {
item.style.display = 'none';
}
});
});
// 图片查看模态框
const viewFullImageBtns = document.querySelectorAll('.view-full-image');
const modalImage = document.getElementById('modalImage');
const imageModal = new bootstrap.Modal(document.getElementById('imageModal'));
viewFullImageBtns.forEach(btn => {
btn.addEventListener('click', function() {
const imageUrl = this.getAttribute('data-image-url');
modalImage.src = imageUrl;
imageModal.show();
});
});
});
</script>
{% endblock %}
{% block scripts %}
<script>
// 创建检测时间线图表
const timelineCtx = document.getElementById('detectionTimelineChart').getContext('2d');
// 准备数据
const timestamps = [];
const detectionCounts = [];
{% for detection in detection_data.detections %}
timestamps.push({{ detection.timestamp }});
detectionCounts.push({{ detection.detections|length }});
{% endfor %}
new Chart(timelineCtx, {
type: 'line',
data: {
labels: timestamps,
datasets: [{
label: '检测到的目标数量',
data: detectionCounts,
borderColor: 'rgba(75, 192, 192, 1)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderWidth: 2,
pointRadius: 4,
pointBackgroundColor: 'rgba(75, 192, 192, 1)',
fill: true,
tension: 0.1
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: '检测时间线'
},
tooltip: {
callbacks: {
title: function(tooltipItems) {
return '时间: ' + tooltipItems[0].label + '秒';
}
}
}
},
scales: {
x: {
title: {
display: true,
text: '时间 (秒)'
}
},
y: {
beginAtZero: true,
title: {
display: true,
text: '检测目标数量'
},
ticks: {
stepSize: 1
}
}
}
}
});
</script>
{% endblock %}