#include <fstream>
#include <iostream>
#include <sstream>
#include <opencv2/opencv.hpp>
#include "NvInfer.h"
using namespace nvinfer1;
using namespace cv;
class Logger : public ILogger
{
void log(Severity severity, const char* msg) noexcept
{
// suppress info-level messages
if (severity != Severity::kINFO)
std::cout << msg << std::endl;
}
} gLogger;
std::string labels_txt_file = "D:/pycharm/yolov5-7.0/classes.txt";
std::vector<std::string> readClassNames();
std::vector<std::string> readClassNames()
{
std::vector<std::string> classNames;
std::ifstream fp(labels_txt_file);
if (!fp.is_open())
{
printf("could not open file...\n");
exit(-1);
}
std::string name;
while (!fp.eof())
{
std::getline(fp, name);
if (name.length())
classNames.push_back(name);
}
fp.close();
return classNames;
}
int main(int argc, char** argv) {
std::vector<std::string> labels = readClassNames();
std::string enginepath = "D:/tensorrt/TensorRT-8.5.3.1/bin/yolov5s.engine";
std::ifstream file(enginepath, std::ios::binary);
char* trtModelStream = NULL;
int size = 0;
if (file.good()) {
file.seekg(0, file.end);
size = file.tellg();
file.seekg(0, file.beg);
trtModelStream = new char[size];
assert(trtModelStream);
file.read(trtModelStream, size);
file.close();
}
// 初始化几个对象
auto runtime = createInferRuntime(gLogger);
assert(runtime != nullptr);
auto engine = runtime->deserializeCudaEngine(trtModelStream, size);
assert(this->engine != nullptr);
auto context = engine->createExecutionContext();
assert(this->context != nullptr);
delete[] trtModelStream;
void* buffers[2] = { NULL, NULL };
std::vector<float> prob;
cudaStream_t stream;
int input_index = engine->getBindingIndex("images");
int output_index = engine->getBindingIndex("output0");
// 获取输入维度信息 NCHW=1*3*640*640
int input_h = engine->getBindingDimensions(input_index).d[2];
int input_w = engine->getBindingDimensions(input_index).d[3];
printf("inputH : %d, inputW: %d \n", input_h, input_w);
// 获取输出维度信息
int output_h = engine->getBindingDimensions(output_index).d[1];
int output_w = engine->getBindingDimensions(output_index).d[2];
std::cout << "out data format: " << output_h << "x" << output_w << std::endl;
// 创建GPU显存输入/输出缓冲区
std::cout << " input/outpu : " << engine->getNbBindings() << std::endl;
cudaMalloc(&buffers[input_index], input_h * input_w * 3 * sizeof(float));
cudaMalloc(&buffers[output_index], output_h *output_w * sizeof(float));
// 创建临时缓存输出
prob.resize(output_h * output_w);
// 创建cuda流
cudaStreamCreate(&stream);
int64 start = cv::getTickCount();
cv::Mat frame = cv::imread("D:/images/1.jpg");
//图像预处理-格式化操作
int w = frame.cols;
int h = frame.rows;
int _max = std::max(h, w);
cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);
cv::Rect roi(0, 0, w, h);
frame.copyTo(image(roi));
// HWC => CHW
float x_factor = image.cols / static_cast<float>(input_w);
float y_factor = image.rows / static_cast<float>(input_h);
cv::Mat tensor = cv::dnn::blobFromImage(image, 1.0f / 225.f, cv::Size(input_w, input_h), cv::Scalar(), true);
// 内存到GPU显存
cudaMemcpyAsync(buffers[0], tensor.ptr<float>(), input_h * input_w * 3 * sizeof(float), cudaMemcpyHostToDevice, stream);
// 推理
context->enqueueV2(buffers, stream, nullptr);
// GPU显存到内存
cudaMemcpyAsync(prob.data(), buffers[1], output_h *output_w * sizeof(float), cudaMemcpyDeviceToHost, stream);
// 后处理, 1x25200x85, 85 - box + conf, 80- min/max
std::vector<cv::Rect> boxes;
std::vector<int> classIds;
std::vector<float> confidences;
cv::Mat det_output(output_h, output_w, CV_32F, (float*)prob.data());
for (int i = 0; i < det_output.rows; i++) {
float confidence = det_output.at<float>(i, 4);
if (confidence < 0.45) {
continue;
}
cv::Mat classes_scores = det_output.row(i).colRange(5, output_w);
cv::Point classIdPoint;
double score;
minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);
// 置信度 0~1之间
if (score > 0.25)
{
float cx = det_output.at<float>(i, 0);
float cy = det_output.at<float>(i, 1);
float ow = det_output.at<float>(i, 2);
float oh = det_output.at<float>(i, 3);
int x = static_cast<int>((cx - 0.5 * ow) * x_factor);
int y = static_cast<int>((cy - 0.5 * oh) * y_factor);
int width = static_cast<int>(ow * x_factor);
int height = static_cast<int>(oh * y_factor);
cv::Rect box;
box.x = x;
box.y = y;
box.width = width;
box.height = height;
boxes.push_back(box);
classIds.push_back(classIdPoint.x);
confidences.push_back(score);
}
}
// NMS
std::vector<int> indexes;
cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);
for (size_t i = 0; i < indexes.size(); i++) {
int idx = indexes[i];
int cid = classIds[idx];
cv::rectangle(frame, boxes[idx], Scalar(0, 0, 255), 2, 8, 0);
putText(frame, labels[cid].c_str(), boxes[idx].tl(), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255, 0, 0), 1, 8);
}
// 计算FPS render it
float t = (cv::getTickCount() - start) / static_cast<float>(cv::getTickFrequency());
putText(frame, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
cv::imshow("TensorRT8.6 + YOLOv5 7.0推理演示", frame);
cv::waitKey(0);
// 同步结束,释放资源
cudaStreamSynchronize(stream);
cudaStreamDestroy(stream);
if (!context) {
context->destroy();
}
if (!engine) {
engine->destroy();
}
if (!runtime) {
runtime->destroy();
}
if (!buffers[0]) {
delete[] buffers;
}
return 0;
}