面向对象设计
与人脸检测和人脸识别一样,人脸跟踪也由两部分组成:数据和算法。算法通过预先储存(即离线)的数据来训练模型,然后对新来的(即在线)数据执行某类操作。因此,采用面向对象设计是不错的选择。
在 opencv 2.x 版本中,可方便引入 XML/YAML 文件存储类型,对算法来讲,会大大简化组织离线数据任务。下面通过一个假象类来展示这个功能
-
自定义类 foo
1 // foo.h 2 /* 3 在下面的代码中,定义了一个序列化函数,可对 I/O 函数 read 和 write 实现序列化。 4 FileStorage 类支持两种能被序列化的数据结构类型。 5 为了简单起见,本章所有类将采用映射,其中每个用于存储的变量都会创建一个 FileNode::MAP 类型的 FileNode 对象。 6 这需要分配给变量中的每个元素唯一键。为了保持一致性,将变量名作为标签 7 */ 8 9 #include <opencv2/opencv.hpp> 10 #include <iostream> 11 using namespace cv; 12 using namespace std; 13 14 class foo { 15 public: 16 int a, b; 17 void write(FileStorage &fs) const { // 序列化存储自定义数据类型 18 assert(fs.isOpened()); 19 fs << "{" << "a" << a << "b" << b << "}"; // 创建 FileNode::MAP 类型的对象 20 } 21 void read(const FileNode& node) { // 读取数据 22 assert(node.type() == FileNode::MAP); 23 node["a"] >> a; node["b"] >> b; 24 } 25 };
-
为了使 FileStorage 类的序列化能正常工作,还需要定义write, read函数
1 template<class T> 2 void 3 write(FileStorage& fs, 4 const string&, 5 const T& x) 6 { 7 x.write(fs); 8 } 9 //============================================================================== 10 template<class T> 11 void 12 read(const FileNode& node, 13 T& x, 14 const T& d) 15 { 16 if(node.empty())x = d; else x.read(node); 17 }
-
为了让保存和加载采用了序列化的用户自定义类变得容易,采用模块化函数定义了load_ft,save_ft函数
1 template <class T> 2 T load_ft(const char* fname){ 3 T x; FileStorage f(fname,FileStorage::READ); 4 f["ft object"] >> x; f.release(); return x; // 定义与对象关联的标签都为 ft object 5 } 6 //============================================================================== 7 template<class T> 8 void save_ft(const char* fname,const T& x){ 9 FileStorage f(fname,FileStorage::WRITE); 10 f << "ft object" << x; f.release(); 11 }
-
将以上定义在 ft.hpp 中
ft.hpp
1 /* 2 ft.hpp 3 用于加载、保存对象数据 4 */ 5 6 #ifndef _FT_FT_HPP_ 7 #define _FT_FT_HPP_ 8 #include <opencv2/opencv.hpp> 9 //============================================================================== 10 // 为了让保存和加载采用了序列化的用户自定义类变得容易,采用模块化函数定义了load_ft,save_ft函数 11 template <class T> 12 T load_ft(const char* fname){ 13 T x; FileStorage f(fname,FileStorage::READ); 14 f["ft object"] >> x; f.release(); return x; // 定义与对象关联的标签都为 ft object 15 } 16 //============================================================================== 17 template<class T> 18 void save_ft(const char* fname,const T& x){ 19 FileStorage f(fname,FileStorage::WRITE); 20 f << "ft object" << x; f.release(); 21 } 22 //============================================================================== 23 // 为了使 FileStorage 类的序列化能正常工作,还需要定义write, read函数 24 template<class T> 25 void 26 write(FileStorage& fs, 27 const string&, 28 const T& x) 29 { 30 x.write(fs); 31 } 32 //============================================================================== 33 template<class T> 34 void 35 read(const FileNode& node, 36 T& x, 37 const T& d) 38 { 39 if(node.empty())x = d; else x.read(node); 40 } 41 //============================================================================== 42 #endif