最近在研究人脸识别,打算用PCA(主原分析)对图像数据进行降维后用神经网络训练的方法实现,在网上找了一下PCA的C++算法,发现很难用,而且速度奇慢,后来知道opencv上有实现PCA算法的函数,于是下载了一个2.0版,发现原来已经不支持VC6了,由于之前的代码都是在VC6下实现的,现在要移植也不太可能,无奈之下,用了1.0,但是却不知为什么只要维数大于数据量时就出错,真的要放弃?最后就孤注一掷,在VS2008下作一个封装2.0版下PCA类相关函数的库,再在VC6上链接。
首先做成了静态库,居然链接不成功,看来VC6与VS2008的静态库还是不兼容,我想如果做动态库链接时应该还是会有这个问题啊,就想放弃了,不过经过高人指点,可以直接用LoadLibrary的方法调用动态库的函数啊。好,这个方法可以完全避开编译器和链接器,是最后的机会了。
首先声明一个struct
struct PCA
{void* pca;}
这个pca就是指向opencv2.0中PCA对象的指针。
接着声明创建和释放该对象的函数。
最后再声明其它PCA类方法的函数,如Project。
extern "C" void Project(PCA* pca, float* vec, int veclen, float*& res, int reslen);
这里记着最好要加上extern "C",好让编译器用C函数的方法对该函数进行编译,这样在dll库的函数名就会是Project,否则用C++编译的就会显示加上参数的一串很长的函数名,这时就需要VC6的一个工具Depends打开dll文件才能看到正确的函数名。
在VS2008下写好了动态库,就要在VC6下调用了,这个网上就有很多资料了,大概步骤如下:
// 声明这个函数指针
typedef bool (__cdecl *ProjectPtr)(CPCA*, const data_t*, int, data_t*&, int);
// 加载这个动态库
HMODULE hModule = LoadLibrary("pcalib.dll");
// 取得这个函数的地址
ProjectPtr projectPtr = (ProjectPtr)GetProcAddress(hModule, "Project");
// 创建对象
PCA* pca = (createPCAPtr)(orl_input, TrainNum, InputUnits, MaxComponents);
// 调用这个函数
(projectPtr)(pca, orl_input[i], InputUnits, train_input[i], MaxComponents);
该方法的确行,而且opencv中的PCA算法速度超快,opevcv果然强大,里面还有很多矩阵运算等算法,一点也不比Matlab差。