using OpenCVForUnity.CoreModule; using OpenCVForUnity.UtilsModule; using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace OpenCVForUnity.FaceModule { // C++: class MACE /** * Minimum Average Correlation Energy Filter * useful for authentication with (cancellable) biometrical features. * (does not need many positives to train (10-50), and no negatives at all, also robust to noise/salting) * * see also: CITE: Savvides04 * * this implementation is largely based on: https://code.google.com/archive/p/pam-face-authentication (GSOC 2009) * * use it like: * * * Ptr<face::MACE> mace = face::MACE::create(64); * * vector<Mat> pos_images = ... * mace->train(pos_images); * * Mat query = ... * bool same = mace->same(query); * * * * you can also use two-factor authentication, with an additional passphrase: * * * String owners_passphrase = "ilikehotdogs"; * Ptr<face::MACE> mace = face::MACE::create(64); * mace->salt(owners_passphrase); * vector<Mat> pos_images = ... * mace->train(pos_images); * * // now, users have to give a valid passphrase, along with the image: * Mat query = ... * cout << "enter passphrase: "; * string pass; * getline(cin, pass); * mace->salt(pass); * bool same = mace->same(query); * * * save/load your model: * * Ptr<face::MACE> mace = face::MACE::create(64); * mace->train(pos_images); * mace->save("my_mace.xml"); * * // later: * Ptr<MACE> reloaded = MACE::load("my_mace.xml"); * reloaded->same(some_image); * */ public class MACE : Algorithm { protected override void Dispose(bool disposing) { try { if (disposing) { } if (IsEnabledDispose) { if (nativeObj != IntPtr.Zero) face_MACE_delete(nativeObj); nativeObj = IntPtr.Zero; } } finally { base.Dispose(disposing); } } protected internal MACE(IntPtr addr) : base(addr) { } // internal usage only public static new MACE __fromPtr__(IntPtr addr) { return new MACE(addr); } // // C++: void cv::face::MACE::salt(String passphrase) // /** * optionally encrypt images with random convolution * param passphrase a crc64 random seed will get generated from this */ public void salt(string passphrase) { ThrowIfDisposed(); face_MACE_salt_10(nativeObj, passphrase); } // // C++: void cv::face::MACE::train(vector_Mat images) // /** * train it on positive features * compute the mace filter: {code h = D(-1) * X * (X(+) * D(-1) * X)(-1) * C} * also calculate a minimal threshold for this class, the smallest self-similarity from the train images * param images a vector<Mat> with the train images */ public void train(List images) { ThrowIfDisposed(); Mat images_mat = Converters.vector_Mat_to_Mat(images); face_MACE_train_10(nativeObj, images_mat.nativeObj); } // // C++: bool cv::face::MACE::same(Mat query) // /** * correlate query img and threshold to min class value * param query a Mat with query image * return automatically generated */ public bool same(Mat query) { ThrowIfDisposed(); if (query != null) query.ThrowIfDisposed(); return face_MACE_same_10(nativeObj, query.nativeObj); } // // C++: static Ptr_MACE cv::face::MACE::load(String filename, String objname = String()) // /** * constructor * param filename build a new MACE instance from a pre-serialized FileStorage * param objname (optional) top-level node in the FileStorage * return automatically generated */ public static MACE load(string filename, string objname) { return MACE.__fromPtr__(DisposableObject.ThrowIfNullIntPtr(face_MACE_load_10(filename, objname))); } /** * constructor * param filename build a new MACE instance from a pre-serialized FileStorage * return automatically generated */ public static MACE load(string filename) { return MACE.__fromPtr__(DisposableObject.ThrowIfNullIntPtr(face_MACE_load_11(filename))); } // // C++: static Ptr_MACE cv::face::MACE::create(int IMGSIZE = 64) // /** * constructor * param IMGSIZE images will get resized to this (should be an even number) * return automatically generated */ public static MACE create(int IMGSIZE) { return MACE.__fromPtr__(DisposableObject.ThrowIfNullIntPtr(face_MACE_create_10(IMGSIZE))); } /** * constructor * return automatically generated */ public static MACE create() { return MACE.__fromPtr__(DisposableObject.ThrowIfNullIntPtr(face_MACE_create_11())); } #if (UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR const string LIBNAME = "__Internal"; #else const string LIBNAME = "opencvforunity"; #endif // C++: void cv::face::MACE::salt(String passphrase) [DllImport(LIBNAME)] private static extern void face_MACE_salt_10(IntPtr nativeObj, string passphrase); // C++: void cv::face::MACE::train(vector_Mat images) [DllImport(LIBNAME)] private static extern void face_MACE_train_10(IntPtr nativeObj, IntPtr images_mat_nativeObj); // C++: bool cv::face::MACE::same(Mat query) [DllImport(LIBNAME)] [return: MarshalAs(UnmanagedType.U1)] private static extern bool face_MACE_same_10(IntPtr nativeObj, IntPtr query_nativeObj); // C++: static Ptr_MACE cv::face::MACE::load(String filename, String objname = String()) [DllImport(LIBNAME)] private static extern IntPtr face_MACE_load_10(string filename, string objname); [DllImport(LIBNAME)] private static extern IntPtr face_MACE_load_11(string filename); // C++: static Ptr_MACE cv::face::MACE::create(int IMGSIZE = 64) [DllImport(LIBNAME)] private static extern IntPtr face_MACE_create_10(int IMGSIZE); [DllImport(LIBNAME)] private static extern IntPtr face_MACE_create_11(); // native support for java finalize() [DllImport(LIBNAME)] private static extern void face_MACE_delete(IntPtr nativeObj); } }