欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

手把手教你用c#制作一個小型桌面程序

 更新時間:2024年09月24日 09:39:37   作者:萊茶荼菜  
本文介紹了使用Visual?Studio創(chuàng)建DLL項目,并通過屬性管理器導入工程屬性表的方法,詳細闡述了制作Windows動態(tài)庫的步驟,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

封裝dll

首先使用visual stdio 創(chuàng)建Dll新項目,然后屬性管理器導入自己的工程屬性表(如果沒有可以參考visual stdio 如何配置opencv等其他環(huán)境)

創(chuàng)建完成后 系統(tǒng)會自動生成一些文件,其中 pch.cpp 先不要修改,pch.h中先導入自己需要用到的庫,下面是我的代碼

pch.h

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

現(xiàn)在編寫我們的接口代碼,我封裝的是resnet18的代碼:
首先添加源文件ResNetDll.cpp:

ResNetDll.cpp

#include "pch.h"
#include "ResNetDll.h"

// 全局變量,用于存儲模型路徑和圖像路徑
static std::string g_imagePath;
static std::string g_modelPath;

// 圖像預處理函數(shù)
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 轉(zhuǎn)換到 RGB
    cv::Mat rgbImage;
    cv::cvtColor(normalizedImage, rgbImage, cv::COLOR_BGR2RGB);

    return rgbImage;
}

// 推理函數(shù)
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);

        // 創(chuàng)建 blob 并設置為網(wǎng)絡輸入
        cv::Mat blob = cv::dnn::blobFromImage(rgbImage, 1.0, cv::Size(224, 224), cv::Scalar(), true, false);
        net.setInput(blob);

        // 執(zhí)行推理
        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;

        // 根據(jù)預測結(jié)果返回相應的標簽
        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 暴露的函數(shù),用于設置圖像路徑
extern "C" RESNETDLL_API void set_image_path(const char* imagePath) {
    g_imagePath = imagePath;
}

// DLL 暴露的函數(shù),用于設置模型路徑
extern "C" RESNETDLL_API void set_model_path(const char* modelPath) {
    g_modelPath = modelPath;
}

// DLL 暴露的函數(shù),運行推理
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)
#endif

extern "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動態(tài)庫

制作Demo

創(chuàng)建.NET Framework新項目,將之前生成的dll放在Demo文件夾的bin ->debug或是 release中(看你自己用的什么模式),
新建NativeMethods.cs 這個文件用于 導入 dll中的接口函數(shù)或類
我的代碼如下

NativeMethods.cs

using System;
using System.Runtime.InteropServices;

namespace ResNetApp
{
    public static class NativeMethods
    {
        // 導入 DLL 中的 set_image_path 函數(shù)
        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void set_image_path(string imagePath);

        // 導入 DLL 中的 set_model_path 函數(shù)
        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void set_model_path(string modelPath);

        // 導入 DLL 中的 run_resnet 函數(shù)
        [DllImport("ResNetDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr run_resnet();
    }
}

然后在窗口中拉入你想要的控件,這是我的窗口布局

布局完了之后會自動生成Form1.Designer.cs 的窗口設計代碼,點擊控件按F4 還可以修改他們的屬性

Form1.cs

這個代碼 編寫你想要每個控件實現(xiàn)的功能:

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);

                // 調(diào)用 DLL 執(zhí)行推理
                IntPtr resultPtr = NativeMethods.run_resnet();

                // 將返回的指針轉(zhuǎn)換為字符串
                string result = Marshal.PtrToStringAnsi(resultPtr);

                // 顯示結(jié)果
                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中出現(xiàn)的你的.exe文件咯,是不是很簡單呀~[狗頭]

總結(jié)

到此這篇關于用c#制作一個小型桌面程序的文章就介紹到這了,更多相關c#制作小型桌面程序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C#基于時間輪調(diào)度實現(xiàn)延遲任務詳解

    C#基于時間輪調(diào)度實現(xiàn)延遲任務詳解

    在很多.net開發(fā)體系中開發(fā)者在面對調(diào)度作業(yè)需求的時候一般會選擇三方開源成熟的作業(yè)調(diào)度框架來滿足業(yè)務需求,但是有些時候可能我們只是需要一個簡易的延遲任務。本文主要分享一個簡易的基于時間輪調(diào)度的延遲任務實現(xiàn),需要的可以參考一下
    2022-12-12
  • 詳細了解C# 枚舉與位枚舉

    詳細了解C# 枚舉與位枚舉

    這篇文章主要介紹了C# 枚舉與位枚舉的相關資料,文中講解非常細致,幫助大家更好的理解和學習枚舉和位枚舉,感興趣的朋友可以了解下
    2020-07-07
  • c# 播放聲音的四種方法

    c# 播放聲音的四種方法

    這篇文章主要介紹了c# 播放聲音的四種方法,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-11-11
  • C#使用linq計算執(zhí)行元素在列表中出現(xiàn)次數(shù)的方法

    C#使用linq計算執(zhí)行元素在列表中出現(xiàn)次數(shù)的方法

    這篇文章主要介紹了C#使用linq計算執(zhí)行元素在列表中出現(xiàn)次數(shù)的方法,涉及C#使用linq擴展進行列表查詢的技巧,需要的朋友可以參考下
    2015-04-04
  • C#調(diào)用和實現(xiàn)WebService,純手工打造!

    C#調(diào)用和實現(xiàn)WebService,純手工打造!

    C#調(diào)用和實現(xiàn)WebService,純手工打造! 需要的朋友可以參考一下
    2013-02-02
  • C#實現(xiàn)MP3播放器功能的示例代碼

    C#實現(xiàn)MP3播放器功能的示例代碼

    這篇文章主要為大家詳細介紹了如何利用C#實現(xiàn)MP3播放器功能,文中的示例代碼講解詳細,對我們學習C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • Unity3D利用DoTween實現(xiàn)卡牌翻轉(zhuǎn)效果

    Unity3D利用DoTween實現(xiàn)卡牌翻轉(zhuǎn)效果

    這篇文章主要為大家詳細介紹了Unity3D利用DoTween實現(xiàn)卡牌翻轉(zhuǎn)效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • 在C#中處理時間戳和時區(qū)的解決方法

    在C#中處理時間戳和時區(qū)的解決方法

    處理時間戳和不同的時區(qū)可能是軟件開發(fā)中的一個棘手問題,尤其是當系統(tǒng)不確定給定的日期時間是UTC還是本地時間時,通常會遇到與時間轉(zhuǎn)換相關的問題,在這篇文章中,我將分享我們?nèi)绾卧贑#中處理時間戳和時區(qū),需要的朋友可以參考下
    2024-06-06
  • C#獲取硬盤編號的方法

    C#獲取硬盤編號的方法

    這篇文章主要介紹了C#獲取硬盤編號的方法,涉及C#獲取硬件屬性的相關技巧,非常簡單實用,需要的朋友可以參考下
    2015-05-05
  • c#?使用線程對串口serialPort進行收發(fā)數(shù)據(jù)(四種)

    c#?使用線程對串口serialPort進行收發(fā)數(shù)據(jù)(四種)

    本文主要介紹了c#?使用線程對串口serialPort進行收發(fā)數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07

最新評論