rtsp_tensorrt/pipeline/inference/preprocess.cpp
sladro e13cb3659c feat: 初始化项目结构
- 创建基本项目结构和目录
- 添加CMake构建系统
- 实现基础的配置解析功能
- 添加YOLO推理框架支持
- 集成RTSP和视频流处理功能
- 添加性能监控和日志系统
2024-12-24 16:25:03 +08:00

150 lines
5.0 KiB
C++

#include "preprocess.hpp"
#include <opencv2/imgproc.hpp>
namespace pipeline {
// 声明GPU预处理函数
namespace detail {
bool preprocessGPU(const std::vector<cv::Mat>& images,
detail::CudaBuffer& output_buffer,
const std::vector<std::unique_ptr<detail::CudaBuffer>>& temp_buffers,
cudaStream_t stream,
float scale);
}
Preprocessor::Preprocessor(const Config& config)
: config_(config),
stream_(std::make_unique<detail::CudaStream>()) {
// 预分配临时缓冲区
if (config_.use_cuda) {
const size_t single_size = config_.input_shape[0] * config_.input_shape[1] *
config_.input_shape[2] * sizeof(float);
for (int i = 0; i < config_.max_batch_size; ++i) {
temp_buffers_.emplace_back(std::make_unique<detail::CudaBuffer>(single_size));
}
}
}
Preprocessor::~Preprocessor() = default;
bool Preprocessor::process(const std::vector<cv::Mat>& images, detail::CudaBuffer& output_buffer) {
try {
// 检查输入
if (!checkInput(images)) {
Logger::error("Invalid input for preprocessing");
return false;
}
// 根据配置选择处理方式
return config_.use_cuda ? processGPU(images, output_buffer)
: processCPU(images, output_buffer);
}
catch (const std::exception& e) {
Logger::error("Error in preprocessing: " + std::string(e.what()));
return false;
}
}
bool Preprocessor::checkInput(const std::vector<cv::Mat>& images) const {
if (images.empty() || images.size() > static_cast<size_t>(config_.max_batch_size)) {
return false;
}
for (const auto& img : images) {
if (img.empty() || img.type() != CV_8UC3) {
return false;
}
}
return true;
}
bool Preprocessor::processCPU(const std::vector<cv::Mat>& images, detail::CudaBuffer& output_buffer) {
const int batch_size = static_cast<int>(images.size());
const int target_height = config_.input_shape[1];
const int target_width = config_.input_shape[2];
// 获取输出缓冲区的主机内存指针
float* output_ptr = static_cast<float*>(output_buffer.hostPtr());
if (!output_ptr) {
Logger::error("Failed to get host pointer from output buffer");
return false;
}
// 处理每张图片
for (int i = 0; i < batch_size; ++i) {
float* current_output = output_ptr + i * target_height * target_width * 3;
if (!preprocessImageCPU(images[i], current_output, target_height, target_width)) {
Logger::error("Failed to preprocess image " + std::to_string(i));
return false;
}
}
// 将处理后的数据拷贝到设备内存
if (!output_buffer.copyH2D(stream_->get())) {
Logger::error("Failed to copy preprocessed data to device");
return false;
}
return stream_->sync();
}
bool Preprocessor::preprocessImageCPU(const cv::Mat& input, float* output,
int target_height, int target_width) {
try {
// 1. 缩放图像
cv::Mat resized;
cv::resize(input, resized, cv::Size(target_width, target_height), 0, 0, cv::INTER_LINEAR);
// 2. BGR转RGB并归一化
for (int h = 0; h < target_height; ++h) {
for (int w = 0; w < target_width; ++w) {
const cv::Vec3b& pixel = resized.at<cv::Vec3b>(h, w);
const int base_idx = (h * target_width + w) * 3;
// BGR转RGB并归一化到0-1
output[base_idx + 0] = pixel[2] * config_.scale; // R
output[base_idx + 1] = pixel[1] * config_.scale; // G
output[base_idx + 2] = pixel[0] * config_.scale; // B
}
}
return true;
}
catch (const std::exception& e) {
Logger::error("Error in CPU preprocessing: " + std::string(e.what()));
return false;
}
}
bool Preprocessor::processGPU(const std::vector<cv::Mat>& images, detail::CudaBuffer& output_buffer) {
try {
// 1. 缩放图像到目标尺寸
std::vector<cv::Mat> resized_images;
resized_images.reserve(images.size());
for (const auto& img : images) {
cv::Mat resized;
cv::resize(img, resized, cv::Size(config_.input_shape[2], config_.input_shape[1]),
0, 0, cv::INTER_LINEAR);
resized_images.push_back(resized);
}
// 2. 使用CUDA进行BGR转RGB和归一化
if (!detail::preprocessGPU(resized_images, output_buffer, temp_buffers_,
stream_->get(), config_.scale)) {
Logger::error("GPU preprocessing failed");
return false;
}
return stream_->sync();
}
catch (const std::exception& e) {
Logger::error("Error in GPU preprocessing: " + std::string(e.what()));
return false;
}
}
} // namespace pipeline