149 lines
5.0 KiB
C++
149 lines
5.0 KiB
C++
#include "renderer.hpp"
|
|
#include "../common/logger.hpp"
|
|
#include <sstream>
|
|
|
|
namespace pipeline {
|
|
|
|
bool Renderer::init(const renderer::RendererConfig& config) {
|
|
if (initialized_) {
|
|
Logger::warning("Renderer already initialized");
|
|
return true;
|
|
}
|
|
|
|
config_ = config;
|
|
initialized_ = true;
|
|
last_metrics_update_ = std::chrono::steady_clock::now();
|
|
|
|
// 如果不是测试模式,创建显示窗口
|
|
if (!config_.test_mode) {
|
|
cv::namedWindow(config_.window_name, cv::WINDOW_NORMAL);
|
|
cv::resizeWindow(config_.window_name, config_.window_width, config_.window_height);
|
|
if (config_.fullscreen) {
|
|
cv::setWindowProperty(config_.window_name, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
|
|
}
|
|
}
|
|
|
|
Logger::info("Renderer initialized successfully");
|
|
return true;
|
|
}
|
|
|
|
bool Renderer::render(const cv::Mat& frame,
|
|
const std::vector<renderer::DetectionResult>& results,
|
|
const PerformanceMetrics& metrics) {
|
|
if (!initialized_) {
|
|
Logger::error("Renderer not initialized");
|
|
return false;
|
|
}
|
|
|
|
if (frame.empty()) {
|
|
Logger::error("Input frame is empty");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
// 如果渲染功能被禁用,直接返回原始帧的副本
|
|
if (!config_.enable) {
|
|
Logger::info("Rendering is disabled, returning original frame");
|
|
last_frame_ = frame.clone();
|
|
return true;
|
|
}
|
|
|
|
Logger::info("Rendering is enabled, processing frame");
|
|
// 创建帧的副本用于绘制
|
|
cv::Mat display_frame = frame.clone();
|
|
|
|
// 绘制检测结果
|
|
drawDetections(display_frame, results);
|
|
|
|
// 绘制性能指标
|
|
if (config_.metrics.show_fps ||
|
|
config_.metrics.show_inference_time ||
|
|
config_.metrics.show_gpu_usage) {
|
|
drawMetrics(display_frame, metrics);
|
|
}
|
|
|
|
// 显示或保存结果
|
|
if (!config_.test_mode) {
|
|
cv::imshow(config_.window_name, display_frame);
|
|
cv::waitKey(1);
|
|
}
|
|
last_frame_ = display_frame; // 保存最后渲染的帧
|
|
|
|
return true;
|
|
} catch (const cv::Exception& e) {
|
|
Logger::error("OpenCV error in render: " + std::string(e.what()));
|
|
return false;
|
|
} catch (const std::exception& e) {
|
|
Logger::error("Error in render: " + std::string(e.what()));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void Renderer::drawDetections(cv::Mat& frame, const std::vector<renderer::DetectionResult>& results) {
|
|
for (const auto& det : results) {
|
|
// 获取类别样式
|
|
const auto& style = config_.class_styles.count(det.label) > 0 ?
|
|
config_.class_styles.at(det.label) :
|
|
config_.default_style;
|
|
|
|
// 绘制边界框
|
|
cv::rectangle(frame, det.bbox, style.box_color, style.box_thickness);
|
|
|
|
// 准备标签文本
|
|
std::stringstream ss;
|
|
ss << det.label << " " << std::fixed << std::setprecision(2) << det.confidence;
|
|
std::string label_text = ss.str();
|
|
|
|
// 绘制标签背景
|
|
cv::Point text_pos(det.bbox.x, det.bbox.y - 5);
|
|
cv::Size text_size = cv::getTextSize(label_text, cv::FONT_HERSHEY_SIMPLEX,
|
|
style.font_scale, style.font_thickness, nullptr);
|
|
cv::rectangle(frame,
|
|
cv::Point(text_pos.x, text_pos.y - text_size.height),
|
|
cv::Point(text_pos.x + text_size.width, text_pos.y + 5),
|
|
style.box_color, -1);
|
|
|
|
// 绘制标签文本
|
|
drawText(frame, label_text, text_pos, style);
|
|
}
|
|
}
|
|
|
|
void Renderer::drawMetrics(cv::Mat& frame, const PerformanceMetrics& metrics) {
|
|
const auto& style = config_.default_style;
|
|
int y_offset = 30;
|
|
|
|
if (config_.metrics.show_fps) {
|
|
std::stringstream ss;
|
|
ss << "FPS: " << std::fixed << std::setprecision(1) << metrics.fps;
|
|
drawText(frame, ss.str(), cv::Point(10, y_offset), style);
|
|
y_offset += 30;
|
|
}
|
|
|
|
if (config_.metrics.show_inference_time) {
|
|
std::stringstream ss;
|
|
ss << "Inference: " << std::fixed << std::setprecision(1) << metrics.inference_time_ms << "ms";
|
|
drawText(frame, ss.str(), cv::Point(10, y_offset), style);
|
|
y_offset += 30;
|
|
}
|
|
|
|
if (config_.metrics.show_gpu_usage) {
|
|
std::stringstream ss;
|
|
ss << "GPU: " << std::fixed << std::setprecision(1) << metrics.gpu_usage_percent << "%";
|
|
drawText(frame, ss.str(), cv::Point(10, y_offset), style);
|
|
}
|
|
}
|
|
|
|
void Renderer::drawText(cv::Mat& frame, const std::string& text, const cv::Point& pos,
|
|
const renderer::RendererConfig::ClassStyle& style) {
|
|
cv::putText(frame, text, pos, cv::FONT_HERSHEY_SIMPLEX, style.font_scale,
|
|
style.text_color, style.font_thickness);
|
|
}
|
|
|
|
void Renderer::cleanup() {
|
|
if (initialized_ && !config_.test_mode) {
|
|
cv::destroyWindow(config_.window_name);
|
|
}
|
|
initialized_ = false;
|
|
}
|
|
|
|
} // namespace pipeline
|