当前位置: 首页 > news >正文

使用mmdeploy框架C++预测mask并绘制最小外接矩形

目录

解决目标

逻辑思路

代码实现

第1部分

第2部分


解决目标

这段代码实现了,一个基于深度学习的图像检测程序。它使用mmdeploy框架,加载一个预训练的模型【实例分割模型】来检测图像中的物体。

逻辑思路

程序首先加载模型,然后,在指定的输入文件夹中,遍历所有JPG图像,对每张图像进行重复检测(默认2次),并绘制每个检测到的物体掩码的最大区域的最小外接矩形。这些矩形以绿色线条绘制在图像上,并且每次检测的结果都会保存到输出文件夹中。

同时,检测结果(包括图像名称、预测次数、标签ID和得分)会被记录到一个文本文件中。程序完成后,会提示用户按Enter键退出。

代码实现

我们有两部分代码。第一部分是每一次预测的结果框,都绘制到一个单独的图上。第二部分是,每一次预测结果都绘制到同一个图上。

第1部分

#include <filesystem>
#include <mmdeploy/detector.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include "utils/visualize.h"// 指定模型路径和输入图像文件夹路径
const std::string sModelPath = "path_to_model";
const std::string sInputFolderPath = "path_to_images";  // 替换为你的图像文件夹路径
const std::string sOutputFolderPath = "output_images";  // 输出图像文件夹路径
const float fDetectionThreshold = 0.9;
const std::string sDevice = "cpu"; // 根据实际情况选择设备(默认为cpu)
int iWarmUpCount = 20;  // 预热次数
int iRepetitions = 10000;  // 重复遍历次数// 加载图像
bool LoadImageFromFile(const std::string& sFilePath, cv::Mat& matImage) {matImage = cv::imread(sFilePath);if (matImage.empty()) {fprintf(stderr, "Failed to load image: %s\n", sFilePath.c_str());return false;}return true;
}// 查找最大轮廓
std::vector<cv::Point> GetLargestContour(const std::vector<std::vector<cv::Point>>& vecContours) {double dMaxArea = 0.0;std::vector<cv::Point> vecLargestContour;for (const auto& vecContour : vecContours) {double dArea = cv::contourArea(vecContour);if (dArea > dMaxArea) {dMaxArea = dArea;vecLargestContour = vecContour;}}return vecLargestContour;
}int main() {std::ofstream ofsResultFile("detection_results.txt"); // 输出结果的文本文件// 初始化性能分析器mmdeploy::Profiler profiler("/tmp/profile.bin");// 创建上下文环境mmdeploy::Context context;context.Add(mmdeploy::Device(sDevice));context.Add(profiler);// 创建检测器实例mmdeploy::Detector detector(mmdeploy::Model{ sModelPath }, context);// 获取所有jpg文件路径std::vector<std::string> vecImagePaths;for (const auto& entry : std::filesystem::directory_iterator(sInputFolderPath)) {if (entry.is_regular_file() && entry.path().extension() == ".jpg") {vecImagePaths.push_back(entry.path().generic_u8string());}}// 预热cv::Mat matImage;if (LoadImageFromFile(vecImagePaths[0], matImage)) { // 使用vecImagePaths的第一个元素for (int i = 0; i < iWarmUpCount; ++i) {detector.Apply(matImage);}} else {std::cerr << "Failed to load image during warm-up!" << std::endl;}// 遍历图像文件for (const auto& entry : std::filesystem::directory_iterator(sInputFolderPath)) {const std::string sInputImagePath = entry.path().generic_u8string();std::string sCurrentImageName = entry.path().filename().string();std::cout << "Predicting on image: " << sCurrentImageName << std::endl;cv::Mat matImage;if (!LoadImageFromFile(sInputImagePath, matImage)) {continue;}// 创建原图副本用于绘制外接矩形cv::Mat matColoredRects = matImage.clone();for (int iRepetition = 0; iRepetition < iRepetitions; ++iRepetition) {mmdeploy::Detector::Result result = detector.Apply(matImage);if (result.size() == 0) {std::cout << "Error: result.size() == 0" << std::endl;std::cin.get();}// 绘制外接矩形for (const mmdeploy_detection_t& detection : result) {if (detection.score > fDetectionThreshold && detection.mask) {cv::Mat matMaskImage(matImage.size(), CV_8UC1, cv::Scalar(0)); // 掩码图像cv::Rect rect(static_cast<int>(detection.bbox.left), static_cast<int>(detection.bbox.top),static_cast<int>(detection.bbox.right - detection.bbox.left),static_cast<int>(detection.bbox.bottom - detection.bbox.top));// 提取并调整掩码尺寸cv::Mat matMask(detection.mask->height, detection.mask->width, CV_8UC1, detection.mask->data);cv::resize(matMask, matMask, rect.size());matMask.copyTo(matMaskImage(rect));// 寻找轮廓std::vector<std::vector<cv::Point>> vecContours;cv::findContours(matMaskImage, vecContours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 找到最大轮廓std::vector<cv::Point> vecLargestContour = GetLargestContour(vecContours);// 计算最小外接矩形if (!vecLargestContour.empty()) {cv::RotatedRect rotatedRect = cv::minAreaRect(vecLargestContour);cv::Point2f points[4];rotatedRect.points(points);// 绘制矩形for (int j = 0; j < 4; j++) {cv::line(matColoredRects, points[j], points[(j + 1) % 4], cv::Scalar(0, 255, 0), 8);}}std::cout << "Image: " << sCurrentImageName << " Iteration " << iRepetition<< ", Label: " << detection.label_id << ", Score: " << detection.score << std::endl;ofsResultFile << "Image: " << sCurrentImageName << " Iteration " << iRepetition<< ", Label: " << detection.label_id << ", Score: " << detection.score << "\n";}}// 保存图像副本std::string sOutputImagePath = sOutputFolderPath + "/" + entry.path().stem().string() + "_iteration_" + std::to_string(iRepetition) + ".png";cv::imwrite(sOutputImagePath, matColoredRects);ofsResultFile << "----" << std::endl;}}ofsResultFile.close();std::cout << "Program finished. Press Enter to exit..." << std::endl;std::cin.get();return 0;
}

第2部分

#include "filesystem"
#include "mmdeploy/detector.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "utils/visualize.h"
#include <iostream>
#include <vector>
#include <string>
#include <fstream>// 配置文件路径和参数
const std::string cfgModelPath = "path_to_model";
const std::string cfgInputDir = "input_images";  // 指定图像文件夹路径
const std::string cfgOutputDir = "output_results";  // 结果输出文件夹路径
const float cfgThreshold = 0.9;
const std::string cfgDevice = "cpu"; // 设备选择(默认为cpu)
int cfgWarmups = 20;  // 预热次数
int cfgIterations = 10000;  // 重复次数// 图像加载函数
bool imgLoader(const std::string& file_path, cv::Mat& matrix) {matrix = cv::imread(file_path);if (matrix.empty()) {fprintf(stderr, "Error loading image: %s\n", file_path.c_str());return false;}return true;
}// 最大轮廓查找函数
std::vector<cv::Point> maxContourFinder(const std::vector<std::vector<cv::Point>>& contourList) {double largestArea = 0.0;std::vector<cv::Point> maxContour;for (const auto& contour : contourList) {double area = cv::contourArea(contour);if (area > largestArea) {largestArea = area;maxContour = contour;}}return maxContour;
}// 绘制颜色数组
const cv::Scalar drawColors[] = {cv::Scalar(0, 255, 0), // Greencv::Scalar(0, 0, 255), // Redcv::Scalar(255, 0, 0), // Bluecv::Scalar(0, 255, 255), // Cyancv::Scalar(255, 255, 0), // Yellowcv::Scalar(255, 0, 255), // Magentacv::Scalar(128, 0, 0), // Dark Redcv::Scalar(0, 128, 0), // Dark Greencv::Scalar(0, 0, 128), // Dark Blue// Additional colors can be added here
};int main() {std::ofstream outputLog("analysis_results.txt"); // 结果日志文件// 性能分析器初始化mmdeploy::Profiler perfProfiler("/tmp/perf_profile.bin");// 上下文环境配置mmdeploy::Context envContext;envContext.Add(mmdeploy::Device(cfgDevice));envContext.Add(perfProfiler);// 检测器实例化mmdeploy::Detector objectDetector(mmdeploy::Model{ cfgModelPath }, envContext);// 读取图像文件路径std::vector<std::string> filePaths;for (const auto& dirEntry : std::filesystem::directory_iterator(cfgInputDir)) {if (dirEntry.is_regular_file() && dirEntry.path().extension() == ".jpg") {filePaths.push_back(dirEntry.path().generic_u8string());}}// 预热操作cv::Mat warmupImg;if (imgLoader(filePaths[0], warmupImg)) { // 使用filePaths的第一个元素进行预热for (int i = 0; i < cfgWarmups; ++i) {objectDetector.Apply(warmupImg);}} else {std::cerr << "Failed to load image during warm-up!" << std::endl;}// 处理图像文件for (const auto& dirEntry : std::filesystem::directory_iterator(cfgInputDir)) {const std::string imgFilePath = dirEntry.path().generic_u8string();std::string imgFileName = dirEntry.path().filename().string();std::cout << "Processing image: " << imgFileName << std::endl;cv::Mat imageMatrix;if (!imgLoader(imgFilePath, imageMatrix)) {continue;}for (int iter = 0; iter < cfgIterations; ++iter) {// 绘制副本cv::Mat drawingCopy = imageMatrix.clone();mmdeploy::Detector::Result detectionResults = objectDetector.Apply(imageMatrix);if (detectionResults.size() == 0) {std::cout << "Error: Empty detection results" << std::endl;std::cin.get();}// 绘制检测结果for (const mmdeploy_detection_t& detection : detectionResults) {if (detection.score > cfgThreshold && detection.mask) {// 选择颜色cv::Scalar color = drawColors[iter % (sizeof(drawColors) / sizeof(cv::Scalar))];cv::Mat maskImage(imageMatrix.size(), CV_8UC1, cv::Scalar(0)); // 掩码图像初始化cv::Rect region(static_cast<int>(detection.bbox.left), static_cast<int>(detection.bbox.top),static_cast<int>(detection.bbox.right - detection.bbox.left),static_cast<int>(detection.bbox.bottom - detection.bbox.top));// 掩码调整cv::Mat mask(detection.mask->height, detection.mask->width, CV_8UC1, detection.mask->data);cv::resize(mask, mask, region.size());mask.copyTo(maskImage(region));// 轮廓查找std::vector<std::vector<cv::Point>> contourList;cv::findContours(maskImage, contourList, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 最大轮廓std::vector<cv::Point> largestContour = maxContourFinder(contourList);// 最小外接矩形计算if (!largestContour.empty()) {cv::RotatedRect minRect = cv::minAreaRect(largestContour);cv::Point2f rectPoints[4];minRect.points(rectPoints);// 绘制矩形for (int j = 0; j < 4; j++) {cv::line(drawingCopy, rectPoints[j], rectPoints[(j + 1) % 4], color, 8);}}std::cout << "Image: " << imgFileName << " Iteration " << iter<< ", Label: " << detection.label_id << ", Confidence: " << detection.score << std::endl;outputLog << "Image: " << imgFileName << " Iteration " << iter<< ", Label: " << detection.label_id << ", Confidence: " << detection.score << "\n";}}// 结果保存std::string resultImagePath = cfgOutputDir + "/" + "result_" + dirEntry.path().stem().string() + ".png";cv::imwrite(resultImagePath, drawingCopy);}outputLog << "----" << std::endl;}outputLog.close();std::cout << "Processing complete. Press Enter to exit..." << std::endl;std::cin.get();return 0;
}

希望能帮助到你!


http://www.mrgr.cn/news/79596.html

相关文章:

  • DocFlow票据AI自动化处理工具:出色的文档解析+抽取能力,提升企业文档数字化管理效能
  • 【C++】LeetCode:LCR 078. 合并 K 个升序链表
  • 设计模式之原型模式:深入浅出讲解对象克隆
  • CSS的2D和3D动画效果
  • 微信小程序:实现节点进度条的效果;正在完成的节点有动态循环效果;横向,纵向排列
  • 什么是多线程中的上下文切换
  • 排序算法(1):冒泡排序
  • STM32F103 FPGA进行通信方式
  • 第四十六篇 Vision Transformer论文翻译
  • 【开源】A065—基于SpringBoot的库存管理系统的设计与实现
  • java中的抽象类
  • Redis安装和Python练习(Windows11 + Python3.X + Pycharm社区版)
  • 人工智能大模型LLM开源资源汇总(持续更新)
  • 【光电倍增管】-打拿极 PMT
  • SpringBoot3整合Druid数据源
  • 配置新电脑设置的脚本
  • 嵌入式入门Day26
  • android NumberPicker隐藏分割线或修改颜色
  • android notification
  • Python 检验项目分析与历次报告比对
  • SpringBoot3整合SpringMVC
  • 制造业信息化系统:构建高效生产与管理的数字化基石
  • 阿里云 云产品流转(实现设备与小程序交互)
  • c++ 学习笔记 函数进阶
  • Python知识分享第二十二天-数据结构入门
  • LEGO-GraphRAG框架-图谱检索增强生成框架介绍