C#使用公共语言拓展(CLE)调用Python3(使用TensorFlow训练的模型)

     对于Python2来说,使用IronPython可以方便的实现C#调用Python,但是对于特定需求,比如使用TensorFlow(最低支持Python3.5),就没办法使用IronPython了,为了解决这个问题,一个方法就是使用TensorflowSharp,简单使用可以看我的这篇文章:TensorflowSharp安装和使用入门,或者自行百度。还有一个方法就是用公共语言拓展(CLE),这个在Java上面似乎挺多人使用的,但是C#貌似没有很多相关的信息,官方文档也有使用方法,比较容易使用,不过我还是遇到了一些小问题,干脆直接记录下来。
       首先是安装,根据自己的需要选择地址安装后,(Windows)实际上库文件是在C盘下面的srplab文件夹,而不是选择的安装路径,然后根据自己的.NET版本导入合适的版本,我的是AMD64平台,使用的是.NET Framework4.5.2,因此在项目中导入:

记得将VS编译选择去掉“首选32位”选项,不然无法正确导入。然后使用using Star_csharp完成环境安装。
干脆截取一段我自己的代码做一下说明,代码所创建的类是用来导入TensorFlow训练好的模型做预测:
 

using Star_csharp;

namespace C_Python
{
    class useTF
    {
        //将模型导入和预测分开,这样可以多次调用预测函数
        private StarObjectClass model;
        private StarObjectClass processor;
        private StarCoreFactory starcore;
        private StarServiceClass Service;
        private StarSrvGroupClass SrvGroup;
        private StarObjectClass python;
        private string path;
        private string prediction;
        public useTF(string path)
        {
            this.path = path;
            this.prediction = "";
        }

        public string getPred()
        {
            tryPred();
            return prediction;
        }
        
        public int modelPre(int[][] data)
        {
            //将灰度数组转为python数组然后作为预测值
            python._Call("eval", "input = list()");
            for(int i = 0; i < 64; i++)
            {
                for(int j = 0; j < 64; j++)
                {
                    python._Call("eval", "input.append(" + data[i][j] + ")");
                }
            }
            python._Call("eval", "input = np.array(input)");
            python._Call("eval", "input = input.reshape(1,64,64,1)");
            python._Call("eval", "prediction = pd.test_image(input)");
            //使用强制转换获得数据
            int result = (int)model._Get("num_class");
            int prediction = (int)python._Get("prediction");
            return prediction;
        }

        public void modelImport()
        {
            string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
            path = path.Substring(0, path.LastIndexOf("\\"));
            path = path + "/pythonModel";
            path = path.Replace('\\','/');
            //这里是官方给出的初始化过程
            starcore = StarCoreFactory.GetFactory();
            Service = starcore._InitSimple("test", "123", 0, 0, null);
            SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup");
            //--init python raw interface,我这里用的是python3.6
            SrvGroup._InitRaw("python36", Service);
            python = Service._ImportRawContext("python", "", false, "");
            //个人推荐使用这种写法,看起来比较直观,不容易带给自己误解
            python._Call("eval", "import sys");
            python._Call("eval", "sys.path.append(r'" + path + "')");
            python._Call("eval", "import numpy as np");
            python._Call("eval", "import pred as pd");
            //这里在导入tensorflow模型后获得模块接口,可以使用model._Call("func")
            //相当于python._Call("eval", "pd.func()"),但是前一种方法没法保存返回结果
            model = python._GetObject("pd");
            python._Call("eval", "import operate_data as processor");
            processor = python._GetObject("processor");
        }

        public void modelClose()
        {
            SrvGroup._ClearService();
            starcore._ModuleExit();
        }

        public int imgProcess(string file)
        {
            //将原始图片转换为灰度图片,通过下面的get_img获得结果
            processor._Call("operate_face", file);
            //对于非基本类型没法直接强制转换,比如这里返回的二维数组只能这样一个一个读
            int[][] img = new int[64][];
            for (int i = 0; i < 64; i++)
                img[i] = new int[64];
            for (int i = 0; i < 64; i++)
            {
                for (int j = 0; j < 64; j++)
                    img[i][j] = (int)processor._Call("get_img", i, j);
            }
            //将灰度图片的数据直接作为预测模型的输入
            int result = modelPre(img);
            return result;
        }
    }
}

除此之外,因为我使用了多线程来调用该类的实例,不知道什么原因,如果在主进程中导入模型,在子线程中没法使用某些方法,解决方法:导入模型和方法调用放在同一个子线程下进行。

猜你喜欢

转载自blog.csdn.net/Micusd/article/details/81605593