yolov5C++onnxruntimeGPU.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include <iostream>
  2. #include <opencv2/opencv.hpp>
  3. #include <onnxruntime_cxx_api.h>
  4. #include <vector>
  5. #include <string>
  6. #include <algorithm>
  7. #include <numeric>
  8. #include <sstream>
  9. using cv::Mat;
  10. using std::cout;
  11. using std::endl;
  12. using std::string;
  13. using std::vector;
  14. static const vector<string> class_name = { "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
  15. "fire hydrant","stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
  16. "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
  17. "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
  18. "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
  19. "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
  20. "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
  21. "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
  22. "hair drier", "toothbrush" };
  23. vector<vector<float>> get_info(const Mat& result, float conf = 0.5, int len_data = 85)
  24. {
  25. float* pdata = (float*)result.data;
  26. vector<vector<float>> info;
  27. for (int i = 0; i < result.total() / len_data; i++)
  28. {
  29. if (pdata[4] >= conf)
  30. {
  31. vector<float> line_data(pdata, pdata + len_data);
  32. info.push_back(line_data);
  33. }
  34. pdata += len_data;
  35. }
  36. return info;
  37. }
  38. void info_simplify(vector<vector<float>>& info)
  39. {
  40. for (auto& entry : info)
  41. {
  42. entry[5] = std::max_element(entry.begin() + 5, entry.end()) - entry.begin() - 5;
  43. entry.resize(6);
  44. float x = entry[0];
  45. float y = entry[1];
  46. float w = entry[2];
  47. float h = entry[3];
  48. entry[0] = x - w / 2.0;
  49. entry[1] = y - h / 2.0;
  50. entry[2] = x + w / 2.0;
  51. entry[3] = y + h / 2.0;
  52. }
  53. }
  54. vector<vector<vector<float>>> split_info(vector<vector<float>>& info)
  55. {
  56. vector<vector<vector<float>>> info_split;
  57. vector<int> class_id;
  58. for (const auto& entry : info)
  59. {
  60. int classIndex = static_cast<int>(entry[5]);
  61. if (std::find(class_id.begin(), class_id.end(), classIndex) == class_id.end())
  62. {
  63. class_id.push_back(classIndex);
  64. info_split.emplace_back();
  65. }
  66. info_split[std::find(class_id.begin(), class_id.end(), classIndex) - class_id.begin()].push_back(entry);
  67. }
  68. return info_split;
  69. }
  70. void nms(vector<vector<float>>& info, float iou = 0.5)
  71. {
  72. std::sort(info.begin(), info.end(), [](vector<float> p1, vector<float> p2) {
  73. return p1[4] > p2[4];
  74. });
  75. vector<vector<float>> return_info;
  76. vector<bool> suppressed(info.size(), false);
  77. for (size_t i = 0; i < info.size(); i++)
  78. {
  79. if (suppressed[i]) continue;
  80. return_info.push_back(info[i]);
  81. float x1 = info[i][0], y1 = info[i][1], x2 = info[i][2], y2 = info[i][3];
  82. for (size_t j = i + 1; j < info.size(); j++)
  83. {
  84. if (suppressed[j]) continue;
  85. float interX1 = std::max(x1, info[j][0]);
  86. float interY1 = std::max(y1, info[j][1]);
  87. float interX2 = std::min(x2, info[j][2]);
  88. float interY2 = std::min(y2, info[j][3]);
  89. float interArea = std::max(0.0f, interX2 - interX1) * std::max(0.0f, interY2 - interY1);
  90. float totalArea = (x2 - x1) * (y2 - y1) + (info[j][2] - info[j][0]) * (info[j][3] - info[j][1]) - interArea;
  91. if (interArea / totalArea > iou)
  92. {
  93. suppressed[j] = true;
  94. }
  95. }
  96. }
  97. info = std::move(return_info);
  98. }
  99. void draw_box(Mat& img, const vector<vector<float>>& info)
  100. {
  101. for (int i = 0; i < info.size(); i++)
  102. {
  103. cv::Point topLeft(info[i][0], info[i][1]);
  104. cv::Point bottomRight(info[i][2], info[i][3]);
  105. int thickness = 2;
  106. cv::Scalar color(0, 255, 0);
  107. int lineType = cv::LINE_8;
  108. const int cornerRadius = 5;
  109. cv::rectangle(img, topLeft, bottomRight, color, thickness, lineType);
  110. string label = class_name[static_cast<int>(info[i][5])] + " " + std::to_string(info[i][4]);
  111. cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.6, 1, nullptr);
  112. cv::Rect textBgRect(topLeft.x, topLeft.y - textSize.height - 5, textSize.width + 10, textSize.height + 5);
  113. cv::rectangle(img, textBgRect, color, cv::FILLED);
  114. cv::putText(img, label, cv::Point(topLeft.x + 5, topLeft.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.6, CV_RGB(255, 255, 255), 2);
  115. }
  116. }
  117. int main() {
  118. try {
  119. Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "ONNXRuntime");
  120. Ort::SessionOptions session_options;
  121. OrtCUDAProviderOptions cuda_options;
  122. session_options.AppendExecutionProvider_CUDA(cuda_options);
  123. std::wstring model_path = L"D:/VisualStudio/test/Project1/Project1/yolov5s.onnx";
  124. Ort::Session session(env, model_path.c_str(), session_options);
  125. std::vector<std::string> input_names = { "input" };
  126. std::vector<std::string> output_names = { "output" };
  127. std::vector<const char*> input_names_cstr;
  128. std::vector<const char*> output_names_cstr;
  129. for (const auto& name : input_names) {
  130. input_names_cstr.push_back(name.c_str());
  131. }
  132. for (const auto& name : output_names) {
  133. output_names_cstr.push_back(name.c_str());
  134. }
  135. cv::VideoCapture cap(0);
  136. if (!cap.isOpened()) {
  137. cout << "Error: Cannot open the camera" << endl;
  138. return -1;
  139. }
  140. Ort::MemoryInfo memory_info("Cpu", OrtArenaAllocator, 0, OrtMemTypeDefault);
  141. while (true) {
  142. Mat img;
  143. cap >> img;
  144. if (img.empty()) break;
  145. cv::resize(img, img, cv::Size(640, 640));
  146. // Convert image to float and normalize
  147. Mat blob;
  148. img.convertTo(blob, CV_32F, 1.0 / 255.0);
  149. std::vector<float> input_tensor_values(blob.total());
  150. std::memcpy(input_tensor_values.data(), blob.data, blob.total() * sizeof(float));
  151. // Create ONNX Runtime tensor from input data
  152. std::vector<int64_t> input_node_dims = { 1, 3, 640, 640 };
  153. Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
  154. memory_info, input_tensor_values.data(), input_tensor_values.size(),
  155. input_node_dims.data(), input_node_dims.size());
  156. // Run inference
  157. auto output_tensors = session.Run(Ort::RunOptions{ nullptr },
  158. input_names_cstr.data(), &input_tensor, 1,
  159. output_names_cstr.data(), 1);
  160. // Get the result
  161. Ort::Value& output_tensor = output_tensors.front();
  162. auto output_shape = output_tensor.GetTensorTypeAndShapeInfo().GetShape();
  163. std::vector<float> output_data(output_tensor.GetTensorTypeAndShapeInfo().GetElementCount());
  164. // Print output shape for debugging
  165. cout << "Output Shape: ";
  166. for (const auto& dim : output_shape) {
  167. cout << dim << " ";
  168. }
  169. cout << endl;
  170. size_t expected_size = std::accumulate(output_shape.begin(), output_shape.end(), 1, std::multiplies<size_t>());
  171. if (output_data.size() != expected_size) {
  172. std::cerr << "Error: Output data size mismatch." << endl;
  173. return -1;
  174. }
  175. std::memcpy(output_data.data(), output_tensor.GetTensorData<float>(),
  176. output_data.size() * sizeof(float));
  177. // Print a portion of the output data for debugging
  178. cout << "Output Data (first 10 values): ";
  179. for (size_t i = 0; i < std::min(output_data.size(), static_cast<size_t>(10)); ++i) {
  180. cout << output_data[i] << " ";
  181. }
  182. cout << endl;
  183. Mat result(output_shape[2], output_shape[3], CV_32FC1, output_data.data());
  184. vector<vector<float>> info = get_info(result);
  185. info_simplify(info);
  186. vector<vector<vector<float>>> info_split = split_info(info);
  187. for (auto& split_info : info_split) {
  188. nms(split_info);
  189. draw_box(img, split_info);
  190. }
  191. cv::imshow("test", img);
  192. if (cv::waitKey(1) == 'q') break;
  193. }
  194. cap.release();
  195. cv::destroyAllWindows();
  196. }
  197. catch (const Ort::Exception& e) {
  198. cout << "ONNX Runtime error: " << e.what() << endl;
  199. return -1;
  200. }
  201. catch (const std::exception& e) {
  202. cout << "Standard exception: " << e.what() << endl;
  203. return -1;
  204. }
  205. return 0;
  206. }