当前位置:首页 » 《关于电脑》 » 正文

使用c#制作一个小型桌面程序

15 人参与  2024年10月21日 10:01  分类 : 《关于电脑》  评论

点击全文阅读


封装dll

首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表(如果没有可以参考visual stdio 如何配置opencv等其他环境)

创建完成后 系统会自动生成一些文件,其中 pch.cpp 先不要修改,pch.h中先导入自己需要用到的库,下面是我的代码

pch.h

#pragma once#include <opencv2/opencv.hpp>#include <opencv2/dnn.hpp>#include <iostream>#include <string>

现在编写我们的接口代码,我封装的是resnet18的代码:
首先添加源文件ResNetDll.cpp:

ResNetDll.cpp

#include "pch.h"#include "ResNetDll.h"// 全局变量,用于存储模型路径和图像路径static std::string g_imagePath;static std::string g_modelPath;// 图像预处理函数cv::Mat transformImage(const std::string& imagePath) {    cv::Mat image = cv::imread(imagePath);    if (image.empty()) {        throw std::runtime_error("Failed to load image.");    }    cv::Mat resizedImage;    cv::resize(image, resizedImage, cv::Size(224, 224));    cv::Mat floatImage;    resizedImage.convertTo(floatImage, CV_32F, 1.0 / 255.0);    cv::Mat normalizedImage;    cv::Scalar mean(0.485, 0.456, 0.406);    cv::Scalar stdDev(0.229, 0.224, 0.225);    cv::subtract(floatImage, mean, normalizedImage);    cv::divide(normalizedImage, stdDev, normalizedImage);    // 从 BGR 转换到 RGB    cv::Mat rgbImage;    cv::cvtColor(normalizedImage, rgbImage, cv::COLOR_BGR2RGB);    return rgbImage;}// 推理函数const char* run_inference() {    static std::string result;    try {        // 加载 ONNX 模型        cv::dnn::Net net = cv::dnn::readNetFromONNX(g_modelPath);        if (net.empty()) {            result = "Failed to load the model.";            return result.c_str();        }        // 预处理图像        cv::Mat rgbImage = transformImage(g_imagePath);        // 创建 blob 并设置为网络输入        cv::Mat blob = cv::dnn::blobFromImage(rgbImage, 1.0, cv::Size(224, 224), cv::Scalar(), true, false);        net.setInput(blob);        // 执行推理        cv::Mat output = net.forward();        // 处理输出        cv::Mat prob = output.reshape(1, 1);  // 变换成 1D 张量        cv::Point classIdPoint;        double confidence;        // 用来找到矩阵或图像中元素的最小值和最大值,以及它们所在的位置        cv::minMaxLoc(prob, 0, &confidence, 0, &classIdPoint);        int classId = classIdPoint.x;        // 根据预测结果返回相应的标签        result = "Predicted Class ID: " + std::to_string(classId) + " with confidence: " + std::to_string(confidence);        return result.c_str();    }    catch (const std::exception& e) {        result = "Error occurred during inference: " + std::string(e.what());        return result.c_str();    }}// DLL 暴露的函数,用于设置图像路径extern "C" RESNETDLL_API void set_image_path(const char* imagePath) {    g_imagePath = imagePath;}// DLL 暴露的函数,用于设置模型路径extern "C" RESNETDLL_API void set_model_path(const char* modelPath) {    g_modelPath = modelPath;}// DLL 暴露的函数,运行推理extern "C" RESNETDLL_API const char* run_resnet() {    return run_inference();}

ResNetDll.h:

#pragma once#ifdef RESNETDLL_EXPORTS#define RESNETDLL_API __declspec(dllexport)#else#define RESNETDLL_API __declspec(dllimport)#endifextern "C" {    // 设置图像路径    RESNETDLL_API void set_image_path(const char* imagePath);    // 设置模型路径    RESNETDLL_API void set_model_path(const char* modelPath);    // 运行推理    RESNETDLL_API const char* run_resnet();}

点击生成dll,就封装成了windows动态库

制作Demo

创建.NET Framework新项目,将之前生成的dll放在Demo文件夹的bin ->debug或是 release中(看你自己用的什么模式),
新建NativeMethods.cs 这个文件用于 导入 dll中的接口函数或类
我的代码如下

NativeMethods.cs

using System;using System.Runtime.InteropServices;namespace ResNetApp{    public static class NativeMethods    {        // 导入 DLL 中的 set_image_path 函数        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]        public static extern void set_image_path(string imagePath);        // 导入 DLL 中的 set_model_path 函数        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]        public static extern void set_model_path(string modelPath);        // 导入 DLL 中的 run_resnet 函数        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]        public static extern IntPtr run_resnet();    }}

然后在窗口中拉入你想要的控件,这是我的窗口布局
在这里插入图片描述
布局完了之后会自动生成Form1.Designer.cs 的窗口设计代码,点击控件按F4 还可以修改他们的属性

Form1.cs

这个代码 编写你想要每个控件实现的功能:

using System;using System.ComponentModel;using System.Runtime.InteropServices;using System.Windows.Forms;namespace ResNetApp{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void buttonSelectImage_Click(object sender, EventArgs e)        {            OpenFileDialog openFileDialog = new OpenFileDialog();            openFileDialog.Filter = "图像文件|*.bmp;*.jpg;*.jpeg;*.png";            if (openFileDialog.ShowDialog() == DialogResult.OK)            {                textBoxImagePath.Text = openFileDialog.FileName; // 显示选择的图像路径            }        }        private void buttonSelectModel_Click(object sender, EventArgs e)        {            OpenFileDialog openFileDialog = new OpenFileDialog();            openFileDialog.Filter = "ONNX 模型文件|*.onnx";            if (openFileDialog.ShowDialog() == DialogResult.OK)            {                textBoxModelPath.Text = openFileDialog.FileName; // 显示选择的模型路径            }        }        private void button1_Click(object sender, EventArgs e)        {            try            {                string imagePath = textBoxImagePath.Text;                string modelPath = textBoxModelPath.Text;                if (string.IsNullOrEmpty(imagePath) || string.IsNullOrEmpty(modelPath))                {                    textBox1.Text = "请选择图像和模型路径。";                    return;                }                textBox1.Text = "开始运行 ResNet ...";                // 设置图像路径和模型路径                NativeMethods.set_image_path(imagePath);                NativeMethods.set_model_path(modelPath);                // 调用 DLL 执行推理                IntPtr resultPtr = NativeMethods.run_resnet();                // 将返回的指针转换为字符串                string result = Marshal.PtrToStringAnsi(resultPtr);                // 显示结果                textBox1.Text = result;            }            catch (Exception ex)            {                textBox1.Text = "错误: " + ex.Message;            }        }           }}

Program.cs

我们还需要一个入口主程序

using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace ResNetApp{    static class Program    {        /// <summary>        /// 应用程序的主入口点。        /// </summary>        [STAThread]        static void Main()        {            Application.EnableVisualStyles();            Application.SetCompatibleTextRenderingDefault(false);            Application.Run(new Form1());        }    }}

完成之后点击生成 就可以在bin中出现的你的.exe文件咯,是不是很简单呀~[狗头]


点击全文阅读


本文链接:http://zhangshiyu.com/post/174796.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1