C#(winform)调用pytorch模型

winform调用pytorch上训练好的unet模型:

项目是写一个辅助诊断系统软件,用winform写软件,调用pytorch和matlab的模型。这篇博客只包含调用pytorch模型的部分。

1.c++(libtorch)调用模型
2.c++生成动态链接库
3.c#调用dll

1. libtorch(cpu)调用gpu模型

首先把pytorch的模型转成libtorch的。如果模型没有控制流(if-else语句),就用简单的trace方式进行转换。

pth文件转为pt文件

import torch
import torchvision
import numpy as np
import cv2
import os
from unet_parts import UNet

device = torch.device('cpu')
model = UNet(1,1)
#服务器gpu训练模型,导成cpu模型
model.load_state_dict(torch.load("best_model.pth", map_location='cpu'))
model.eval()
traced_script_module = torch.jit.trace(model)
traced_script_module.save("best_model.pt")

VS2019部署libtorch+opencv

下载libtorch、opencv
配置项目属性
右键项目,配置属性。VC++目录添加包含目录、库目录:

包含目录
D:\Tools\libtorch\include\torch\csrc\api\include
D:\Tools\libtorch\include
D:\Tools\opencv\build\include\opencv2
D:\Tools\opencv\build\include

库目录
D:\Tools\libtorch\lib
D:\Tools\opencv\build\x64\vc15\lib

添加链接器->输入->附加依赖项,把libtorch、opencv库目录下的所有.lib文件全都复制过来。

asmjit.lib
c10.lib
caffe2_detectron_ops.lib
caffe2_module_test_dynamic.lib
Caffe2_perfkernels_avx.lib
Caffe2_perfkernels_avx2.lib
Caffe2_perfkernels_avx512.lib
clog.lib
cpuinfo.lib
dnnl.lib
fbgemm.lib
fbjni.lib
kineto.lib
XNNPACK.lib
torch_cpu.lib
torch.lib
pytorch_jni.lib
libprotoc.lib
opencv_world455.lib

项目是release版本就调用release版本的dll:opencv_xxxx.lib,debug版本opencv_xxxd.lib,注意区别。

最后跑一下模型验证效果

2.c++生成动态链接库

创建项目:Windows桌面向导
选择应用类型:DLL
选择预编译头文件。其余配置同上

#include "pch.h"
#include<iostream>
#include <torch/torch.h>
#include <torch/script.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace cv;
using namespace std;

void __stdcall LoadModel(char* file_name) //接口传入图片地址
{
	torch::jit::script::Module module;
	module = torch::jit::load("E:/Project/octa/pytorch/best_model.pt");
	module.eval();
	torch::Device device(torch::kCPU);
	module.to(device);

	Mat image = imread(file_name);
	cvtColor(image, image, CV_BGR2GRAY);
	resize(image, image, Size(256, 256));

	//Mat to Tensor, add one dimension
	torch::Tensor tensor_image = torch::from_blob(image.data, { image.rows, image.cols,image.channels() }, torch::kByte);
	//-> 1*1*256*256
	tensor_image = tensor_image.permute({ 2,0,1 });

	//preprocessing
	tensor_image = tensor_image.toType(torch::kFloat);
	//tensor_image = tensor_image.div(255);    //normalization
	tensor_image = tensor_image.unsqueeze(0);
	tensor_image.to(device);

	torch::Tensor output = module.forward({ tensor_image }).toTensor();
	torch::Tensor output_max = output.squeeze();
	//cout << output_max[0][0][0];

	//tensor to Mat
	output_max = (output_max >= 0.5);
	output_max = output_max.mul(255).clamp(0, 255).to(torch::kU8);
	output_max = output_max.to(torch::kCPU);
	Mat result_img(Size(256, 256), CV_8UC1);  //8 bit 1 channel, 256 colors
	memcpy((void*)result_img.data, output_max.data_ptr(), sizeof(torch::kU8) * output_max.numel());

	//imshow("result", result_img);
	vector<int> compression_params;
	compression_params.push_back(IMWRITE_PNG_COMPRESSION);
	compression_params.push_back(0);    // 无压缩png.
	compression_params.push_back(IMWRITE_PNG_STRATEGY);
	compression_params.push_back(IMWRITE_PNG_STRATEGY_DEFAULT);
	imwrite("test.png", result_img, compression_params);
	//waitKey(0);
	return;
}

头文件

#pragma once
//定义宏
#ifdef UNET_DLL
#define UNET_DLL __declspec(dllexport)
#else
#define UNET_DLL __declspec(dllimport)
#endif 

extern "C" UNET_DLL void __stdcall LoadModel(char* file_name);
//extern "C" 避免编码问题改变函数名,导致找不到入口函数

注意!!不用提供的模板pch.h,pch.cpp时,进行如下操作:
右键项目 --> 属性 --> C/C++ --> 预编译头 -->预编译头 改为创建

3. winform调用dll

把libtorch中所有dll、刚刚生成的dll文件放到项目文件夹的bin目录下。创建Windows窗体应用程序。

using System.Runtime.InteropServices;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        //静态调用dll
        [DllImport(@"E:\vs\winform_test\WindowsFormsApp1\bin\octa.dll", EntryPoint = "LoadModel", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi, ExactSpelling = false)]
        public static extern void LoadModel(string s);
        
        private void analyzeButton_Click(object sender, EventArgs e)
        {
            LoadModel("E:/Project/octa/dataset/test/0.png");
            string ss = openFileDialog1.FileName;
            if(!string.IsNullOrEmpty(ss))
            {
                LoadModel(ss);
                MessageBox.Show("Region segmentation succeeded!");
            } 
        }
    }
}

  • 2
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
你可以使用C#WinForms来调用摄像头。首先,确保你的计算机上已经安装了摄像头设备,并且已经安装了适当的驱动程序。 接下来,你可以使用`System.Windows.Forms`命名空间中的`PictureBox`和`VideoCapture`类来实现这个功能。下面是一个简单的示例代码: ```csharp using System; using System.Windows.Forms; using Emgu.CV; using Emgu.CV.Structure; namespace CameraCapture { public partial class MainForm : Form { private VideoCapture capture; public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { // 初始化摄像头 capture = new VideoCapture(); // 设置图像控件作为视频捕获窗口 capture.ImageGrabbed += Capture_ImageGrabbed; // 开始捕获 capture.Start(); } private void Capture_ImageGrabbed(object sender, EventArgs e) { // 获取当前帧图像 Mat frame = new Mat(); capture.Retrieve(frame); // 在PictureBox中显示图像 pictureBox.Image = frame.ToBitmap(); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { // 停止捕获并释放资源 capture.Stop(); capture.Dispose(); } } } ``` 在这个示例中,我们创建了一个`MainForm`类,继承自`Form`,并在窗体的加载事件中初始化了摄像头,并将当前帧图像显示在一个名为`pictureBox`的`PictureBox`控件中。在窗体关闭事件中停止捕获并释放资源。 请注意,上述示例使用了Emgu.CV库来实现摄像头调用。你可以使用NuGet包管理器来安装Emgu.CV库,并在代码中引用它。 希望这个简单的示例能帮助你开始使用C# WinForms调用摄像头!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值