目录
写作目的
为了更方便的进行图像预测。
项目源码下载:MFC-PaddleClas图像分类+带界面C++实现+项目源码资源-CSDN文库
环境准备
下载编译环境
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 = '/';
#endif
void 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 res
std::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 = '/';
#endif
void 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 res
std::cout << res.Str() << std::endl;
}
int main() {
// 直接指定模型目录和图片文件路径
std::string model_dir = "./ResNet50_vd";
std::string image_file = "./test.jpeg";
// 设置运行选项
fastdeploy::RuntimeOption option;
// 根据需要选择CPU或GPU
option.UseCpu(); // 或者 option.UseGpu(); 来使用GPU
option.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 = '/';
#endif
std::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 string
return res.Str();
}
修改CMFCPaddleClasDlg::ExecutePrediction函数如下:
CString CMFCPaddleClasDlg::ExecutePrediction(const CString& imagePath)
{
// 将CString转换为std::string
CT2CA 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);
// 将结果转换回CString
CString 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]**:
后来,查阅资料,是因为缺少一些东西:
- openvino相关库
- 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 = '/';
#endif
namespace 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_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
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::string
std::string model_dir = std::string(CT2CA(m_selectedFolderPath_Model));
std::string image_file = std::string(CT2CA(imagePath));
// 设置运行选项
fastdeploy::RuntimeOption option;
//option.UseCpu(); // 或者 option.UseGpu(); 来使用GPU
option.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文件内容
依赖环境
包含目录
库目录
依赖项
运行结果
运行软件,输入模型和图像路径,给出结果如下:
大功告成!