工具准备:


视觉学习库:opencv、emgucv、dlib

编译工具:visual studio 2017 、CMake

操作系统:Win10 64位

环境配置:


请参考我这篇dlib、opencv的文章 http://www.cnblogs.com/dongzhaosheng/p/8568163.html

跨语言兼容方案:


dlib提供了两种语言一个是C++库 ,另一个是python库(为此我还特意去学了几天python),首先我想到了用python封装,但是结果我失败了听说python是胶水语言实质上它是把其它语言沾到自己身上,要是想把python

融合到其它语言上恐怕你还得下功夫想想怎么才能粘的没有缝。这里提供一个目前C#引用python的方案InronPython,我尝试了用它去调用python里的方法很遗憾现在python都已经3.0了 该容器还是2.x的解决方案,因此

第三方库我根本掉不到也没法封装,因此该方案被我pass了。当然你可以用python来写你自己的项目如果不要是要求即时输出的话可以将数据保存到目录再读回来。

第二种方案就是用C++来封装dll给C#调用毕竟是自己平台的东西所以兼容方面肯定没问题,封装C++方案一共3种:DllImport、利用CLI 编写的C++要符合CLS规范(虽然是C++项目里编写但是用到的几乎没有C++的类型)、

利用Component Object Model (COM组件对象模型)的方式包装这也是windows底层大部分插件的构成方式。

①DllImport 最简单跟调用系统API一样就可以完成封装好的方法,但是缺点是只能是静态方法,难以对内部对象直接进行控制(不好做前期的初始化或者释放)

[DllImport(“user32.dll”,CharSet = CharSet.Unicode)]

public static extern int MessageBox(IntPtr hWnd,String text,String caption,uint type);

②CLI 编写dll 但是要用CLS规范的类型来写,优点是可以做到无缝衔接只要成功编写到C#中就可以像平时操作其它类的方式来操作,但是对于不熟悉C++的C#工程师或者不熟悉面向对象的C++工程师都是一种煎熬,并且对于调用第三方库并不是很友好我经过

多番尝试无法编译后(需要兼容太多写法)只好放弃。

③最后我选择的方案也是CLI,可是微软帮我们提供了一种非常便捷的包装方式,它不需要你搭建非常复杂的接口转换只需要利用ATL向导即可轻松完成一个方法或者对象的建立,然后你只要在继承接口的方法中写实现过程即可,但是你要满足输出输入格式因为com为兼容语言

类型是中间类型(关于C#跟C++ATL的类型转换可自行查阅)。

实现思路:


因为人脸识别与特征识别都不是我实现的,我只是利用dlib机器学习库的现成函数拼凑的功能,但是从C++移植到C#的大致方式我还是要说下因为现在网上还没有看到比较完整的解决方案。首先就是类型转换字符型没什么好说的BSTR在C#里对应的就是string,到了

c++中有现成的转换函数_com_util::ConvertBSTRToString,然后是人脸识别传入的图像数据首先我想到的就是将图像指针直接传入然后到C++中完成图像初始化,经过多方资料查阅后我查到原来C#的emgucv里的图像指针可以直接到C++的opencv里转成需要的Mat类型

因为他们都符合IplImage规范,指针的传递可以用LRESULT来完成C#里看到的是一个long型数据。

关于输出结果很多人倾向于在C++里完成图像操作然后直接将图像返回到C#,但是如果我只想取得人类数据结构呢?我这里使用的可以序列号与反序列化的json,在c++里将得到的人脸模型转成json格式再到C#里反序列化拿到实例即可,C++没有C#那么方便的Json转换工具只有一个rapidjson库(一个台湾同胞写的第三方库)。

rapidjson::Document jsonDoc;

rapidjson::Document::AllocatorType &allocator = jsonDoc.GetAllocator(); //获取分配器

jsonDoc.SetArray();

/

插入数据过程

rapidjson::StringBuffer buffer;

rapidjson::Writerrapidjson::StringBuffer writer(buffer);

jsonDoc.Accept(writer);

std::string strJson = buffer.GetString();

封装好后就可以直接在C#里进行调用了

NaughtyKidATLLib.NaughtyKidDlibClass dlib = new NaughtyKidDlibClass();

//初始化数据文件

var a = dlib.InitialDat($“{System.IO.Directory.GetCurrentDirectory()}\shape_predictor_68_face_landmarks.dat”);

//返回特征点

System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();

Image<Bgr, Byte> img3 = new Image<Bgr, Byte>(System.IO.Directory.GetCurrentDirectory() + “\temp.jpg”);

watch.Start();//开始计时

var b = dlib.GetFaceModel((long)img3.Ptr);

var models = NaughtyKid.MyTools.SerializationHelper.ScriptDeserialize<List>(b);

更多推荐