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

使用MFC编写一个paddleclas预测软件

目录

写作目的

环境准备

下载编译环境

解压预编译库

准备训练文件

模型文件

图像文件

路径整理

准备预测代码

创建预测应用

新建mfc应用

拷贝文档

配置环境

界面布局

添加回cpp文件

修改函数

报错1解决

报错2未解决

修改infer代码

修改MFCPaddleClasDlg.cpp代码

依赖文件纵览

依赖环境

运行结果


写作目的

为了更方便的进行图像预测。

项目源码下载:MFC-PaddleClas图像分类+带界面C++实现+项目源码资源-CSDN文库

环境准备

参考文档:PaddlePaddle/FastDeploy

下载编译环境

FastDeploy提供各平台预编译库,供开发者直接下载安装使用。当然FastDeploy编译也非常容易,开发者也可根据自身需求编译FastDeploy。

本文,我们直接下载cpu+windows版本的预编译库。链接为:cpu_windows_预编译库

解压预编译库

下载后,解压文档,就会看到如下几个文件夹。

准备训练文件

主要是模型文件和图像。

模型文件

自己使用paddleclas训练好的文件,包含以下3个文件。

图像文件

为了方便演示,我们这里只准备了两个图片。

路径整理

我们将模型和图像分别放到这两个文件夹中:

准备预测代码

这里,我们直接下载官方给我们写好的cpp文件。

地址为:下载infer.cc文件

创建预测应用

新建mfc应用

拷贝文档

将上面整理好的文档,全部拷贝到sln所在文件夹。其中1代表:编译环境;2代表训练文件;3代表预测代码【注意,需要将cc后缀修改为cpp】。

将cpp文件,添加到资源管理器的“源文件”中。

配置环境

在VC++目录中,配置包含目录:fastdeploy和opencv。

在VC++目录中,配置库目录:fastdeploy和opencv。

从如下目录拷贝opencv的opencv_world3416.lib。

添加到:链接器-输入-附加依赖项中。

界面布局

资源视图中,找到:IDD_MFCPADDLECLAS_DIALOG。开始添加各种按钮和文本编辑框。

从左侧的对话框编辑器中,添加组件。

添加完成后的截图如下:

在MFCPaddleClasDlg.h中,增加组件变量:

private:// 控件变量CButton m_btnSelectFolder_Model;//模型选择按钮CButton m_btnSelectFolder_Img; //图像路径选择按钮CButton m_btnImgPredict; //图像预测按钮CEdit m_editDirectory_Model; //模型路径编辑框	CEdit m_editDirectory_Img; //图像路径编辑框// 选定模型和图像文件夹路径CString m_selectedFolderPath_Model;CString m_selectedFolderPath_Img;

增加按钮点击后的事件处理函数:

public:afx_msg void OnBnClickedButtonFolder_Model();afx_msg void OnBnClickedButtonFolder_Img();afx_msg void OnBnClickedButtonImgPredict();

接下来,需要在实现文件MFCPaddleClasDlg.cpp中实现这些新增的函数和逻辑,以及将相应的功能,添加到对话框的事件处理函数中。

比如,增加如下代码:

void CMFCPaddleClasDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_BUTTON_model, m_btnSelectFolder_Model);DDX_Control(pDX, IDC_BUTTON_img, m_btnSelectFolder_Img);DDX_Control(pDX, IDC_EDIT_model, m_editDirectory_Model);DDX_Control(pDX, IDC_EDIT_img, m_editDirectory_Img);
}

在BEGIN_MESSAGE_MAP增加如下代码:

BEGIN_MESSAGE_MAP(CMFCPaddleClasDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()// 增加ON_BN_CLICKED(IDC_BUTTON_model, &CMFCPaddleClasDlg::OnBnClickedButtonFolder_Model)ON_BN_CLICKED(IDC_BUTTON_img, &CMFCPaddleClasDlg::OnBnClickedButtonFolder_Img)ON_BN_CLICKED(IDC_BUTTON_predict, &CMFCPaddleClasDlg::OnBnClickedButtonImgPredict)
END_MESSAGE_MAP()

实现函数OnBnClickedButtonFolder_Model,OnBnClickedButtonFolder_Img。具体如下:

void CMFCPaddleClasDlg::OnBnClickedButtonFolder_Model()
{CFolderPickerDialog folderDlg;if (folderDlg.DoModal() == IDOK){m_selectedFolderPath_Model = folderDlg.GetPathName();m_editDirectory_Model.SetWindowText(m_selectedFolderPath_Model);}
}void CMFCPaddleClasDlg::OnBnClickedButtonFolder_Img()
{CFolderPickerDialog folderDlg;if (folderDlg.DoModal() == IDOK){m_selectedFolderPath_Img = folderDlg.GetPathName();m_editDirectory_Img.SetWindowText(m_selectedFolderPath_Img);}
}

以及OnBnClickedButtonImgPredict,代码如下:

void CMFCPaddleClasDlg::OnBnClickedButtonImgPredict()
{// 检查模型和图片路径是否已经选择if (m_selectedFolderPath_Model.IsEmpty() || m_selectedFolderPath_Img.IsEmpty()){AfxMessageBox(_T("请先选择模型和图片的文件夹路径。"), MB_ICONWARNING);return;}// 执行预测,这里假设有一个函数ExecutePrediction,它接受图片路径并返回预测结果CString predictionResult = ExecutePrediction(m_selectedFolderPath_Img);if (predictionResult.IsEmpty()){AfxMessageBox(_T("图片预测失败。"), MB_ICONERROR);return;}// 显示预测结果AfxMessageBox(_T("预测结果: ") + predictionResult);
}// 以下是ExecutePrediction的示例实现,需要根据实际情况进行修改
CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
{// 执行预测的逻辑// 返回预测结果return _T("预测结果"); // 示例代码,实际应根据预测结果返回
}

由于我们又额外定义了1个函数,因此,需要在.h文件里面进行函数声明。如下:

由于我们还没有用到infer.cpp文件,所以暂时,先将其移除。

当我们点击运行后,就会看到如下界面:

然后,当我们如果不输入任何路径,直接点击”图像预测按钮“,就会出来如下提示:

添加回cpp文件

将infer.cpp文件加回来,并且修改代码:

#原来的代码
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#include "fastdeploy/vision.h"
#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endifvoid InitAndInfer(const std::string &model_dir, const std::string &image_file,const fastdeploy::RuntimeOption &option) {auto model_file = model_dir + sep + "inference.pdmodel";auto params_file = model_dir + sep + "inference.pdiparams";auto config_file = model_dir + sep + "inference_cls.yaml";auto model = fastdeploy::vision::classification::PaddleClasModel(model_file, params_file, config_file, option);if (!model.Initialized()) {std::cerr << "Failed to initialize." << std::endl;return;}auto im = cv::imread(image_file);fastdeploy::vision::ClassifyResult res;if (!model.Predict(im, &res)) {std::cerr << "Failed to predict." << std::endl;return;}// print resstd::cout << res.Str() << std::endl;
}int main(int argc, char *argv[]) {if (argc < 4) {std::cout << "Usage: infer_demo path/to/model path/to/image run_option, ""e.g ./infer_demo ./ResNet50_vd ./test.jpeg 0"<< std::endl;return -1;}fastdeploy::RuntimeOption option;int flag = std::atoi(argv[3]);if (flag == 0) {option.UseCpu();option.UsePaddleBackend();  // Paddle Inference} else if (flag == 1) {option.UseCpu();option.UseOpenVINOBackend();  // OpenVINO} else if (flag == 2) {option.UseCpu();option.UseOrtBackend();  // ONNX Runtime} else if (flag == 3) {option.UseCpu();option.UseLiteBackend();  // Paddle Lite} else if (flag == 4) {option.UseGpu();option.UsePaddleBackend();  // Paddle Inference} else if (flag == 5) {option.UseGpu();option.UsePaddleInferBackend();option.paddle_infer_option.enable_trt = true;} else if (flag == 6) {option.UseGpu();option.UseOrtBackend();  // ONNX Runtime} else if (flag == 7) {option.UseGpu();option.UseTrtBackend();  // TensorRT}std::string model_dir = argv[1];std::string image_dir = argv[2];InitAndInfer(model_dir, image_dir, option);
}

修改原来的代码为如下【去除命令行传参,而是使用参数传递】:

#include "fastdeploy/vision.h"
#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endifvoid InitAndInfer(const std::string &model_dir, const std::string &image_file,const fastdeploy::RuntimeOption &option) {auto model_file = model_dir + sep + "inference.pdmodel";auto params_file = model_dir + sep + "inference.pdiparams";auto config_file = model_dir + sep + "inference_cls.yaml";auto model = fastdeploy::vision::classification::PaddleClasModel(model_file, params_file, config_file, option);if (!model.Initialized()) {std::cerr << "Failed to initialize." << std::endl;return;}auto im = cv::imread(image_file);fastdeploy::vision::ClassifyResult res;if (!model.Predict(im, &res)) {std::cerr << "Failed to predict." << std::endl;return;}// print resstd::cout << res.Str() << std::endl;
}int main() {// 直接指定模型目录和图片文件路径std::string model_dir = "./ResNet50_vd";std::string image_file = "./test.jpeg";// 设置运行选项fastdeploy::RuntimeOption option;// 根据需要选择CPU或GPUoption.UseCpu(); // 或者 option.UseGpu(); 来使用GPUoption.UsePaddleBackend();  // Paddle Inference// 调用InitAndInfer函数InitAndInfer(model_dir, image_file, option);return 0;
}

修改函数

当用户点击按钮预测,运行OnBnClickedButtonImgPredict函数,这个函数要调用infer.cpp函数的代码。如何修改代码呢?

首先,在头文件夹中,新建一个infer.h文件。写入如下代码:

// infer.h
#pragma once#include "fastdeploy/vision.h"
#include <string>std::string InitAndInfer(const std::string& model_dir, const std::string& image_file,const fastdeploy::RuntimeOption& option);

在MFCPaddleClasDlg.cpp代码中增加如下头文件:

#include"infer.h"// 包含infer.cpp的头文件

修改infer.cpp文件如下:【需要注意】#include "pch.h"一定不要忘记添加,否则运行会出错。

严重性	代码	说明	项目	文件	行	禁止显示状态
错误	C1010	在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "pch.h"”?	MFCPaddleClas	C:\Users\source\repos\MFCPaddleClas\infer.cpp	43	

// infer.cpp
#include "pch.h"
#include "infer.h"
#include "fastdeploy/vision.h"
#include <opencv2/opencv.hpp>
#include <string>
#include <iostream>#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endifstd::string InitAndInfer(const std::string& model_dir, const std::string& image_file,const fastdeploy::RuntimeOption& option) {auto model_file = model_dir + sep + "inference.pdmodel";auto params_file = model_dir + sep + "inference.pdiparams";auto config_file = model_dir + sep + "inference_cls.yaml";auto model = fastdeploy::vision::classification::PaddleClasModel(model_file, params_file, config_file, option);if (!model.Initialized()) {std::cerr << "模型初始化失败." << std::endl;return "模型初始化失败";}auto im = cv::imread(image_file);if (im.empty()) {std::cerr << "读取图像失败." << std::endl;return "Failed to read image";}fastdeploy::vision::ClassifyResult res;if (!model.Predict(im, &res)) {std::cerr << "预测失败." << std::endl;return "预测失败";}// Return the result as a stringreturn res.Str();
}

修改CMFCPaddleClasDlg::ExecutePrediction函数如下:

CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
{// 将CString转换为std::stringCT2CA pszModelPath(m_selectedFolderPath_Model);std::string strModelPath(pszModelPath);CT2CA pszImagePath(imagePath);std::string strImagePath(pszImagePath);// 调用infer.cpp中的InitAndInfer函数fastdeploy::RuntimeOption option;option.UseCpu();option.UsePaddleBackend();std::string result = InitAndInfer(strModelPath, strImagePath, option);// 将结果转换回CStringCString cstrResult(result.c_str());return cstrResult;
}

报错1解决

现在运行程序,会出现如下错误:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误	LNK2001	无法解析的外部符号 "__declspec(dllimport) public: __cdecl fastdeploy::vision::classification::PaddleClasModel::PaddleClasModel(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,struct fastdeploy::RuntimeOption const &,enum fastdeploy::ModelFormat const &)" (__imp_??0PaddleClasModel@classification@vision@fastdeploy@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@00AEBURuntimeOption@3@AEBW4ModelFormat@3@@Z)	MFCPaddleClas	C:\Users\source\repos\MFCPaddleClas\infer.obj	1	

这个原因的因为附加依赖项中,缺少fastdeploy.dll文件,我们添加进来就好了。如下:

这时,再次运行程序,就会出现:

这说明,程序运行时需要的动态库dll没有放到exe所在目录,我们加进去,一共有几个呢?如下几个文件夹中,各自的dll文件,都要复制过去,外加:fastdeploy.dll,tbb.dll,mkldnn.dll,icuuc70.dll,icudt70.dll【已经验证,的确如此!】。

tbb.dll:是 英特尔线程构建块库中的一个关键组件,它提供了一组线程并行编程工具,对于运行某些依赖于此库的软件或游戏至关重要。 位于:fastdeploy-win-x64-1.0.7\third_libs\install\openvino\runtime\3rdparty\tbb\bin;
mkldnn.dll:是  Intel MKL-DNN(Math Kernel Library for Deep Neural Networks)的动态链接库文件。 MKL-DNN 是由 Intel 开发的一个开源库,专门针对在 CPU 上运行的深度学习应用进行了优化,以提高性能。 这个库提供了一套 API,用于深度学习中的各种操作,比如卷积、池化等,并且能够利用 Intel 处理器的 SIMD 指令集(如 AVX2)来加速这些操作。 在使用 MKL-DNN 时, mkldnn.dll 文件作为动态库被应用程序在运行时调用,以实现对深度学习模型的加速。 位于:fastdeploy\third_libs\install\paddle_inference\third_party\install\mkldnn\lib
icuuc70.dll:属于  International Components for Unicode (ICU) 项目的一部分。 ICU 是一个成熟、广泛使用的开源软件库,提供 Unicode 和全球化支持。 这个库包含了多个组件,用于支持各种软件开发中的字符串处理、日期/时间格式化、数字格式化等国际化功能。位于:fastdeploy\third_libs\install\fast_tokenizer\third_party\lib
icudt70.dll: International Components for Unicode (ICU) 项目的一部分,这是一个提供 Unicode 和全球化支持的成熟、广泛使用的开源软件库。ICU 包含了多个组件,用于支持软件开发中的字符串处理、日期/时间格式化、数字格式化等国际化功能。位于:fastdeploy\third_libs\install\fast_tokenizer\third_party\lib

再次运行报错如下[未加载kernelbase.pdb]

后来,查阅资料,是因为缺少一些东西:

  1. openvino相关库
  2. plugins.xml文件

因此,补充这两个文件后,不报这个错了:[未加载kernelbase.pdb]。但是,又出来了其他错误:

未处理的异常:auto model = fastdeploy::vision::classification::PaddleClasModel

报错2未解决

这个报错,实在是找不到解决方案。【搞了很久,头要炸了!!!】

因此,我用了自己之前编译好的fastdeploy【点击链接下载:【Windows-x64-gpu或者cpu预测】编译好的FastDeploy环境资源-CSDN文库】,就解决了这个问题!!!

修改infer代码

// infer.cpp
#include "pch.h" // 确保pch.h在包含其他头文件之前
#include "fastdeploy/vision.h"
#include <string>
#include <iostream>
#include <opencv2/opencv.hpp> // 包含OpenCV的头文件
#include <filesystem> // C++17文件系统库,用于遍历文件夹#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endifnamespace fs = std::filesystem; // 文件系统命名空间别名std::vector<std::string> InitAndInfer(const std::string& model_dir, const std::string& image_folder, const fastdeploy::RuntimeOption& option) {std::vector<std::string> results;  // 存储每个图像的预测结果// 构建模型文件路径auto model_file = model_dir + sep + "inference.pdmodel";auto params_file = model_dir + sep + "inference.pdiparams";auto config_file = model_dir + sep + "inference_cls.yaml";// 加载模型auto model = fastdeploy::vision::classification::PaddleClasModel(model_file, params_file, config_file, option);if (!model.Initialized()) {std::cerr << "Failed to initialize." << std::endl;return results;  // 如果初始化失败,返回空结果}// 遍历文件夹中的所有图像for (const auto& entry : fs::directory_iterator(image_folder)) {if (entry.is_regular_file()) {auto image_file = entry.path().string();auto im = cv::imread(image_file);if (im.empty()) {std::cerr << "Failed to read image: " << image_file << std::endl;continue; // 如果读取图像失败,则跳过当前图像}fastdeploy::vision::ClassifyResult res;int topk = 20;if (!model.Predict(&im, &res, topk)) {std::cerr << "Failed to predict for image: " << image_file << std::endl;continue; // 如果预测失败,则跳过当前图像}// 将结果添加到返回的容器中results.push_back("Image: " + image_file + " - " + res.Str());}}return results;  // 返回结果
}

修改MFCPaddleClasDlg.cpp代码

// MFCPaddleClasDlg.cpp: 实现文件
//#include "pch.h"
#include "framework.h"
#include "MFCPaddleClas.h"
#include "MFCPaddleClasDlg.h"
#include "afxdialogex.h"
#include "infer.h" // 包含infer.cpp的头文件
#include "fastdeploy/vision.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CMFCPaddleClasDlg 对话框CMFCPaddleClasDlg::CMFCPaddleClasDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_MFCPADDLECLAS_DIALOG, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CMFCPaddleClasDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_BUTTON_model, m_btnSelectFolder_Model);DDX_Control(pDX, IDC_BUTTON_img, m_btnSelectFolder_Img);DDX_Control(pDX, IDC_EDIT_model, m_editDirectory_Model);DDX_Control(pDX, IDC_EDIT_img, m_editDirectory_Img);
}BEGIN_MESSAGE_MAP(CMFCPaddleClasDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()// 增加ON_BN_CLICKED(IDC_BUTTON_model, &CMFCPaddleClasDlg::OnBnClickedButtonFolder_Model)ON_BN_CLICKED(IDC_BUTTON_img, &CMFCPaddleClasDlg::OnBnClickedButtonFolder_Img)ON_BN_CLICKED(IDC_BUTTON_predict, &CMFCPaddleClasDlg::OnBnClickedButtonImgPredict)
END_MESSAGE_MAP()// CMFCPaddleClasDlg 消息处理程序BOOL CMFCPaddleClasDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CMFCPaddleClasDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CMFCPaddleClasDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCPaddleClasDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CMFCPaddleClasDlg::OnBnClickedButtonFolder_Model()
{CFolderPickerDialog folderDlg;if (folderDlg.DoModal() == IDOK){m_selectedFolderPath_Model = folderDlg.GetPathName();m_editDirectory_Model.SetWindowText(m_selectedFolderPath_Model);}
}void CMFCPaddleClasDlg::OnBnClickedButtonFolder_Img()
{CFolderPickerDialog folderDlg;if (folderDlg.DoModal() == IDOK){m_selectedFolderPath_Img = folderDlg.GetPathName();m_editDirectory_Img.SetWindowText(m_selectedFolderPath_Img);}
}void CMFCPaddleClasDlg::OnBnClickedButtonImgPredict()
{// 检查模型和图片路径是否已经选择if (m_selectedFolderPath_Model.IsEmpty() || m_selectedFolderPath_Img.IsEmpty()){AfxMessageBox(_T("请先选择模型和图片的文件夹路径。"), MB_ICONWARNING);return;}// 执行预测,这里假设有一个函数ExecutePrediction,它接受图片路径并返回预测结果CString predictionResult = ExecutePrediction(m_selectedFolderPath_Img);if (predictionResult.IsEmpty()){AfxMessageBox(_T("图片预测失败。"), MB_ICONERROR);return;}// 显示预测结果AfxMessageBox(_T("预测结果: ") + predictionResult);
}//CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
//{
//	// 执行预测的逻辑
//	// 返回预测结果
//	return _T("预测结果"); // 示例代码,实际应根据预测结果返回
//}
//CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
//{
//	// 将CString转换为std::string
//	std::string model_dir = std::string(CT2CA(m_selectedFolderPath_Model));
//	std::string image_file = std::string(CT2CA(imagePath));
//
//	// 设置运行选项
//	fastdeploy::RuntimeOption option;
//	// 根据需要选择CPU或GPU
//	option.UseCpu(); // 或者 option.UseGpu(); 来使用GPU
//	//option.UsePaddleBackend();  // Paddle Inference
//
//	// 调用InitAndInfer函数,获取预测结果
//	std::vector<std::string> results = InitAndInfer(model_dir, image_file, option);
//
//	// 输出结果
//	for (const auto& res : results) {
//		std::cout << res << std::endl;
//	}
//	return _T("预测结果"); // 示例代码,实际应根据预测结果返回
//}CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
{// 将CString转换为std::stringstd::string model_dir = std::string(CT2CA(m_selectedFolderPath_Model));std::string image_file = std::string(CT2CA(imagePath));// 设置运行选项fastdeploy::RuntimeOption option;//option.UseCpu();  // 或者 option.UseGpu(); 来使用GPUoption.UseGpu();// 调用InitAndInfer函数,获取预测结果std::vector<std::string> results = InitAndInfer(model_dir, image_file, option);// 拼接所有结果std::string concatenatedResults;for (const auto& res : results) {concatenatedResults += res + "\n";  // 使用换行符分隔每个结果}// 返回拼接后的字符串return CString(concatenatedResults.c_str());
}

依赖文件纵览

模型文件

图像文件

Release文件内容
Release文件内容

依赖环境

包含目录

库目录

依赖项

运行结果

运行软件,输入模型和图像路径,给出结果如下:

大功告成!

相关文章:

使用MFC编写一个paddleclas预测软件

目录 写作目的 环境准备 下载编译环境 解压预编译库 准备训练文件 模型文件 图像文件 路径整理 准备预测代码 创建预测应用 新建mfc应用 拷贝文档 配置环境 界面布局 添加回cpp文件 修改函数 报错1解决 报错2未解决 修改infer代码 修改MFCPaddleClasDlg.cp…...

SAP SD BP名称和销售订单描述的对应不起来的问题

问题 VBPA-ADRNR地址 和 KNA1-ADRNR 指向同一个号码 销售订单读取这个地址 改正后恢复正常 原因&#xff1a;推测 应该是创建Y0 电商客户的时候&#xff0c;引起锁和混乱导致的。 具体实际时什么样&#xff0c;不太清楚 写于20241230 浙江台州...

FlastOcc-网络复现-1.环境配置及问题

研究OCC网络 1.RuntimeError: Ninja is required to load C extensions RuntimeError: Ninja is required to load C extensions #32 Ninja is required to load C extensions File “/FlashOCC/projects/mmdet3d_plugin/core/evaluation/ray_metrics.py”, line 12, in dvr …...

Go语言中值接收者和指针接收者的区别?

在 Go 语言中&#xff0c;值接收者和指针接收者是方法定义中的两种接收者类型。它们的主要区别在于方法调用时的行为、接收者是否可以被修改&#xff0c;以及性能上的差异。 值接收者 定义 值接收者的方法接收的是调用对象的一个副本&#xff0c;方法内部对该副本的修改不会影…...

kafka小实站

需要先在前面的文章里面照着下载好kafka&#xff0c;并且启动 先启动zookeeper 项目目录 package kafka; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.kafka.annotation.KafkaListener; import…...

基于Python实现车辆检测、机动车检测、识别位置标记、计数

目录 引言背景与应用场景车辆检测的研究意义相关工作车辆检测概述机动车检测方法分类基于传统计算机视觉的检测方法基于深度学习的检测方法技术与方法车辆检测技术概述基于Python的车辆检测方法图像处理与特征提取深度学习方法(如YOLO、SSD、Faster R-CNN等)数据集与标注常用…...

心理学硕士

心理学硕士的主要研究方向包括基础心理学、发展心理学和应用心理学‌。 基础心理学研究一般的心理现象与规律&#xff0c;如心理的实质及神经机制、感觉与知觉、意识与注意、学习与记忆、思维与语言、情绪与意识、人格等‌。发展心理学研究人类个体心理发生发展的特点和规律&a…...

python量化分析学习与实践1:API接口篇

业内比较流行的几款API数据接口&#xff0c;有聚宽、TuShare&#xff0c;yfinance&#xff0c;以及pandas的pandas_datareader等。国内的一般都需要用户认证&#xff0c;才能下载数据。国外的yfinance与pandas_datareader等则不需要&#xff0c;但需要科学上网。 聚宽 测试下…...

【GO基础学习】gin的使用

文章目录 模版使用流程参数传递路由分组数据解析和绑定gin中间件 模版使用流程 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 1.创建路由r : gin.Default()// 2.绑定路由规则&#xff0c;执行的函数// gin.Context&#x…...

网卡状态变更,virtio-net检测

实现方案&#xff1a; 现在在amp模式下linux端有个真实的物理网卡eth0&#xff0c;有一个虚拟网卡virtio-net0后端&#xff0c;此时需要一种机制&#xff0c;将真实物理网卡的状态发送rtos的virtio-net0前端。这里使用register_netdevice_notifier机制&#xff0c;每个virtio-n…...

中华人民共和国保守国家秘密法

中华人民共和国保守国家秘密法 &#xff08;1988年9月5日第七届全国人民代表大会常务委员会第三次会议通过 2010年4月29日第十一届全国人民代表大会常务委员会第十四次会议第一次修订 2024年2月27日第十四届全国人民代表大会常务委员会第八次会议第二次修订&#xff09; 目…...

ELK日志收集系统部署

1、 ElasticSearch部署 Elastic — 搜索 AI 公司 | Elastic 系统类型&#xff1a;Centos7.4 节点IP&#xff1a;172.16.246.234 软件版本&#xff1a;jdk-8u191-linux-x64.tar.gz、elasticsearch-6.5.4.tar.gz 示例节点&#xff1a;172.16.246.234 1、安装配置jdk8 ES运行依…...

3D线上艺术展:艺术与技术的完美融合

随着数字技术的飞速发展&#xff0c;未来的艺术展览正逐步迈向线上线下融合的新阶段。其中&#xff0c;3D线上展览以其独特的魅力&#xff0c;成为线下展览的延伸与拓展&#xff0c;为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言&#xff0c;3D线上展览不仅打…...

TiDB 的MPP架构概述

MPP架构介绍&#xff1a; 如图&#xff0c;TiDB Server 作为协调者&#xff0c;首先 TiDB Server 会把每个TiFlash 拥有的region 会在TiFlash上做交换&#xff0c;让表连接在一个TiFlash上。另外 TiFlash会作为计算节点&#xff0c;每个TiFlash都负责数据交换&#xff0c;表连接…...

Leetcode 10-正则表达式匹配/ 剑指 Offer 19. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ‘*’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分字符串。 题解 字符串匹配多…...

FFmpeg 编码和解码

文章目录 音频格式AACADIF音频数据交换格式ADTS音频数据传输流 音频解码音频编码 视频格式H264GOP图像组I帧&#xff0c;P帧&#xff0c;B帧H264压缩技术H264压缩级别H264视频级别H264码流结构SPSPPS 解码视频编码视频 音频格式 AAC AAC全称 Advanced Audio Coding&#xff0…...

kali当中web扫描工具的用法

1. cadaver 用途&#xff1a;用于与WebDAV服务器交互&#xff0c;可进行文件上传、下载、目录浏览等操作。使用方法 连接到WebDAV服务器&#xff1a;cadaver <WebDAV服务器地址>&#xff0c;例如cadaver https://example.com/dav&#xff0c;然后按提示输入用户名和密码…...

深度剖析 Android Animation 框架

深度剖析 Android Animation 框架 目录 引言Android Animation 框架概述架构设计 3.1 核心类与接口3.2 动画类型3.3 动画执行流程使用指南 4.1 属性动画4.2 视图动画4.3 过渡动画设计模式 5.1 策略模式5.2 观察者模式5.3 工厂模式核心逻辑 6.1 动画插值器6.2 动画估值器6.3 动…...

泰山派GPIO子系统驱动---亮灯

本人linux驱动小白&#xff0c;文章基于B站up主 李Sir______ 视频内容记录&#xff0c;做笔记用。如有错误欢迎指正。本文将以开发板第40引脚GPIO3_B4作为LED灯珠的控制引脚&#xff0c;高电平灯亮&#xff0c;低电平灯灭。 杂话 在linux内核中&#xff0c;芯片厂商已经把所有…...

【C#特性整理】C#特性及语法基础

1. C#特性 1.1 统一的类型系统 C#中, 所有类型都共享一个公共的基类型. 例如&#xff0c;任何类型的实例都可以通过调用ToString方法将自身转换为一个字符串 1.2 类和接口 接口: 用于将标准与实现隔离, 仅仅定义行为,不做实现. 1.3 属性、方法、事件 属性: 封装了一部分对…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...