对于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;
}
}
}
除此之外,因为我使用了多线程来调用该类的实例,不知道什么原因,如果在主进程中导入模型,在子线程中没法使用某些方法,解决方法:导入模型和方法调用放在同一个子线程下进行。
补充一个问题:在使用tensorFlow做预测的时候发现一个严重的问题,对于导入的模型,在正常的python项目下,对第一批输入数据做预测的时候,一般会比较慢,但是后面预测速度会很快(不知道是不是因为python的缓冲机制),但是在使用CLE的时候无论第几次预测,速度都和第一次是一样的,对时间有要求的可能需要自行寻找一下解决方案,最好也能告诉我怎么解决的,先谢谢啦~