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

封装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 转换到 RGBcv::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://www.rhkb.cn/news/423892.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unet改进31:添加Star_Block(2024最新改进方法)|紧凑的网络结构和高效的运算

本文内容:在不同位置添加Star_Block 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 最近的研究引起了人们对网络设计中尚未开发的“星型操作”(元素智能乘法)潜力的关注。虽然有很多直观的解释,但其应用背后的基本原理在很大程度上仍未被探索。我们的研…

旅游网站设计与实现:SpringBoot技术手册

第三章 系统分析 开发一个系统首先要对系统进行分析&#xff0c;是开发者针对系统实际客户对软件应用的一个调查访问和研究&#xff0c;弄清用户对软件需求的具体要求&#xff0c;同时开发者还要对系统开发的经济和可技术上是否可行进行分析&#xff0c;并确定系统开发的成本和…

OZON电子产品大幅增长,OZON跨境PS5销量激增

Top1 存储卡 Карта памяти Canvas Select Plus 128 ГБ 商品id&#xff1a;1548303593 月销量&#xff1a;2131 欢迎各位卖家朋友点击这里&#xff1a; &#x1f449; D。DDqbt。COm/74rD 免费体验 随着智能手机和平板电脑的普及&#xff0c;用户对于存储空…

C++笔记---继承(上)

1. 继承的简单介绍 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增加方法(成员函数)和属性(成员变量)&#xff0c;这样产生新的类&#xff0c;称派生类。 继承呈…

使用LDAP登录GitLab

使用LDAP登录GitLab gitlab.rb 配置如下 gitlab_rails[ldap_enabled] true #gitlab_rails[prevent_ldap_sign_in] false###! **remember to close this block with EOS below** gitlab_rails[ldap_servers] YAML.load <<-EOSmain:label: LDAPhost: 172.16.10.180port:…

python环境安装

一、下载开发IDE https://www.jetbrains.com/pycharm/download/?sectionwindows 下载:conda Download Now | Anaconda 重新打开PyCharm Community Edition 2024.2.1 新建项目&#xff1a;pythonProject1 编写python 文件时没有提示&#xff1a;错误:未选择 Python 解释器。请…

云轴科技ZStack 获鲲鹏应用创新大赛2024上海赛区决赛一等奖

9月13日&#xff0c;鲲鹏应用创新大赛2024上海赛区决赛成功举办。经评委专家从方案创新性、技术领先性、商业前景以及社会价值四个维度严格评审&#xff0c;云轴科技ZStack参赛作品《ZStack鲲鹏原生开发方案》荣获上海赛区企业赛——原生开发赛道&#xff08;互联网&#xff09…

线程 - 线程的由来、进程和线程的关系、进程创建_等待_退出详解

文章目录 一、线程概念1. 线程的出现2. linux 对线程的设计3. 线程二、进程和线程1. 进程和线程的关系2. 进程的调度3. 轻量级进程三、pthread库1. pthread 库的作用2. 手动链接 pthread库四、创建线程1. pthread_create()2. 函数的使用3. 线程和函数五、线程等待1. 新线程的运…

ROADM(可重构光分插复用器)-介绍

1. 引用 https://zhuanlan.zhihu.com/p/163369296 https://zhuanlan.zhihu.com/p/521352954 https://zhuanlan.zhihu.com/p/91103069 https://zhuanlan.zhihu.com/p/50610236 术语&#xff1a; 英文缩写描述灰光模块彩光模块CWDM&#xff1a;Coarse Wave-Length Division …

WireShark分析localhost包

文章目录 需要npcap。 java 需要配置Npcap&#xff0c;如果没有需要卸载重新安装 Npcap 是专为 Windows 开发的一款网络抓包 SDK&#xff0c;该 SDK 提供了被应用程序调用的库文件和系统驱动程序。通过 Npcap&#xff0c;我们可以得到原始&#xff08;raw&#xff09;网络数据&…

Java手写RPC框架-01-开篇

项目背景 随着业务不断升级&#xff0c;系统规模不断扩大&#xff0c; 单体架构会产生越来越多的问题&#xff0c;需要引入微服务将原先架构解耦为一个个模块。每个服务模块放在不同的服务器上&#xff0c;能够保证系统在高并发环境下的正常运转。 各个服务模块之间如何相互调…

OpenHarmony(鸿蒙南向开发)——轻量系统STM32F407芯片移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量和小型系统三方库移植指南…

【getshell】phpmyadmin后台getshell(4.8.5)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【getshell】phpmyadmin后台getshell&#xff08;4.8.5&#xff09; 一、进入sql命令输入界面二、上传代码三、getshell 一、进入…

Kubernetes (k8s)v1.27.1版本安装步骤

这 一、k8s 安装步骤1.1 安装docker及containerd容器1.2、设置每台服务器的参数1.3、安装kubelet、kubeadm、kubectl1.4、修改 kubelet 的 cgroup 和 docker 的 cgroup-driver 保持一致1.5、使用containerd 默认容器的配置1.6、使用kubeadm进行初始化1.7、初始化成功1.8、集群部…

海外云手机有哪些推荐?

随着云手机的发展&#xff0c;越来越多的企业和个人开始使用云手机来满足他们的海外业务需求。用户可以通过云手机实现方便、快捷的海外访问&#xff0c;一般用来进行tiktok运营、亚马逊电商运营、海外社媒运营等操作。海外云手机平台有很多&#xff0c;以下是一些比较好的云手…

✨机器学习笔记(四)—— 逻辑回归、决策边界、过拟合、正则化

Course1-Week3: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Supervised%20Machine%20Learning%20Regression%20and%20Classification/week3机器学习笔记&#xff08;四&#xff09; 1️⃣逻辑回归&#xff08;logistic regression&#xff09;…

Java的衍生生态有哪些?恐怖如斯的JAVA

Java的衍生生态极其丰富&#xff0c;涵盖了多个层面和领域。以下是Java衍生生态的一些主要方面&#xff1a; 1. 开源工具 开发工具&#xff1a;如Eclipse&#xff0c;这是一款非常优秀的Java IDE工具&#xff0c;支持Java以及其他语言的代码编写。Spring官方还基于Eclipse开发…

Excel单元格操作:读写单元格数据、格式设置与条件格式详解

目录 一、Excel单元格的基本操作 1.1 单元格的选取与编辑 案例一&#xff1a;基本数据录入 1.2 单元格的读取与写入 案例二&#xff1a;使用公式计算销售额 二、单元格格式设置 2.1 字体与颜色设置 案例三&#xff1a;设置标题格式 2.2 数字格式设置 案例四&#xff…

树形弹窗选择框/vue2/Element/弹框选择

前言 此类选择器根据vueelementUI实现&#xff0c;使用vue3的可以根据此案例稍作改动即可实现&#xff0c;主要功能有弹出选择、搜索过滤、搜索结果高亮等&#xff0c;此选择器只支持单选&#xff0c;如需多选可在此基础进行改造。 效果图 代码实现 使用时&#xff0c;props-…

【C++ Primer Plus习题】15.1

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream> #include "tv.h" us…