删除 video_results.html
This commit is contained in:
parent
c35cf7daaf
commit
14418af6bb
@ -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 %}
|
||||
Loading…
Reference in New Issue
Block a user