├── CppQt_OpenVINO_YOLOv8_Image_Classification ├── CMakeLists.txt ├── CppQt_OpenVINO_YOLOv8_Image_Classification.pro └── main.cpp ├── CppQt_OpenVINO_YOLOv8_Image_Detection ├── CMakeLists.txt ├── CppQt_OpenVINO_YOLOv8_Image_Detection.pro └── main.cpp ├── CppQt_OpenVINO_YOLOv8_Image_OBB ├── CMakeLists.txt ├── CppQt_OpenVINO_YOLOv8_Image_OBB.pro └── main.cpp ├── CppQt_OpenVINO_YOLOv8_Image_Pose ├── CMakeLists.txt ├── CppQt_OpenVINO_YOLOv8_Image_Pose.pro └── main.cpp ├── CppQt_OpenVINO_YOLOv8_Image_Segmentation ├── CMakeLists.txt ├── CppQt_OpenVINO_YOLOv8_Image_Segmentation.pro └── main.cpp ├── README.md ├── common.hpp └── result ├── CppQt_OpenVINO_YOLOv8_Image_Classification.jpg ├── CppQt_OpenVINO_YOLOv8_Image_Detection.jpg ├── CppQt_OpenVINO_YOLOv8_Image_OBB.jpg ├── CppQt_OpenVINO_YOLOv8_Image_Pose.jpg └── CppQt_OpenVINO_YOLOv8_Image_Segmentation.jpg /CppQt_OpenVINO_YOLOv8_Image_Classification/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CppQt_OpenVINO_YOLOv8_Image_Classification LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | 10 | # OpenCV 11 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 12 | set(OpenCV_DIR G:/OpenSource/OpenCV/4_8_0/build) 13 | find_package(OpenCV REQUIRED) 14 | include_directories(${OpenCV_INCLUDE_DIRS}) 15 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 16 | 17 | # OpenVINO 18 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 19 | set(OpenVINO_RUNTIME G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime) 20 | set(OpenVINO_DIR ${OpenVINO_RUNTIME}/cmake) 21 | find_package(OpenVINO REQUIRED) 22 | include_directories(${OpenVINO_RUNTIME}/include) 23 | find_library(OpenVINO_LIBS NAMES openvino PATHS ${OpenVINO_RUNTIME}/lib/intel64/Release) 24 | target_link_libraries(${PROJECT_NAME} ${OpenVINO_LIBS}) 25 | 26 | 27 | #设置可执行文件输出路径 28 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin) 29 | 30 | #install(TARGETS ${PROJECT_NAME} 31 | # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 32 | 33 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Classification/CppQt_OpenVINO_YOLOv8_Image_Classification.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++17 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.cpp 8 | 9 | ## OpenCV 4.8.0 world 10 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 11 | OPENCV_BUILD = G:/OpenSource/OpenCV/4_8_0/build/install 12 | win32:CONFIG(release, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480 13 | else:win32:CONFIG(debug, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480d 14 | INCLUDEPATH += $${OPENCV_BUILD}/include 15 | 16 | ## OpenVINO 2023.2 17 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 18 | OPENVINO_RUNTIME = G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime 19 | CONFIG(release, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/release/ \ 20 | -lopenvino \ 21 | -lopenvino_onnx_frontend 22 | else:CONFIG(debug, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/debug/ \ 23 | -lopenvinod \ 24 | -lopenvino_onnx_frontendd 25 | INCLUDEPATH += \ 26 | $${OPENVINO_RUNTIME}/include 27 | 28 | ## 指定exe或dll的生成目录 29 | DESTDIR = ../bin 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Classification/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../common.hpp" 3 | 4 | // 模型文件路径 5 | static const std::string model_file = "../model/yolov8n-cls.onnx"; 6 | // 分类标签文件路径 7 | static const std::string label_file = "../model/imagenet_2012.txt"; 8 | // 测试图片路径 9 | //static const std::string image_file = "../data/zidane.jpg"; 10 | static const std::string image_file = "../data/dog_512.bmp"; 11 | //static const std::string image_file = "../data/car.bmp"; 12 | //static const std::string image_file = "../data/bus.jpg"; 13 | 14 | int main(int argc, char **argv) 15 | { 16 | try { 17 | /// 读取标签文件, 这个文件必须和训练集的标签相符 18 | std::vector labels; 19 | std::ifstream inputFile; 20 | inputFile.open(label_file, std::ios::in); 21 | if (inputFile.is_open()) { 22 | std::string strLine; 23 | while (std::getline(inputFile, strLine)) { 24 | labels.push_back(strLine); 25 | } 26 | } else { 27 | throw "open labels file failed!"; 28 | } 29 | /// 创建OpenVINO Runtime Core对象 30 | ov::Core core; 31 | std::shared_ptr model = core.read_model(model_file); 32 | printInputAndOutputsInfo(*model); // 打印模型信息 33 | 34 | /// 载入并编译模型 35 | ov::CompiledModel compiled_model = core.compile_model(model, "AUTO"); 36 | 37 | /// 创建推理请求 38 | ov::InferRequest infer_request = compiled_model.create_infer_request(); 39 | 40 | /// 设置模型输入 41 | // 获取模型输入节点 42 | ov::Tensor input_tensor = infer_request.get_input_tensor(); 43 | 44 | const int64 start = cv::getTickCount(); 45 | // 读取图片并按照模型输入要求进行预处理 46 | cv::Mat image = cv::imread(image_file, cv::IMREAD_COLOR); 47 | fill_tensor_data_image(input_tensor, image); 48 | 49 | /// 执行推理计算 50 | infer_request.infer(); 51 | 52 | /// 处理推理计算结果 53 | // 获得推理结果 54 | const ov::Tensor output = infer_request.get_output_tensor(); 55 | const ov::Shape output_shape = output.get_shape(); 56 | const float *output_buffer = output.data(); 57 | 58 | // 解析推理结果 59 | const int out_rows = output_shape[1]; //获得"output"节点的rows 60 | const cv::Mat classes_scores(out_rows, 1, CV_32F, (float *)output_buffer); 61 | 62 | cv::Point class_id_point; 63 | double score; 64 | cv::minMaxLoc(classes_scores, nullptr, &score, nullptr, &class_id_point); 65 | const std::string classification = labels.at(class_id_point.y); 66 | 67 | // 计算FPS 68 | const float t = (cv::getTickCount() - start) / static_cast(cv::getTickFrequency()); 69 | std::cout << "Infer time(ms): " << t * 1000 << "ms" << std::endl; 70 | std::cout << "Classification: " << classification << std::endl; 71 | std::cout << "Score: " << score << std::endl; 72 | 73 | const cv::Point pos(10, 30); 74 | cv::putText(image, cv::format("FPS: %.2f", 1.0 / t), pos, cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); 75 | // 绘制标签 76 | const std::string label = classification + ": " + std::to_string(score).substr(0, 4); 77 | const cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, nullptr); 78 | const cv::Rect textBox(pos.x, pos.y + 5, textSize.width, textSize.height + 10); 79 | cv::rectangle(image, textBox, cv::Scalar(0, 255, 255), cv::FILLED); 80 | cv::putText(image, label, cv::Point(pos.x, pos.y + 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, 81 | cv::Scalar(0, 0, 0)); 82 | 83 | /// 获取程序名称 84 | const std::string programName{extractedProgramName(argv[0])}; 85 | cv::imshow(programName, image); 86 | /// 保存结果图 87 | save(programName, image); 88 | 89 | cv::waitKey(0); 90 | cv::destroyAllWindows(); 91 | 92 | } catch (const std::exception &e) { 93 | std::cerr << "exception: " << e.what() << std::endl; 94 | } catch (...) { 95 | std::cerr << "unknown exception" << std::endl; 96 | } 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Detection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CppQt_OpenVINO_YOLOv8_Image_Detection LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | 10 | # OpenCV 11 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 12 | set(OpenCV_DIR G:/OpenSource/OpenCV/4_8_0/build) 13 | find_package(OpenCV REQUIRED) 14 | include_directories(${OpenCV_INCLUDE_DIRS}) 15 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 16 | 17 | # OpenVINO 18 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 19 | set(OpenVINO_RUNTIME G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime) 20 | set(OpenVINO_DIR ${OpenVINO_RUNTIME}/cmake) 21 | find_package(OpenVINO REQUIRED) 22 | include_directories(${OpenVINO_RUNTIME}/include) 23 | find_library(OpenVINO_LIBS NAMES openvino PATHS ${OpenVINO_RUNTIME}/lib/intel64/Release) 24 | target_link_libraries(${PROJECT_NAME} ${OpenVINO_LIBS}) 25 | 26 | 27 | #设置可执行文件输出路径 28 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin) 29 | 30 | #install(TARGETS ${PROJECT_NAME} 31 | # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 32 | 33 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Detection/CppQt_OpenVINO_YOLOv8_Image_Detection.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++17 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.cpp 8 | 9 | ## OpenCV 4.8.0 world 10 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 11 | OPENCV_BUILD = G:/OpenSource/OpenCV/4_8_0/build/install 12 | win32:CONFIG(release, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480 13 | else:win32:CONFIG(debug, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480d 14 | INCLUDEPATH += $${OPENCV_BUILD}/include 15 | 16 | ## OpenVINO 2023.2 17 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 18 | OPENVINO_RUNTIME = G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime 19 | CONFIG(release, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/release/ \ 20 | -lopenvino \ 21 | -lopenvino_onnx_frontend 22 | else:CONFIG(debug, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/debug/ \ 23 | -lopenvinod \ 24 | -lopenvino_onnx_frontendd 25 | INCLUDEPATH += \ 26 | $${OPENVINO_RUNTIME}/include 27 | 28 | ## 指定exe或dll的生成目录 29 | DESTDIR = ../bin 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Detection/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | 3 | // COCO数据集的标签 4 | static const std::vector class_names = { 5 | "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", 6 | "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", 7 | "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", 8 | "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", 9 | "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", 10 | "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush" 11 | }; 12 | 13 | // 模型文件路径 14 | static const std::string model_file = "../model/yolov8n.onnx"; 15 | // 测试图片路径 16 | //static const std::string image_file = "../data/zidane.jpg"; 17 | static const std::string image_file = "../data/dog_512.bmp"; 18 | //static const std::string image_file = "../data/car.bmp"; 19 | //static const std::string image_file = "../data/bus.jpg"; 20 | 21 | int main(int argc, char **argv) 22 | { 23 | try { 24 | /// 创建OpenVINO Runtime Core对象 25 | ov::Core core; 26 | std::shared_ptr model = core.read_model(model_file); 27 | printInputAndOutputsInfo(*model); // 打印模型信息 28 | /// 载入并编译模型 29 | ov::CompiledModel compiled_model = core.compile_model(model, "AUTO"); 30 | 31 | /// 创建推理请求 32 | ov::InferRequest infer_request = compiled_model.create_infer_request(); 33 | 34 | /// 设置模型输入 35 | // 获取模型输入节点 36 | ov::Tensor input_tensor = infer_request.get_input_tensor(); 37 | 38 | const int64 start = cv::getTickCount(); 39 | // 读取图片并按照模型输入要求进行预处理 40 | cv::Mat image = cv::imread(image_file, cv::IMREAD_COLOR); 41 | const float factor = fill_tensor_data_image(input_tensor, image); 42 | 43 | /// 执行推理计算 44 | infer_request.infer(); 45 | 46 | /// 处理推理计算结果 47 | // 获得推理结果 48 | const ov::Tensor output = infer_request.get_output_tensor(); 49 | const ov::Shape output_shape = output.get_shape(); 50 | const float *output_buffer = output.data(); 51 | 52 | // 解析推理结果 53 | const int out_rows = output_shape[1]; //获得"output"节点的rows 54 | const int out_cols = output_shape[2]; //获得"output"节点的cols 55 | const cv::Mat det_output(out_rows, out_cols, CV_32F, (float *)output_buffer); 56 | 57 | std::vector boxes; 58 | std::vector class_ids; 59 | std::vector confidences; 60 | // 输出格式是[84,8400], 每列代表一个框(即最多有8400个框), 前面4行分别是cx, cy, ow, oh, 后面80行是每个类别的置信度 61 | std::cout << std::endl << std::endl; 62 | for (int i = 0; i < det_output.cols; ++i) { 63 | const cv::Mat classes_scores = det_output.col(i).rowRange(4, 84); 64 | cv::Point class_id_point; 65 | double score; 66 | cv::minMaxLoc(classes_scores, nullptr, &score, nullptr, &class_id_point); 67 | 68 | // 置信度 0~1之间 69 | if (score > 0.3) { 70 | const float cx = det_output.at(0, i); 71 | const float cy = det_output.at(1, i); 72 | const float ow = det_output.at(2, i); 73 | const float oh = det_output.at(3, i); 74 | cv::Rect box; 75 | box.x = static_cast((cx - 0.5 * ow) * factor); 76 | box.y = static_cast((cy - 0.5 * oh) * factor); 77 | box.width = static_cast(ow * factor); 78 | box.height = static_cast(oh * factor); 79 | 80 | boxes.push_back(box); 81 | class_ids.push_back(class_id_point.y); 82 | confidences.push_back(score); 83 | } 84 | } 85 | // NMS, 消除具有较低置信度的冗余重叠框 86 | std::vector indexes; 87 | cv::dnn::NMSBoxes(boxes, confidences, 0.25f, 0.45f, indexes); 88 | for (size_t i = 0; i < indexes.size(); i++) { 89 | const int index = indexes[i]; 90 | const cv::Rect &box = boxes[index]; 91 | // 绘制矩形框 92 | cv::rectangle(image, box, cv::Scalar(0, 0, 255), 2, 8); 93 | // 绘制标签 94 | const std::string label = class_names[class_ids[index]] + ":" + std::to_string(confidences[index]).substr(0, 4); 95 | const cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, nullptr); 96 | const cv::Rect textBox(box.tl().x, box.tl().y - 15, textSize.width, textSize.height + 5); 97 | cv::rectangle(image, textBox, cv::Scalar(0, 255, 255), cv::FILLED); 98 | cv::putText(image, label, cv::Point(box.tl().x, box.tl().y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, 99 | cv::Scalar(0, 0, 0)); 100 | } 101 | // 计算FPS 102 | const float t = (cv::getTickCount() - start) / static_cast(cv::getTickFrequency()); 103 | std::cout << "Infer time(ms): " << t * 1000 << "ms; Detections: " << indexes.size() << std::endl; 104 | cv::putText(image, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); 105 | /// 获取程序名称 106 | const std::string programName{extractedProgramName(argv[0])}; 107 | cv::imshow(programName, image); 108 | /// 保存结果图 109 | save(programName, image); 110 | 111 | cv::waitKey(0); 112 | cv::destroyAllWindows(); 113 | 114 | } catch (const std::exception &e) { 115 | std::cerr << "exception: " << e.what() << std::endl; 116 | } catch (...) { 117 | std::cerr << "unknown exception" << std::endl; 118 | } 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_OBB/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CppQt_OpenVINO_YOLOv8_Image_OBB LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | 10 | # OpenCV 11 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 12 | set(OpenCV_DIR G:/OpenSource/OpenCV/4_8_0/build) 13 | find_package(OpenCV REQUIRED) 14 | include_directories(${OpenCV_INCLUDE_DIRS}) 15 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 16 | 17 | # OpenVINO 18 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 19 | set(OpenVINO_RUNTIME G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime) 20 | set(OpenVINO_DIR ${OpenVINO_RUNTIME}/cmake) 21 | find_package(OpenVINO REQUIRED) 22 | include_directories(${OpenVINO_RUNTIME}/include) 23 | find_library(OpenVINO_LIBS NAMES openvino PATHS ${OpenVINO_RUNTIME}/lib/intel64/Release) 24 | target_link_libraries(${PROJECT_NAME} ${OpenVINO_LIBS}) 25 | 26 | 27 | #设置可执行文件输出路径 28 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin) 29 | 30 | #install(TARGETS ${PROJECT_NAME} 31 | # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 32 | 33 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_OBB/CppQt_OpenVINO_YOLOv8_Image_OBB.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++17 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.cpp 8 | 9 | ## OpenCV 4.8.0 world 10 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 11 | OPENCV_BUILD = G:/OpenSource/OpenCV/4_8_0/build/install 12 | win32:CONFIG(release, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480 13 | else:win32:CONFIG(debug, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480d 14 | INCLUDEPATH += $${OPENCV_BUILD}/include 15 | 16 | ## OpenVINO 2023.2 17 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 18 | OPENVINO_RUNTIME = G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime 19 | CONFIG(release, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/release/ \ 20 | -lopenvino \ 21 | -lopenvino_onnx_frontend 22 | else:CONFIG(debug, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/debug/ \ 23 | -lopenvinod \ 24 | -lopenvino_onnx_frontendd 25 | INCLUDEPATH += \ 26 | $${OPENVINO_RUNTIME}/include 27 | 28 | ## 指定exe或dll的生成目录 29 | DESTDIR = ../bin 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_OBB/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | 3 | //const float PI = std::acos(-1); 4 | constexpr float PI = 3.1415926f; 5 | 6 | // DOTAv1数据集的标签, 共有15个类别 7 | static const std::vector class_names = { 8 | "plane", "ship", "storage tank", "baseball diamond", "tennis court", 9 | "basketball court", "ground track field", "harbor", "bridge", "large vehicle", "small vehicle", 10 | "helicopter", "roundabout", "soccer ball field", "swimming pool", 11 | }; 12 | 13 | // 模型文件路径 14 | static const std::string model_file = "../model/yolov8n-obb.onnx"; 15 | // 测试图片路径 16 | //static const std::string image_file = "../data/zidane.jpg"; 17 | //static const std::string image_file = "../data/dog_512.bmp"; 18 | static const std::string image_file = "../data/airport.png"; 19 | //static const std::string image_file = "../data/bus.jpg"; 20 | 21 | int main(int argc, char **argv) 22 | { 23 | try { 24 | /// 创建OpenVINO Runtime Core对象 25 | ov::Core core; 26 | std::shared_ptr model = core.read_model(model_file); 27 | printInputAndOutputsInfo(*model); // 打印模型信息 28 | /// 载入并编译模型 29 | ov::CompiledModel compiled_model = core.compile_model(model, "AUTO"); 30 | /// 创建推理请求 31 | ov::InferRequest infer_request = compiled_model.create_infer_request(); 32 | /// 设置模型输入 33 | // 获取模型输入节点 34 | ov::Tensor input_tensor = infer_request.get_input_tensor(); 35 | 36 | const int64 start = cv::getTickCount(); 37 | // 读取图片并按照模型输入要求进行预处理 38 | cv::Mat image = cv::imread(image_file, cv::IMREAD_COLOR); 39 | const float factor = fill_tensor_data_image(input_tensor, image); 40 | 41 | /// 执行推理计算 42 | infer_request.infer(); 43 | 44 | /// 处理推理计算结果 45 | // 获得推理结果 46 | const ov::Tensor output = infer_request.get_output_tensor(); 47 | const ov::Shape output_shape = output.get_shape(); 48 | const float *output_buffer = output.data(); 49 | 50 | // 解析推理结果 51 | const int out_rows = output_shape[1]; //获得"output"节点的rows 52 | const int out_cols = output_shape[2]; //获得"output"节点的cols 53 | const cv::Mat det_output(out_rows, out_cols, CV_32F, (float *)output_buffer); 54 | 55 | std::vector boxes; 56 | std::vector class_ids; 57 | std::vector confidences; 58 | // 输出格式是[20,21504], 每列代表一个框(即最多有21504个框), 前面4行分别是[cx, cy, ow, oh], 中间15行是15个类别的score, 最后1行是旋转框的角度 59 | // 20=4+15+1 60 | std::cout << std::endl << std::endl; 61 | for (int i = 0; i < det_output.cols; ++i) { 62 | const cv::Mat classes_scores = det_output.col(i).rowRange(4, 19); 63 | cv::Point class_id_point; 64 | double score; 65 | cv::minMaxLoc(classes_scores, nullptr, &score, nullptr, &class_id_point); 66 | 67 | // 置信度 0~1之间 68 | if (score > 0.3) { 69 | const float cx = det_output.at(0, i); 70 | const float cy = det_output.at(1, i); 71 | const float ow = det_output.at(2, i); 72 | const float oh = det_output.at(3, i); 73 | float angle = det_output.at(19, i); 74 | // [-PI/4,3/4 PI) --> [-PI/2,PI/2) 75 | if (angle > PI && angle < 0.75 * PI) { 76 | angle = angle - PI; 77 | } 78 | const cv::RotatedRect box{ 79 | cv::Point2f{cx * factor, cy * factor}, 80 | cv::Size2f{ow * factor, oh * factor}, 81 | angle * 180.0f / PI 82 | }; 83 | boxes.push_back(box); 84 | class_ids.push_back(class_id_point.y); 85 | confidences.push_back(score); 86 | } 87 | } 88 | // NMS, 消除具有较低置信度的冗余重叠框 89 | std::vector indexes; 90 | cv::dnn::NMSBoxes(boxes, confidences, 0.25f, 0.45f, indexes); 91 | for (size_t i = 0; i < indexes.size(); i++) { 92 | const int index = indexes[i]; 93 | const cv::RotatedRect &box = boxes[index]; 94 | cv::Point2f points[4]; 95 | box.points(points); 96 | // 绘制旋转矩形框 97 | for (int i = 0; i < 4; ++i) { 98 | cv::line(image, points[i], points[(i + 1) % 4], cv::Scalar(0, 0, 255), 2, 8); 99 | } 100 | // 找到旋转矩形框最上方的那个顶点, 并以之为起点绘制标签 101 | cv::Point2f lowerPoint = points[0]; 102 | for (int i = 1; i < 4; ++i) { 103 | if (points[i].y < lowerPoint.y) { 104 | lowerPoint = points[i]; 105 | } 106 | } 107 | const std::string label = class_names[class_ids[index]] + ":" + std::to_string(confidences[index]).substr(0, 4); 108 | const cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, nullptr); 109 | const cv::Rect textBox(lowerPoint.x, lowerPoint.y - 18, textSize.width, textSize.height + 5); 110 | cv::rectangle(image, textBox, cv::Scalar(0, 255, 255), cv::FILLED); 111 | cv::putText(image, label, cv::Point(lowerPoint.x, lowerPoint.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, 112 | cv::Scalar(0, 0, 0)); 113 | } 114 | /// 计算FPS 115 | const float t = (cv::getTickCount() - start) / static_cast(cv::getTickFrequency()); 116 | std::cout << "Infer time(ms): " << t * 1000 << "ms; Detections: " << indexes.size() << std::endl; 117 | cv::putText(image, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); 118 | /// 获取程序名称 119 | const std::string programName{extractedProgramName(argv[0])}; 120 | cv::imshow(programName, image); 121 | /// 保存结果图 122 | save(programName, image); 123 | 124 | cv::waitKey(0); 125 | cv::destroyAllWindows(); 126 | 127 | } catch (const std::exception &e) { 128 | std::cerr << "exception: " << e.what() << std::endl; 129 | } catch (...) { 130 | std::cerr << "unknown exception" << std::endl; 131 | } 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Pose/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CppQt_OpenVINO_YOLOv8_Image_Pose LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | 10 | # OpenCV 11 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 12 | set(OpenCV_DIR G:/OpenSource/OpenCV/4_8_0/build) 13 | find_package(OpenCV REQUIRED) 14 | include_directories(${OpenCV_INCLUDE_DIRS}) 15 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 16 | 17 | # OpenVINO 18 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 19 | set(OpenVINO_RUNTIME G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime) 20 | set(OpenVINO_DIR ${OpenVINO_RUNTIME}/cmake) 21 | find_package(OpenVINO REQUIRED) 22 | include_directories(${OpenVINO_RUNTIME}/include) 23 | find_library(OpenVINO_LIBS NAMES openvino PATHS ${OpenVINO_RUNTIME}/lib/intel64/Release) 24 | target_link_libraries(${PROJECT_NAME} ${OpenVINO_LIBS}) 25 | 26 | 27 | #设置可执行文件输出路径 28 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin) 29 | 30 | #install(TARGETS ${PROJECT_NAME} 31 | # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 32 | 33 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Pose/CppQt_OpenVINO_YOLOv8_Image_Pose.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++17 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.cpp 8 | 9 | ## OpenCV 4.8.0 world 10 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 11 | OPENCV_BUILD = G:/OpenSource/OpenCV/4_8_0/build/install 12 | win32:CONFIG(release, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480 13 | else:win32:CONFIG(debug, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480d 14 | INCLUDEPATH += $${OPENCV_BUILD}/include 15 | 16 | ## OpenVINO 2023.2 17 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 18 | OPENVINO_RUNTIME = G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime 19 | CONFIG(release, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/release/ \ 20 | -lopenvino \ 21 | -lopenvino_onnx_frontend 22 | else:CONFIG(debug, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/debug/ \ 23 | -lopenvinod \ 24 | -lopenvino_onnx_frontendd 25 | INCLUDEPATH += \ 26 | $${OPENVINO_RUNTIME}/include 27 | 28 | ## 指定exe或dll的生成目录 29 | DESTDIR = ../bin 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Pose/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | 3 | // 模型文件路径 4 | static const std::string model_file = "../model/yolov8n-pose.onnx"; 5 | // 测试图片路径 6 | //static const std::string image_file = "../data/zidane.jpg"; 7 | //static const std::string image_file = "../data/dog_512.bmp"; 8 | //static const std::string image_file = "../data/car.bmp"; 9 | static const std::string image_file = "../data/bus.jpg"; 10 | 11 | // 定义skeleton的连接关系以及color mappings 12 | // skeleton[0]={16, 14}表示objects_keypoints[16]和objects_keypoints[14]连一条线, posePalette[limbColorIndices[0]]表示这条线的颜色 13 | static const std::vector> skeleton = { {16, 14}, {14, 12}, {17, 15}, {15, 13}, {12, 13}, {6, 12}, {7, 13}, {6, 7}, 14 | {6, 8}, {7, 9}, {8, 10}, {9, 11}, {2, 3}, {1, 2}, {1, 3}, {2, 4}, {3, 5}, {4, 6}, {5, 7} 15 | }; 16 | static const std::vector posePalette = { 17 | cv::Scalar(255, 128, 0), cv::Scalar(255, 153, 51), cv::Scalar(255, 178, 102), cv::Scalar(230, 230, 0), cv::Scalar(255, 153, 255), 18 | cv::Scalar(153, 204, 255), cv::Scalar(255, 102, 255), cv::Scalar(255, 51, 255), cv::Scalar(102, 178, 255), cv::Scalar(51, 153, 255), 19 | cv::Scalar(255, 153, 153), cv::Scalar(255, 102, 102), cv::Scalar(255, 51, 51), cv::Scalar(153, 255, 153), cv::Scalar(102, 255, 102), 20 | cv::Scalar(51, 255, 51), cv::Scalar(0, 255, 0), cv::Scalar(0, 0, 255), cv::Scalar(255, 0, 0), cv::Scalar(255, 255, 255) 21 | }; 22 | static const std::vector limbColorIndices = { 9, 9, 9, 9, 7, 7, 7, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16 }; 23 | static const std::vector kptColorIndices = { 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9 }; 24 | 25 | int main(int argc, char **argv) 26 | { 27 | try { 28 | /// 创建OpenVINO Runtime Core对象 29 | ov::Core core; 30 | std::shared_ptr model = core.read_model(model_file); 31 | printInputAndOutputsInfo(*model); // 打印模型信息 32 | 33 | /// 载入并编译模型 34 | ov::CompiledModel compiled_model = core.compile_model(model, "AUTO"); 35 | 36 | /// 创建推理请求 37 | ov::InferRequest infer_request = compiled_model.create_infer_request(); 38 | 39 | /// 设置模型输入 40 | // 获取模型输入节点 41 | ov::Tensor input_tensor = infer_request.get_input_tensor(); 42 | 43 | const int64 start = cv::getTickCount(); 44 | // 读取图片并按照模型输入要求进行预处理 45 | cv::Mat image = cv::imread(image_file, cv::IMREAD_COLOR); 46 | const float factor = fill_tensor_data_image(input_tensor, image); 47 | 48 | /// 执行推理计算 49 | infer_request.infer(); 50 | 51 | /// 处理推理计算结果 52 | // 获得推理结果 53 | const ov::Tensor output = infer_request.get_output_tensor(); 54 | const ov::Shape output_shape = output.get_shape(); 55 | const float *output_buffer = output.data(); 56 | 57 | // 解析推理结果 58 | const int out_rows = output_shape[1]; //获得"output"节点的rows 59 | const int out_cols = output_shape[2]; //获得"output"节点的cols 60 | const cv::Mat det_output(out_rows, out_cols, CV_32F, (float *)output_buffer); 61 | 62 | std::vector boxes; 63 | std::vector confidences; 64 | std::vector> objects_keypoints; 65 | // 输出格式是[56,8400], 每列代表一个框(即最多有8400个框), 前面4行分别是[cx, cy, ow, oh], 中间score, 最后17*3关键点(3代表每个关键点的信息, 包括[x, y, visibility]) 66 | // 56=4+1+17*3 67 | std::cout << std::endl << std::endl; 68 | for (int i = 0; i < det_output.cols; ++i) { 69 | const float score = det_output.at(4, i); 70 | // 置信度 0~1之间 71 | if (score > 0.3f) { 72 | const float cx = det_output.at(0, i); 73 | const float cy = det_output.at(1, i); 74 | const float ow = det_output.at(2, i); 75 | const float oh = det_output.at(3, i); 76 | cv::Rect box; 77 | box.x = static_cast((cx - 0.5 * ow) * factor); 78 | box.y = static_cast((cy - 0.5 * oh) * factor); 79 | box.width = static_cast(ow * factor); 80 | box.height = static_cast(oh * factor); 81 | 82 | boxes.push_back(box); 83 | confidences.push_back(score); 84 | 85 | // 获取关键点 86 | std::vector keypoints; 87 | cv::Mat kpts = det_output.col(i).rowRange(5, 56); 88 | for (int j = 0; j < 17; ++j) { 89 | const float x = kpts.at(j * 3 + 0, 0) * factor; 90 | const float y = kpts.at(j * 3 + 1, 0) * factor; 91 | const float s = kpts.at(j * 3 + 2, 0); 92 | keypoints.push_back(x); 93 | keypoints.push_back(y); 94 | keypoints.push_back(s); 95 | } 96 | objects_keypoints.push_back(keypoints); 97 | } 98 | } 99 | 100 | const int radius = 5; 101 | const cv::Size &shape = image.size(); 102 | std::vector limbColorPalette; 103 | std::vector kptColorPalette; 104 | for (int index : limbColorIndices) { 105 | limbColorPalette.push_back(posePalette[index]); 106 | } 107 | for (int index : kptColorIndices) { 108 | kptColorPalette.push_back(posePalette[index]); 109 | } 110 | 111 | // NMS, 消除具有较低置信度的冗余重叠框 112 | std::vector indexes; 113 | cv::dnn::NMSBoxes(boxes, confidences, 0.25f, 0.45f, indexes); 114 | for (size_t i = 0; i < indexes.size(); ++i) { 115 | const int index = indexes[i]; 116 | const cv::Rect &box = boxes[index]; 117 | // 绘制矩形框 118 | cv::rectangle(image, box, cv::Scalar(0, 0, 255), 2, 8); 119 | // 绘制标签 120 | const std::string label = "Person:" + std::to_string(confidences[index]).substr(0, 4); 121 | const cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, nullptr); 122 | const cv::Rect textBox(box.tl().x, box.tl().y - 15, textSize.width, textSize.height + 5); 123 | cv::rectangle(image, textBox, cv::Scalar(0, 255, 255), cv::FILLED); 124 | cv::putText(image, label, cv::Point(box.tl().x, box.tl().y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, 125 | cv::Scalar(0, 0, 0)); 126 | /// 绘制关键点和连线 127 | const std::vector &keypoint = objects_keypoints[index]; 128 | // 绘制关键点 129 | for (int i = 0; i < 17; ++i) { 130 | const int idx = i * 3; 131 | const int x_coord = static_cast(keypoint[idx]); 132 | const int y_coord = static_cast(keypoint[idx + 1]); 133 | if ((x_coord % shape.width) != 0 && (y_coord % shape.height) != 0) { 134 | const float conf = keypoint[2]; 135 | if (conf < 0.5) { 136 | continue; 137 | } 138 | cv::circle(image, cv::Point(x_coord, y_coord), radius, kptColorPalette[i], -1, cv::LINE_AA); 139 | } 140 | } 141 | // 绘制连线 142 | for (size_t i = 0; i < skeleton.size(); ++i) { 143 | const std::vector &sk = skeleton[i]; 144 | const int idx1_x_pos = (sk[0] - 1) * 3; 145 | const int idx2_x_pos = (sk[1] - 1) * 3; 146 | 147 | const int x1 = static_cast(keypoint[idx1_x_pos]); 148 | const int y1 = static_cast(keypoint[idx1_x_pos + 1]); 149 | const int x2 = static_cast(keypoint[idx2_x_pos]); 150 | const int y2 = static_cast(keypoint[idx2_x_pos + 1]); 151 | 152 | const float conf1 = keypoint[idx1_x_pos + 2]; 153 | const float conf2 = keypoint[idx2_x_pos + 2]; 154 | // Check confidence thresholds 155 | if (conf1 < 0.5 || conf2 < 0.5) { 156 | continue; 157 | } 158 | // Check if positions are within bounds 159 | if (x1 % shape.width == 0 || y1 % shape.height == 0 || x1 < 0 || y1 < 0 || 160 | x2 % shape.width == 0 || y2 % shape.height == 0 || x2 < 0 || y2 < 0) { 161 | continue; 162 | } 163 | // Draw a line between keypoints 164 | cv::line(image, cv::Point(x1, y1), cv::Point(x2, y2), limbColorPalette[i], 2, cv::LINE_AA); 165 | } 166 | } 167 | /// 计算FPS 168 | const float t = (cv::getTickCount() - start) / static_cast(cv::getTickFrequency()); 169 | std::cout << "Infer time(ms): " << t * 1000 << "ms; Detections: " << indexes.size() << std::endl; 170 | cv::putText(image, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); 171 | /// 获取程序名称 172 | const std::string programName{extractedProgramName(argv[0])}; 173 | cv::imshow(programName, image); 174 | /// 保存结果图 175 | save(programName, image); 176 | 177 | cv::waitKey(0); 178 | cv::destroyAllWindows(); 179 | 180 | } catch (const std::exception &e) { 181 | std::cerr << "exception: " << e.what() << std::endl; 182 | } catch (...) { 183 | std::cerr << "unknown exception" << std::endl; 184 | } 185 | return 0; 186 | } 187 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Segmentation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CppQt_OpenVINO_YOLOv8_Image_Segmentation LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | 10 | # OpenCV 11 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 12 | set(OpenCV_DIR G:/OpenSource/OpenCV/4_8_0/build) 13 | find_package(OpenCV REQUIRED) 14 | include_directories(${OpenCV_INCLUDE_DIRS}) 15 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 16 | 17 | # OpenVINO 18 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 19 | set(OpenVINO_RUNTIME G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime) 20 | set(OpenVINO_DIR ${OpenVINO_RUNTIME}/cmake) 21 | find_package(OpenVINO REQUIRED) 22 | include_directories(${OpenVINO_RUNTIME}/include) 23 | find_library(OpenVINO_LIBS NAMES openvino PATHS ${OpenVINO_RUNTIME}/lib/intel64/Release) 24 | target_link_libraries(${PROJECT_NAME} ${OpenVINO_LIBS}) 25 | 26 | 27 | #设置可执行文件输出路径 28 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin) 29 | 30 | #install(TARGETS ${PROJECT_NAME} 31 | # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 32 | 33 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Segmentation/CppQt_OpenVINO_YOLOv8_Image_Segmentation.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++17 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.cpp 8 | 9 | ## OpenCV 4.8.0 world 10 | # 下载链接为https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-windows.exe 11 | OPENCV_BUILD = G:/OpenSource/OpenCV/4_8_0/build/install 12 | win32:CONFIG(release, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480 13 | else:win32:CONFIG(debug, debug|release): LIBS += -L$${OPENCV_BUILD}/x64/vc15/lib/ -lopencv_world480d 14 | INCLUDEPATH += $${OPENCV_BUILD}/include 15 | 16 | ## OpenVINO 2023.2 17 | # 下载链接为https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.2/windows/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64.zip 18 | OPENVINO_RUNTIME = G:/OpenSource/OpenVINO/2023/w_openvino_toolkit_windows_2023.2.0.13089.cfd42bd2cb0_x86_64/runtime 19 | CONFIG(release, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/release/ \ 20 | -lopenvino \ 21 | -lopenvino_onnx_frontend 22 | else:CONFIG(debug, debug|release): LIBS += -L$${OPENVINO_RUNTIME}/lib/intel64/debug/ \ 23 | -lopenvinod \ 24 | -lopenvino_onnx_frontendd 25 | INCLUDEPATH += \ 26 | $${OPENVINO_RUNTIME}/include 27 | 28 | ## 指定exe或dll的生成目录 29 | DESTDIR = ../bin 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CppQt_OpenVINO_YOLOv8_Image_Segmentation/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | 3 | // COCO数据集的标签 4 | static const std::vector class_names = { 5 | "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", 6 | "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", 7 | "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", 8 | "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", 9 | "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", 10 | "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush" 11 | }; 12 | 13 | // 模型文件路径 14 | static const std::string model_file = "../model/yolov8n-seg.onnx"; 15 | // 测试图片路径 16 | static const std::string image_file = "../data/zidane.jpg"; 17 | //static const std::string image_file = "../data/dog_512.bmp"; 18 | //static const std::string image_file = "../data/car.bmp"; 19 | //static const std::string image_file = "../data/bus.jpg"; 20 | 21 | struct SegmentOutput { 22 | int _id; // 结果类别id 23 | float _confidence; // 结果置信度 24 | cv::Rect2f _box; // 矩形框 25 | cv::Mat _boxMask; // 矩形框内mask, 节省内存空间和加快速度 26 | }; 27 | 28 | /// 将一系列SegmentOutput绘制到image上 29 | void draw(cv::Mat &image, std::vector &results) 30 | { 31 | // 生成随机颜色 32 | std::vector colors; 33 | std::srand(std::time(nullptr)); 34 | for (int i = 0; i < class_names.size(); ++i) { 35 | const int b = std::rand() % 256; 36 | const int g = std::rand() % 256; 37 | const int a = std::rand() % 256; 38 | colors.push_back(cv::Scalar(b, g, a)); 39 | } 40 | cv::Mat mask = image.clone(); 41 | for (const SegmentOutput &result : results) { 42 | cv::rectangle(image, result._box, colors[result._id], 2, 8); 43 | 44 | mask(result._box).setTo(colors[result._id], result._boxMask); 45 | 46 | const std::string label = cv::format("%s:%.2f", class_names[result._id].c_str(), result._confidence); 47 | 48 | int baseLine; 49 | const cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); 50 | cv::putText(image, label, 51 | cv::Point(result._box.x, std::max(result._box.y, float(labelSize.height))), 52 | cv::FONT_HERSHEY_SIMPLEX, 1, colors[result._id], 2); 53 | } 54 | cv::addWeighted(image, 0.5, mask, 0.8, 1, image); // 把mask加在原图上面 55 | } 56 | 57 | cv::Rect toBox(const cv::Mat &input, const cv::Rect &range) 58 | { 59 | const float cx = input.at(0); 60 | const float cy = input.at(1); 61 | const float ow = input.at(2); 62 | const float oh = input.at(3); 63 | cv::Rect box; 64 | box.x = cvRound(cx - 0.5f * ow); 65 | box.y = cvRound(cy - 0.5f * oh); 66 | box.width = cvRound(ow); 67 | box.height = cvRound(oh); 68 | return box & range; 69 | } 70 | 71 | int main(int argc, char **argv) 72 | { 73 | try { 74 | /// 创建OpenVINO Runtime Core对象 75 | ov::Core core; 76 | std::shared_ptr model = core.read_model(model_file); 77 | printInputAndOutputsInfo(*model); // 打印模型信息 78 | /// 载入并编译模型 79 | ov::CompiledModel compiled_model = core.compile_model(model, "AUTO"); 80 | 81 | /// 创建推理请求 82 | ov::InferRequest infer_request = compiled_model.create_infer_request(); 83 | 84 | /// 设置模型输入 85 | // 获取模型输入节点 86 | ov::Tensor input_tensor = infer_request.get_input_tensor(); 87 | 88 | const int64 start = cv::getTickCount(); 89 | // 读取图片并按照模型输入要求进行预处理 90 | cv::Mat image = cv::imread(image_file, cv::IMREAD_COLOR); 91 | const float scale_factor = fill_tensor_data_image(input_tensor, image); 92 | 93 | /// 执行推理计算 94 | infer_request.infer(); 95 | 96 | /// 处理推理计算结果 97 | // 获得推理结果, 输出结点是[116,8400], 一共8400个结果, 每个结果116个维度. 98 | // 116=4+80+32, 4是预测框的[cx, cy, w, h], 80是每个类别的置信度, 32是分割需要用到的 99 | const ov::Tensor output0 = infer_request.get_tensor("output0"); 100 | const float *output0_buffer = output0.data(); 101 | const ov::Shape output0_shape = output0.get_shape(); 102 | const int output0_rows = output0_shape[1]; 103 | const int output0_cols = output0_shape[2]; 104 | std::cout << "The shape of Detection tensor:" << output0_shape << std::endl; 105 | 106 | const ov::Tensor output1 = infer_request.get_tensor("output1"); 107 | const ov::Shape output1_shape = output1.get_shape(); 108 | std::cout << "The shape of Proto tensor:" << output1_shape << std::endl; 109 | std::cout << std::endl << std::endl; 110 | 111 | // Detect Matrix: 116 x 8400 -> 8400 x 116 112 | // 一共8400个结果, 每个结果116个维度. 113 | // 116=4+80+32, 4是预测框的[cx, cy, w, h]; 80是每个类别的置信度; 32需要与Proto Matrix相乘得到分割mask, 所以这里转置了矩阵 114 | const cv::Mat detect_buffer = cv::Mat(output0_rows, output0_cols, CV_32F, (float *)output0_buffer).t(); 115 | // Proto Matrix: 1x32x160x160 -> 32x25600 116 | const cv::Mat proto_buffer(output1_shape[1], output1_shape[2]*output1_shape[3], CV_32F, output1.data()); 117 | 118 | const float conf_threshold = 0.5; 119 | const float nms_threshold = 0.5; 120 | std::vector mask_boxes; 121 | std::vector boxes; 122 | std::vector class_ids; 123 | std::vector confidences; 124 | std::vector masks; 125 | for (int i = 0; i < detect_buffer.rows; ++i) { 126 | const cv::Mat result = detect_buffer.row(i); 127 | /// 处理检测部分的结果 128 | // 取置信度最大的那个标签 129 | const cv::Mat classes_scores = result.colRange(4, 84); 130 | cv::Point class_id_point; 131 | double score; 132 | cv::minMaxLoc(classes_scores, nullptr, &score, nullptr, &class_id_point); 133 | 134 | if (score > conf_threshold) { 135 | // score\in [0, 1), 置信度太小的结果可以舍弃掉 136 | class_ids.push_back(class_id_point.x); 137 | confidences.push_back(score); 138 | // 预测框是在640x640的图片上预测的, 但是分割结果只有160x160 139 | const float mask_scale = 0.25f; // 160/640 = 0.25 140 | 141 | const cv::Mat detection_box = result.colRange(0, 4); 142 | const cv::Rect mask_box = toBox(detection_box * mask_scale, 143 | cv::Rect(0, 0, 160, 160)); 144 | const cv::Rect image_box = toBox(detection_box * scale_factor, 145 | cv::Rect(0, 0, image.cols, image.rows)); 146 | mask_boxes.push_back(mask_box); 147 | boxes.push_back(image_box); 148 | 149 | /// 处理分割部分的结果 150 | masks.push_back(result.colRange(84, 116)); 151 | } 152 | } 153 | // NMS, 消除具有较低置信度的冗余重叠框 154 | std::vector nms_indexes; 155 | cv::dnn::NMSBoxes(boxes, confidences, conf_threshold, nms_threshold, nms_indexes); 156 | 157 | std::vector segmentOutputs; 158 | for (const int index : nms_indexes) { 159 | SegmentOutput segmentOutput; 160 | segmentOutput._id = class_ids[index]; 161 | segmentOutput._confidence = confidences[index]; 162 | segmentOutput._box = boxes[index]; 163 | // sigmoid运算 164 | cv::Mat m; 165 | cv::exp(-masks[index] * proto_buffer, m); 166 | m = 1.0f / (1.0f + m); 167 | m = m.reshape(1, 160); // 1x25600 -> 160x160 168 | cv::resize(m(mask_boxes[index]) > 0.5f, 169 | segmentOutput._boxMask, segmentOutput._box.size()); 170 | 171 | segmentOutputs.push_back(segmentOutput); 172 | } 173 | draw(image, segmentOutputs); 174 | 175 | // 计算FPS 176 | const float t = (cv::getTickCount() - start) / static_cast(cv::getTickFrequency()); 177 | std::cout << "Infer time(ms): " << t * 1000 << "ms; Detections: " << nms_indexes.size() << std::endl; 178 | cv::putText(image, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); 179 | /// 获取程序名称 180 | const std::string programName{extractedProgramName(argv[0])}; 181 | cv::imshow(programName, image); 182 | /// 保存结果图 183 | save(programName, image); 184 | 185 | cv::waitKey(0); 186 | cv::destroyAllWindows(); 187 | 188 | } catch (const std::exception &e) { 189 | std::cerr << "exception: " << e.what() << std::endl; 190 | } catch (...) { 191 | std::cerr << "unknown exception" << std::endl; 192 | } 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenVINO_yolov8 2 | 用OpenVINO对yolov8导出的onnx模型进行C++的推理. 任务包括图像分类, 目标检测, 实例分割, 人体姿态检测, 和旋转矩形框目标预测. 步骤包括图片前处理, 推理, NMS等. 3 | 4 | ### 编译环境 5 | - Windows 10 6 | - Qt 6.2.4 MSVC2019 64bit 7 | - OpenCV 4.8.0 8 | - OpenVINO 2023.2 9 | 10 | ### 各个项目简介 11 | - CppQt_OpenVINO_YOLOv8_Image_Classification: 图像分类 12 | 13 | ![效果图](result/CppQt_OpenVINO_YOLOv8_Image_Classification.jpg) 14 | 15 | - CppQt_OpenVINO_YOLOv8_Image_Detection: 目标检测 16 | 17 | ![效果图](result/CppQt_OpenVINO_YOLOv8_Image_Detection.jpg) 18 | 19 | - CppQt_OpenVINO_YOLOv8_Image_Segmentation: 实例分割 20 | 21 | ![效果图](result/CppQt_OpenVINO_YOLOv8_Image_Segmentation.jpg) 22 | 23 | - CppQt_OpenVINO_YOLOv8_Image_Pose: 人体姿态检测 24 | 25 | ![效果图](result/CppQt_OpenVINO_YOLOv8_Image_Pose.jpg) 26 | 27 | - CppQt_OpenVINO_YOLOv8_Image_OBB: 旋转矩形框目标预测 28 | 29 | ![效果图](result/CppQt_OpenVINO_YOLOv8_Image_OBB.jpg) 30 | 31 | 32 | ### 预告 33 | - 将[openvino_notebooks](https://github.com/openvinotoolkit/openvino_notebooks)中的所有模型都用C++推理一遍 34 | -------------------------------------------------------------------------------- /common.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /// 转换图像数据: 先转换元素类型, (可选)然后归一化到[0, 1], (可选)然后交换RB通道 6 | void convert(const cv::Mat &input, cv::Mat &output, const bool normalize, const bool exchangeRB) 7 | { 8 | input.convertTo(output, CV_32F); 9 | if (normalize) { 10 | output = output / 255.0; // 归一化到[0, 1] 11 | } 12 | if (exchangeRB) { 13 | cv::cvtColor(output, output, cv::COLOR_BGR2RGB); 14 | } 15 | } 16 | 17 | /*! 18 | * \brief fill_tensor_data_image 对网络的输入为图片数据的节点进行赋值,实现图片数据输入网络 19 | * \param input_tensor 输入节点的tensor 20 | * \param input_image 输入图片的数据 21 | * \return 缩放因子, 该缩放是为了将input_image塞进input_tensor 22 | */ 23 | float fill_tensor_data_image(ov::Tensor &input_tensor, const cv::Mat &input_image) 24 | { 25 | /// letterbox变换: 不改变宽高比(aspect ratio), 将input_image缩放并放置到blob_image左上角 26 | const ov::Shape tensor_shape = input_tensor.get_shape(); 27 | const size_t num_channels = tensor_shape[1]; 28 | const size_t height = tensor_shape[2]; 29 | const size_t width = tensor_shape[3]; 30 | // 缩放因子 31 | const float scale = std::min(height / float(input_image.rows), 32 | width / float(input_image.cols)); 33 | const cv::Matx23f matrix{ 34 | scale, 0.0, 0.0, 35 | 0.0, scale, 0.0, 36 | }; 37 | cv::Mat blob_image; 38 | // 下面根据scale范围进行数据转换, 这只是为了提高一点速度(主要是提高了交换通道的速度) 39 | // 如果不在意这点速度提升的可以固定一种做法(两个if分支随便一个都可以) 40 | if (scale < 1.0f) { 41 | // 要缩小, 那么先缩小再交换通道 42 | cv::warpAffine(input_image, blob_image, matrix, cv::Size(width, height)); 43 | convert(blob_image, blob_image, true, true); 44 | } else { 45 | // 要放大, 那么先交换通道再放大 46 | convert(input_image, blob_image, true, true); 47 | cv::warpAffine(blob_image, blob_image, matrix, cv::Size(width, height)); 48 | } 49 | 50 | /// 将图像数据填入input_tensor 51 | float *const input_tensor_data = input_tensor.data(); 52 | // 原有图片数据为 HWC格式,模型输入节点要求的为 CHW 格式 53 | for (size_t c = 0; c < num_channels; c++) { 54 | for (size_t h = 0; h < height; h++) { 55 | for (size_t w = 0; w < width; w++) { 56 | input_tensor_data[c * width * height + h * width + w] = blob_image.at>(h, w)[c]; 57 | } 58 | } 59 | } 60 | return 1 / scale; 61 | } 62 | 63 | // 打印模型信息, 这个函数修改自$${OPENVINO_COMMON}/utils/src/args_helper.cpp的同名函数 64 | void printInputAndOutputsInfo(const ov::Model &network) 65 | { 66 | std::cout << "model name: " << network.get_friendly_name() << std::endl; 67 | 68 | const std::vector> inputs = network.inputs(); 69 | for (const ov::Output &input : inputs) { 70 | std::cout << " inputs" << std::endl; 71 | 72 | const std::string name = input.get_names().empty() ? "NONE" : input.get_any_name(); 73 | std::cout << " input name: " << name << std::endl; 74 | 75 | const ov::element::Type type = input.get_element_type(); 76 | std::cout << " input type: " << type << std::endl; 77 | 78 | const ov::Shape shape = input.get_shape(); 79 | std::cout << " input shape: " << shape << std::endl; 80 | } 81 | 82 | const std::vector> outputs = network.outputs(); 83 | for (const ov::Output &output : outputs) { 84 | std::cout << " outputs" << std::endl; 85 | 86 | const std::string name = output.get_names().empty() ? "NONE" : output.get_any_name(); 87 | std::cout << " output name: " << name << std::endl; 88 | 89 | const ov::element::Type type = output.get_element_type(); 90 | std::cout << " output type: " << type << std::endl; 91 | 92 | const ov::Shape shape = output.get_shape(); 93 | std::cout << " output shape: " << shape << std::endl; 94 | } 95 | } 96 | 97 | // 从argv[0]中提取本程序名称 98 | std::string_view extractedProgramName(const std::string_view programPath) 99 | { 100 | std::string_view result = programPath; 101 | if (const size_t lastSlashIndex = result.find_last_of("/\\"); // 查找最后一个反斜杠或正斜杠的位置 102 | std::string::npos != lastSlashIndex) { 103 | result = result.substr(lastSlashIndex + 1); // 从最后一个反斜杠或正斜杠之后开始截取子字符串作为程序名称 104 | } 105 | if (const size_t lastDotIndex = result.find_last_of('.'); // 查找最后一个'.'的位置 106 | std::string::npos != lastDotIndex) { 107 | result = result.substr(0, lastDotIndex); 108 | } 109 | return result; 110 | } 111 | 112 | // 将image保存为"../result/$${programName}.jpg" 113 | void save(const std::string &programName, const cv::Mat &image) 114 | { 115 | const std::filesystem::path saveDir = "../result/"; 116 | if (!std::filesystem::exists(saveDir)) { 117 | std::filesystem::create_directories(saveDir); 118 | } 119 | const std::filesystem::path savePath = saveDir / (programName + ".jpg"); 120 | cv::imwrite(savePath.string(), image); 121 | } 122 | -------------------------------------------------------------------------------- /result/CppQt_OpenVINO_YOLOv8_Image_Classification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shalvenlaw/OpenVINO_yolov8/4189d4d354f3dac9489043b75a82b0af45a6a983/result/CppQt_OpenVINO_YOLOv8_Image_Classification.jpg -------------------------------------------------------------------------------- /result/CppQt_OpenVINO_YOLOv8_Image_Detection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shalvenlaw/OpenVINO_yolov8/4189d4d354f3dac9489043b75a82b0af45a6a983/result/CppQt_OpenVINO_YOLOv8_Image_Detection.jpg -------------------------------------------------------------------------------- /result/CppQt_OpenVINO_YOLOv8_Image_OBB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shalvenlaw/OpenVINO_yolov8/4189d4d354f3dac9489043b75a82b0af45a6a983/result/CppQt_OpenVINO_YOLOv8_Image_OBB.jpg -------------------------------------------------------------------------------- /result/CppQt_OpenVINO_YOLOv8_Image_Pose.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shalvenlaw/OpenVINO_yolov8/4189d4d354f3dac9489043b75a82b0af45a6a983/result/CppQt_OpenVINO_YOLOv8_Image_Pose.jpg -------------------------------------------------------------------------------- /result/CppQt_OpenVINO_YOLOv8_Image_Segmentation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shalvenlaw/OpenVINO_yolov8/4189d4d354f3dac9489043b75a82b0af45a6a983/result/CppQt_OpenVINO_YOLOv8_Image_Segmentation.jpg --------------------------------------------------------------------------------