rtsp_tensorrt/pipeline/render/renderer.cpp

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