当前位置:   article > 正文

yolov5 obb旋转框 tensorrt8.4 生成dll供c# 调用。win10。vs2019_windows tensorrt yolov5_obb

windows tensorrt yolov5_obb

1.首先生成自己的engine文件

yolov5 obb 旋转框 tensorrt 部署踩坑,c++,win10,cuda 11.7,tensorrt 8.4,opencv4.5.5_vokxchh的博客-CSDN博客https://blog.csdn.net/vokxchh/article/details/1307896192.修改文件yolov5_use.cpp

  1. #include <iostream>
  2. #include <chrono>
  3. #include <cmath>
  4. #include "cuda_utils.h"
  5. #include "logging.h"
  6. #include "common.hpp"
  7. #include<string>
  8. #include "yolov5_obb_dll.h"
  9. #define USE_FP16 // set USE_INT8 or USE_FP16 or USE_FP32
  10. #define DEVICE 0 // GPU id
  11. #define NMS_THRESH 0.1
  12. #define CONF_THRESH 0.1
  13. #define objThreshold 0.1
  14. #define BATCH_SIZE 1
  15. #define MAX_IMAGE_INPUT_SIZE_THRESH 3000 * 3000 // ensure it exceed the maximum size in the input images !
  16. using namespace std;
  17. // stuff we know about the network and the input/output blobs
  18. static const int INPUT_H = Yolo::INPUT_H;
  19. static const int INPUT_W = Yolo::INPUT_W;
  20. static const int CLASS_NUM = Yolo::CLASS_NUM;
  21. static const int OUTPUT_SIZE = Yolo::MAX_OUTPUT_BBOX_COUNT * sizeof(Yolo::Detection) / sizeof(float) + 1; // we assume the yololayer outputs no more than MAX_OUTPUT_BBOX_COUNT boxes that conf >= 0.1
  22. const char* INPUT_BLOB_NAME = "data";
  23. const char* OUTPUT_BLOB_NAME = "prob";
  24. const bool keep_ratio = true;
  25. static Logger gLogger;
  26. using namespace cv;
  27. using namespace std;
  28. typedef struct BoxInfo
  29. {
  30. RotatedRect box;
  31. float score;
  32. int label;
  33. } BoxInfo;
  34. cv::Mat resize_image(cv::Mat srcimg, int *newh, int *neww, int *top, int *left)
  35. {
  36. int srch = srcimg.rows, srcw = srcimg.cols;
  37. *newh = INPUT_H;
  38. *neww = INPUT_W;
  39. cv::Mat dstimg;
  40. if (keep_ratio && srch != srcw) {
  41. float hw_scale = (float)srch / srcw;
  42. if (hw_scale > 1) {
  43. *newh = INPUT_H;
  44. *neww = INPUT_W;
  45. cv::resize(srcimg, dstimg, Size(*neww, *newh), INTER_AREA);
  46. *left = int((INPUT_W - *neww) * 0.5);
  47. cv::copyMakeBorder(dstimg, dstimg, 0, 0, *left, INPUT_W - *neww - *left, BORDER_CONSTANT, 114);
  48. }
  49. else {
  50. *newh = (int)INPUT_H * hw_scale;
  51. *neww = INPUT_W;
  52. cv::resize(srcimg, dstimg, Size(*neww, *newh), INTER_AREA);
  53. *top = (int)(INPUT_H - *newh) * 0.5;
  54. cv::copyMakeBorder(dstimg, dstimg, *top, INPUT_H - *newh - *top, 0, 0, BORDER_CONSTANT, 114);
  55. }
  56. }
  57. else {
  58. resize(srcimg, dstimg, Size(*neww, *newh), INTER_AREA);
  59. }
  60. return dstimg;
  61. }
  62. void nms_angle(vector<BoxInfo>& input_boxes)
  63. {
  64. sort(input_boxes.begin(), input_boxes.end(), [](BoxInfo a, BoxInfo b) { return a.score > b.score; });
  65. vector<float> vArea(input_boxes.size());
  66. for (int i = 0; i < int(input_boxes.size()); ++i)
  67. {
  68. vArea[i] = input_boxes[i].box.size.area();
  69. }
  70. vector<bool> isSuppressed(input_boxes.size(), false);
  71. for (int i = 0; i < int(input_boxes.size()); ++i)
  72. {
  73. if (isSuppressed[i]) { continue; }
  74. for (int j = i + 1; j < int(input_boxes.size()); ++j)
  75. {
  76. if (isSuppressed[j]) { continue; }
  77. vector<Point2f> intersectingRegion;
  78. rotatedRectangleIntersection(input_boxes[i].box, input_boxes[j].box, intersectingRegion);
  79. if (intersectingRegion.empty()) { continue; }
  80. float inter = contourArea(intersectingRegion);
  81. float ovr = inter / (vArea[i] + vArea[j] - inter);
  82. if (ovr >= NMS_THRESH)
  83. {
  84. isSuppressed[j] = true;
  85. }
  86. }
  87. }
  88. // return post_nms;
  89. int idx_t = 0;
  90. input_boxes.erase(remove_if(input_boxes.begin(), input_boxes.end(), [&idx_t, &isSuppressed](const BoxInfo& f) { return isSuppressed[idx_t++]; }), input_boxes.end());
  91. }
  92. void doInference(IExecutionContext& context, cudaStream_t& stream, void **buffers, float* input, float* output, int batchSize) {
  93. CUDA_CHECK(cudaMemcpyAsync(buffers[0], input, batchSize * 3 * INPUT_H * INPUT_W * sizeof(float), cudaMemcpyHostToDevice, stream));// °ÑÕâ¸öÈÎÎñͨ¹ýcudaMemcpyAsync·Åµ½cudastramÉÏ
  94. // infer on the batch asynchronously, and DMA output back to host
  95. context.enqueue(batchSize, buffers, stream, nullptr);
  96. CUDA_CHECK(cudaMemcpyAsync(output, buffers[1], batchSize * OUTPUT_SIZE * sizeof(float), cudaMemcpyDeviceToHost, stream));
  97. cudaStreamSynchronize(stream);
  98. }
  99. IExecutionContext* context = nullptr;
  100. cudaStream_t stream;
  101. float* buffers[2];
  102. static float prob[BATCH_SIZE * OUTPUT_SIZE];
  103. ICudaEngine* engine = nullptr;
  104. int Init(std::string engine_name0)
  105. {
  106. cudaSetDevice(DEVICE);
  107. std::string engine_name = engine_name0;
  108. // deserialize the .engine and run inference
  109. std::ifstream file(engine_name, std::ios::binary);
  110. if (!file.good()) {
  111. std::cerr << "read " << engine_name << " error!" << std::endl;
  112. return -1;
  113. }
  114. char* trtModelStream = nullptr;
  115. size_t size = 0;
  116. file.seekg(0, file.end);
  117. size = file.tellg();
  118. file.seekg(0, file.beg);
  119. trtModelStream = new char[size];
  120. assert(trtModelStream);
  121. file.read(trtModelStream, size);
  122. file.close();
  123. IRuntime* runtime = createInferRuntime(gLogger);
  124. assert(runtime != nullptr);
  125. engine = runtime->deserializeCudaEngine(trtModelStream, size);
  126. assert(engine != nullptr);
  127. context = engine->createExecutionContext();
  128. assert(context != nullptr);
  129. delete[] trtModelStream;
  130. assert(engine->getNbBindings() == 2);
  131. // In order to bind the buffers, we need to know the names of the input and output tensors.
  132. // Note that indices are guaranteed to be less than IEngine::getNbBindings()
  133. const int inputIndex = engine->getBindingIndex(INPUT_BLOB_NAME);
  134. const int outputIndex = engine->getBindingIndex(OUTPUT_BLOB_NAME);
  135. assert(inputIndex == 0);
  136. assert(outputIndex == 1);
  137. // Create GPU buffers on device
  138. CUDA_CHECK(cudaMalloc((void**)&buffers[inputIndex], BATCH_SIZE * 3 * INPUT_H * INPUT_W * sizeof(float)));
  139. CUDA_CHECK(cudaMalloc((void**)&buffers[outputIndex], BATCH_SIZE * OUTPUT_SIZE * sizeof(float)));
  140. // Create stream
  141. CUDA_CHECK(cudaStreamCreate(&stream));
  142. uint8_t* img_host = nullptr;
  143. uint8_t* img_device = nullptr;
  144. // prepare input data cache in pinned memory
  145. CUDA_CHECK(cudaMallocHost((void**)&img_host, MAX_IMAGE_INPUT_SIZE_THRESH * 3));
  146. // prepare input data cache in device memory
  147. CUDA_CHECK(cudaMalloc((void**)&img_device, MAX_IMAGE_INPUT_SIZE_THRESH * 3));
  148. }
  149. void detect_yolov5_trt(cv::Mat img0, std::string engine_name, Result* stu)
  150. {
  151. static float data[1 * 3 * INPUT_H * INPUT_W];
  152. cv::Mat pr_img = img0;
  153. int newh = 0, neww = 0, padh = 0, padw = 0;
  154. Mat img = resize_image(pr_img, &newh, &neww, &padh, &padw);
  155. int i = 0;
  156. int b = 0;//Õâ¸öbÔ­±¾ÓÃÀ´¿ØÖÆbatchsizeµÄ£¬µ«ÊÇÎÒÃÇÖ»ÓÐÒ»ÕÅͼƬ ¾ÍÉèÖóÉÁË0
  157. for (int row = 0; row < INPUT_H; ++row)
  158. {
  159. uchar* uc_pixel = img.data + row * img.step;
  160. for (int col = 0; col < INPUT_W; ++col)
  161. {
  162. data[b * 3 * INPUT_H * INPUT_W + i] = (float)uc_pixel[2] / 255.0;
  163. data[b * 3 * INPUT_H * INPUT_W + i + INPUT_H * INPUT_W] = (float)uc_pixel[1] / 255.0;
  164. data[b * 3 * INPUT_H * INPUT_W + i + 2 * INPUT_H * INPUT_W] = (float)uc_pixel[0] / 255.0;
  165. uc_pixel += 3;
  166. ++i;
  167. }
  168. }
  169. //auto start = std::chrono::system_clock::now();
  170. doInference(*context, stream, (void**)buffers, data, prob, 1);
  171. //auto end = std::chrono::system_clock::now();
  172. //auto costtime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
  173. //std::cout << "inference time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
  174. vector<BoxInfo> generate_boxes;
  175. float ratioh = (float)pr_img.rows / newh, ratiow = (float)pr_img.cols / neww;
  176. float* pdata = (float*)prob;
  177. int det_size = 7;//box(4)+conf +classid + classangle
  178. for (int i = 0; i < pdata[0] && i < Yolo::MAX_OUTPUT_BBOX_COUNT; i++) {
  179. if (pdata[7 * i + 4 + 1] <= CONF_THRESH) continue;//ÕâÀïÄã»áºÜÆæ¹ÖΪʲô´Ópdata[5]ÊÇconf ÒòΪpdata[0]´æ·ÅµÄÊÇ0£¬´ú±íµÚÒ»¸öͼƬ
  180. Yolo::Detection det;
  181. memcpy(&det, &pdata[1 + det_size * i], det_size * sizeof(float));
  182. float max_class_socre = det.conf;//ÖÃÐŶÈ
  183. if (max_class_socre > CONF_THRESH)
  184. {
  185. float cx = (det.bbox[0] - padw) * ratiow;
  186. float cy = (det.bbox[1] - padh) * ratioh;
  187. float w = det.bbox[2] * ratiow;
  188. float h = det.bbox[3] * ratioh;
  189. int class_idx = det.class_id;
  190. float angle = 90 - det.angle_id;
  191. RotatedRect box = RotatedRect(Point2f(cx, cy), Size2f(w, h), angle);
  192. generate_boxes.push_back(BoxInfo{ box, (float)max_class_socre, class_idx });
  193. }
  194. }
  195. nms_angle(generate_boxes);
  196. for (size_t i = 0; i < generate_boxes.size(); ++i)
  197. {
  198. RotatedRect rectInput = generate_boxes[i].box;
  199. std::cout << "box center:" << generate_boxes[i].box.center << " angle:" << generate_boxes[i].box.angle << std::endl;
  200. Point2f* vertices = new cv::Point2f[4];
  201. rectInput.points(vertices);
  202. stu[i].x1 = vertices[0].x;
  203. stu[i].y1 = vertices[0].y;
  204. stu[i].x2 = vertices[1].x;
  205. stu[i].y2 = vertices[1].y;
  206. stu[i].x3 = vertices[2].x;
  207. stu[i].y3 = vertices[2].y;
  208. stu[i].x4 = vertices[3].x;
  209. stu[i].y4 = vertices[3].y;
  210. stu[i].conf = generate_boxes[i].score;
  211. stu[i].classid = generate_boxes[i].label;
  212. stu[i].angel = generate_boxes[i].box.angle;
  213. }
  214. }
  215. const bool yolov5_obb_trt(const char* img_dir, const char* eng_dir, Result* stu)
  216. {
  217. std::string img_dir2 = img_dir;
  218. std::string engine_name = eng_dir;
  219. if (engine == nullptr) Init(engine_name);
  220. cv::Mat img = cv::imread(img_dir2);
  221. detect_yolov5_trt(img, engine_name, stu);
  222. return 0;
  223. }
  224. const void yolov5_obb_trt2(uchar* data, int width, int height, int stride, const char* eng_dir, Result* stu)
  225. {
  226. std::string engine_name = eng_dir;
  227. if (engine == nullptr) Init(engine_name);
  228. cv::Mat img = cv::Mat(cv::Size(width, height), CV_8UC3, data, stride);
  229. detect_yolov5_trt(img, engine_name, stu);
  230. }

3.添加 yolov5_obb_dll.h

  1. #pragma once
  2. struct Result
  3. {
  4. float classid;
  5. float conf;
  6. float x1;
  7. float y1;
  8. float x2;
  9. float y2;
  10. float x3;
  11. float y3;
  12. float x4;
  13. float y4;
  14. float angel;
  15. };
  16. extern "C" _declspec(dllexport) const bool yolov5_obb_trt(const char* img_dir, const char* eng_dir, Result * stu);
  17. extern "C" _declspec(dllexport) const void yolov5_obb_trt2(uchar * data, int width, int height, int stride, const char* eng_dir, Result * stu);

4.编译生成dll

5.使用c# 调用dll

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Runtime.InteropServices;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14. using static System.Net.WebRequestMethods;
  15. namespace WindowsFormsApp5
  16. {
  17. public partial class Form1 : Form
  18. {
  19. public Form1()
  20. {
  21. InitializeComponent();
  22. }
  23. [DllImport("yolov5_obb_trt.dll", CallingConvention = CallingConvention.Cdecl,CharSet = CharSet.Ansi)]
  24. extern static bool yolov5_obb_trt(string imgdr,string engdr,[Out] Result[] re);//发送路径
  25. [DllImport("yolov5_obb_trt.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  26. extern static bool yolov5_obb_trt2(IntPtr data, int width, int height, int stride, string engdr, [Out] Result[] re);//发送图片
  27. [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
  28. public struct Result
  29. {
  30. public float classid;
  31. public float conf;
  32. public float x1;
  33. public float y1;
  34. public float x2;
  35. public float y2;
  36. public float x3;
  37. public float y3;
  38. public float x4;
  39. public float y4;
  40. public float angel;
  41. }
  42. public static string engdr = Environment.CurrentDirectory + "\\yolov5n-obb-fp16.engine";
  43. public Bitmap DrawRect(Bitmap bmp, Result[] re)
  44. {
  45. Graphics gg = Graphics.FromImage(bmp);
  46. Pen p = new Pen(Brushes.Lime);
  47. foreach (var i in re)
  48. {
  49. if (i.conf == 0) { break; }
  50. gg.DrawLine (p, i.x1, i.y1, i.x2, i.y2);
  51. gg.DrawLine(p, i.x2, i.y2, i.x3, i.y3);
  52. gg.DrawLine(p, i.x3, i.y3, i.x4, i.y4);
  53. gg.DrawLine(p, i.x4, i.y4, i.x1, i.y1);
  54. Font drawFont = new Font("Arial", 8, FontStyle.Bold, GraphicsUnit.Millimeter);
  55. SolidBrush drawBush = new SolidBrush(Color.Lime);
  56. gg.DrawString(coco[(int)i.classid]+" "+i.conf.ToString("0.000"), drawFont, drawBush, i.x1, i.y1);
  57. }
  58. gg.Dispose();
  59. return bmp;
  60. }
  61. Result[] yolov5_sendbmp(string path)//发送图片
  62. {
  63. Result[] re = new Result[100];
  64. Bitmap img = new Bitmap(path);
  65. BitmapData imgData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite,
  66. PixelFormat.Format24bppRgb);
  67. int width = imgData.Width;
  68. int height = imgData.Height;
  69. int stride = imgData.Stride;
  70. try
  71. {
  72. yolov5_obb_trt2(imgData.Scan0, width, height, stride, engdr, re);
  73. }
  74. catch (Exception ex)
  75. {
  76. MessageBox.Show(ex.ToString());
  77. }
  78. img.UnlockBits(imgData);
  79. DrawRect(img, re);
  80. pictureBox1.Image =img;
  81. return re;
  82. }
  83. private void button1_Click(object sender, EventArgs e)//发送图片的路径
  84. {
  85. Result[] re = new Result[100];
  86. label1.Text = "";
  87. Stopwatch stp = new Stopwatch();
  88. string imgdr = Environment.CurrentDirectory + "\\images\\OK_00004.bmp";
  89. stp.Start();
  90. yolov5_obb_trt(imgdr,engdr,re);
  91. stp.Stop();
  92. Bitmap bp=(Bitmap)Image.FromFile(imgdr);
  93. DrawRect(bp, re);
  94. pictureBox1.Image = bp;
  95. label1.Text ="耗时:"+ stp.ElapsedMilliseconds.ToString() + "ms";
  96. }
  97. private void button2_Click(object sender, EventArgs e)//直接发送图片
  98. {
  99. label1.Text = "";
  100. Stopwatch stp = new Stopwatch();
  101. string imgdr = Environment.CurrentDirectory + "\\images\\OK_00408.bmp";
  102. stp.Start();
  103. yolov5_sendbmp(imgdr);
  104. stp.Stop();
  105. label1.Text = "耗时:"+ stp.ElapsedMilliseconds.ToString() + "ms";
  106. }
  107. string[] coco;
  108. private void Form1_Load(object sender, EventArgs e)
  109. {
  110. Task.Run(() =>
  111. {
  112. coco = System.IO.File.ReadAllLines(Environment.CurrentDirectory + "\\coco.names");
  113. Result[] re = new Result[100];
  114. string imgdr = Environment.CurrentDirectory + "\\images\\OK_00002.bmp";
  115. yolov5_obb_trt(imgdr, engdr, re);//先载入一次,预热。
  116. Bitmap bp = (Bitmap)Image.FromFile(imgdr);
  117. DrawRect(bp, re);
  118. pictureBox1.Image = bp;
  119. this.BeginInvoke(new MethodInvoker(delegate ()
  120. {
  121. button1.Visible = true;
  122. button2.Visible = true;
  123. label1.Text = "载入完毕";
  124. }));
  125. });
  126. }
  127. private void button3_Click(object sender, EventArgs e)
  128. {
  129. richTextBox1.Clear();
  130. StringBuilder sb=new StringBuilder();
  131. for (int i = 0; i < 100; i++)
  132. {
  133. Result[] re = new Result[100];
  134. label1.Text = "";
  135. Stopwatch stp = new Stopwatch();
  136. string imgdr = Environment.CurrentDirectory + "\\images\\OK_00004.bmp";
  137. stp.Start();
  138. yolov5_obb_trt(imgdr, engdr, re);
  139. stp.Stop();
  140. sb.Append(stp.ElapsedMilliseconds.ToString()+"ms\r\n");
  141. }
  142. richTextBox1.AppendText(sb.ToString());
  143. }
  144. }
  145. }

结果是一样的。 RTX 2060 FP16推理速度, 15ms。

-------------------------------------------------------------------------------

完整代码如下

yolov5obb旋转框tensorrt8.4生成dll供c#调用摄像头实时win10vs2019资源-CSDN文库icon-default.png?t=N4HBhttps://download.csdn.net/download/vokxchh/87804850

注意点:

1.修改包含目录和库目录。自己对应的。

2.dll需要覆盖,用自己的版本,我的tensorrt8.4   opencv4.5.5,改了opencv的话,注意附加依赖项。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/311691
推荐阅读
相关标签
  

闽ICP备14008679号