[WPF]C#调用C++代码(通过C++/CLI)
阅读原文时间:2023年07月10日阅读:3

通过使用C++ + Opencv 编写算法,然后用WPF(C#)编写程序界面,实现交互

可以参考MSDN文档:https://docs.microsoft.com/en-us/cpp/windows/pin-ptr-cpp-cli?view=vs-2017

CLR部分:

CLRLibrary.h文件

#pragma once

using namespace System;
using namespace System::Collections::Generic;
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
namespace CLRLibrary {

    public ref class Class1
    {
    public:
        List<Byte>^ ErodeImage(System::String^ filename);
        int Rows;
        int Cols;

    };
}

CLRLibrary.cpp文件

#include "stdafx.h"
using namespace System;
using namespace System::Runtime::InteropServices;
#include "CLRLibrary.h"
#include "H:\CPP\WPF_CPPCLI_Demo\ConsoleLibrary\ErodeClass.h"
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
Mat ErodeAction(const char* filename)
{
    Mat img = imread(filename);
    Mat out;
    //获取自定义核
    Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的
    //膨胀操作
    dilate(img, out, element);

    return out;
}
//Erode The Image Func
List<Byte>^ CLRLibrary::Class1::ErodeImage(System::String ^ filename)
{
    //将String^转换成const char*
    IntPtr ip = Marshal::StringToHGlobalAnsi(filename);
    const char* str = static_cast<const char*>(ip.ToPointer());
    Mat result=ErodeAction(str);
    List<Byte>^ ret=gcnew List<Byte>();
    for (int i = 0; i < result.rows; i++)
    {
        for (int j = 0; j < result.cols; j++)
        {
            //RBG
            ret->Add(result.at<Vec3b>(i, j)[0]);
            ret->Add(result.at<Vec3b>(i, j)[1]);
            ret->Add(result.at<Vec3b>(i, j)[2]);
        }
    }
    Rows = result.rows;
    Cols = result.cols;

    return ret;
}

WPF部分:

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Loaded="MainWindow_OnLoaded">
    <Grid>
        <Image Name="Box"></Image>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CLRLibrary;
using Color = System.Drawing.Color;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 将BitMap转换成ImageSource
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static ImageSource ChangeBitmapToImageSource(Bitmap bitmap)
        {
            //Bitmap bitmap = icon.ToBitmap(); &nbsp;
            IntPtr hBitmap = bitmap.GetHbitmap();

            ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            return wpfBitmap;
        }

        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            var drawClass=new Class1();

            List<byte> RGBData=drawClass.ErodeImage("D:/Background/1.jpg");

            Bitmap map = new Bitmap(drawClass.Cols, drawClass.Rows);
            int temp = 0;
            for (int i = 0; i < drawClass.Rows; i++)
            {
                for (int j = 0; j < drawClass.Cols; j++)
                {
                    var color = Color.FromArgb(RGBData[temp], RGBData[temp + 1], RGBData[temp + 2]);
                    temp += 3;
                    map.SetPixel(j, i, color);
                }
            }
            Box.Source = ChangeBitmapToImageSource(map);
        }

    }
}

项目所有代码全在上面,如果有需要源码的或者需要交流的可以加我QQ或者微信。

关于更多的C++/CLI代码可以参考我上面给的MSDN文档链接,基本用得到的语法都能从上面找到。