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

news2025/1/3 3:26:41

目录

写作目的

环境准备

下载编译环境

解压预编译库

准备训练文件

模型文件

图像文件

路径整理

准备预测代码

创建预测应用

新建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 = '/';
#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]

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

  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 = '/';
#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文件内容
Release文件内容

依赖环境

包含目录

库目录

依赖项

运行结果

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

大功告成!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html+css+js网页设计 美食 美食家6个页面

htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…

【第四期书生大模型实战营基础岛】L1G5000——XTuner 微调个人小助手认知任务

基础任务————使用 XTuner 微调 InternLM2-Chat-7B 实现自己的小助手认知&#xff0c;如下图所示&#xff08;图中的尖米需替换成自己的昵称&#xff09;&#xff0c;记录复现过程并截图。 环境配置与数据准备 步骤 0. 使用 conda 先构建一个 Python-3.10 的虚拟环境 cd …

android知识巩固(二.非线性数据结构)

非线性结构:是从逻辑结构上划分,其元素存在一对多或者多对多的相互关系 1.前言 在前一章中,我们了解了数据结构的基本思想,学习了部分基本的线性数据结构,了解了计算机是如何表示和存储数据的,良好的数据结构思想有助于我们写出性能优良的应用 2.目录 目录.png 3.非线性数据结构…

列车票务信息系统|Java|SSM|JSP|

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、JSP、jquery,html 5⃣️数据库可…

LabVIEW中实现多个Subpanel独立调用同一个VI

在LabVIEW中&#xff0c;如果需要通过多个Subpanel同时调用同一个VI并让这些VI实例独立运行&#xff0c;可以通过以下方法实现&#xff1a; 1. 问题背景 LabVIEW默认的VI是以单实例方式运行的。当将同一个VI加载到多个Subpanel时&#xff0c;会因为共享同一内存空间而导致冲突…

鱼眼相机模型与去畸变实现

1.坐标系说明 鱼眼相机模型涉及到世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换关系。对于分析鱼眼相机模型&#xff0c;假定世界坐标系下的坐标点,经过外参矩阵的变换转到相机坐标系&#xff0c;相机坐标再经过内参转换到像素坐标&#xff0c;具体如下 进一步进…

基于eBPF的微服务网络安全(Cilium 1)

一些开源的kubernetes工具已经开始使用eBPF&#xff0c;这些工具大多数与网络&#xff0c;监控和安全相关。 本文不会涵盖eBPF的方方面面&#xff0c;只作为一个入门指南&#xff0c;包括Linux内核的BPF概念&#xff0c;到将该功能加入到微服务环境的优势&#xff0c;以及当前…

我的JAVA-Web进阶--Maven

1.Maven功能 依赖管理和项目构建 2.Maven仓库 3.Maven项目构建 4.Maven依赖管理 依赖配置 依赖冲突 理解&#xff1a;层级指的是dependency的每一个包的树状图的深度&#xff0c;每一个包都向右延伸一个树状图&#xff0c;层级越深优先级越低&#xff0c;层级越浅&#xff0…

020-spring-整合web

引入web包。通过 ContextLoaderListener 在启动的时候加载spring.xml 加载spring.xml 之后&#xff0c;把dao层等对象放在容器中 <!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.…

Kotlin Multiplatform 新纪元:klibs.io 与鸿蒙支持解锁跨平台开发新潜力

Kotlin Multiplatform 新纪元:klibs.io 与鸿蒙支持解锁跨平台开发新潜力 在软件开发日益多元化的今天,Kotlin Multiplatform(KMP) 正凭借其跨平台代码复用能力迅速成为开发者的首选工具之一。2024年,KMP生态系统的库数量激增了35%,标志着这一领域的强劲增长。然而,随着…

Qt从入门到入土(七)-实现炫酷的登录注册界面(下)

前言 Qt从入门到入土&#xff08;六&#xff09;-实现炫酷的登录注册界面&#xff08;上&#xff09;主要讲了如何使用QSS样式表进行登录注册的界面设计&#xff0c;本篇文章将介绍如何对登录注册界面进行整体控件的布局&#xff0c;界面的切换以及实现登录、记住密码等功能。…

【阅读笔记】《基于区间梯度的联合双边滤波图像纹理去除方法》

一、联合双边滤波背景 联合双边滤波&#xff08;Joint Bilateral Filter, JBF&#xff09;是一种图像处理技术&#xff0c;它在传统的双边滤波&#xff08;Bilateral Filter, BF&#xff09;基础上进行了改进&#xff0c;通过引入一个引导图&#xff08;guidance image&#x…

Dockerfile基础指令

1.FROM 基于基准镜像&#xff08;建议使用官方提供的镜像作为基准镜像&#xff0c;相对安全一些&#xff09; 举例&#xff1a; 制作基准镜像&#xff08;基于centos:lastest&#xff09; FROM cenots 不依赖于任何基准镜像 FROM scratch 依赖于9.0.22版本的tomcat镜像 FROM…

Linux实验报告9-进程管理

目录 一&#xff1a;实验目的 二&#xff1a;实验内容 (1)列出当前系统中的所有进程,如何观察进程的优先级? (2)查看当前终端运行的 bash 进程的 PID,在当前终端启动 vim 编辑器并让其在后台执行,然后列出在当前终端中执行的进程的家族树。 (3)请自行挂载U盘或光盘,然后…

活动预告 |【Part1】Microsoft Azure 在线技术公开课:数据基础知识

课程介绍 参加“Azure 在线技术公开课&#xff1a;数据基础知识”活动&#xff0c;了解有关云环境和数据服务中核心数据库概念的基础知识。通过本次免费的介绍性活动&#xff0c;你将提升在关系数据、非关系数据、大数据和分析方面的技能。 活动时间&#xff1a;01 月 07 日…

笔记本电脑驱动下载并安装

自己的电脑是鸡哥家的&#xff0c;经常出现没有声音、炸麦、麦克风没有音频输入等问题 最快的解决办法就是更新驱动 但是现在市面上好多驱动检测安装软件都已经开始收费了&#xff08;xx人生、xx精灵&#xff09;很恶心 所以不妨自己寻找驱动并重新安装 1.驱动下载 最好是去…

手机实时提取SIM卡打电话的信令声音-双卡手机来电如何获取哪一个卡的来电

手机实时提取SIM卡打电话的信令声音 --双卡手机来电如何获取哪一个卡的来电 一、前言 前面的篇章《手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案》中&#xff0c;我们论述了局域网SIP坐席通过手机外呼出去时&#xff0c;手机中主副卡的呼叫调度策略。 但…

人工智能及深度学习的一些题目(二)

1、【单选题】 不属于语音识别预处理的步骤是哪个&#xff1f; 去重 2、HSV&#xff0c;H是色调&#xff0c;S是饱和度&#xff0c;V是亮度。 3、【填空题】 语音信号预处理中&#xff08; 预加重 &#xff09;的目的是为了对语音的高频部分进行加重&#xff0c;去除口唇辐射的…

关于今天发现的一个bug

一个输入框&#xff0c;定义只能输入0-100的数字 经过测试没有问题。 在回归的时候偶然发现&#xff0c;在输入数字7&#xff0c;点击保存以后&#xff0c;再次打开&#xff0c;发现竟然显示 经过查资料发现&#xff1a; // 关于js失精算法你都遇到哪些&#xff0c;让我们一起来…

力扣-数据结构-7【算法学习day.78】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…