c++ 一个h文件里面定义一个主类,然后定义多个子类

最近遇到一个函数,在调用的时候出现问题,记录下实现过程。

 

#ifndef MLS_DEFORMATION_H
#define MLS_DEFORMATION_H

#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

class MLSDeformation//父类
{
public:
    virtual bool InitMLSD(const cv::Mat& oriImg,const std::vector<cv::Point2i>&src_pt,int alpha=1, int gridsize=5);//定义成虚函数是为了方便子类改写
    virtual cv::Mat Deformation(const std::vector<cv::Point2i> &dst_pt)=0;//=0说明这个函数没有实现完
    explicit MLSDeformation();// 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
    virtual ~MLSDeformation();
protected:
    cv::Mat getDeformationImg();
    void meanMat(cv::Mat& mat, int i, int j);//对mat(i,j)进行gridsize的中值(当mean为空时),不包括像素为空的坐标
    void repairMat(cv::Mat& mat);//变形后的mat有些位置没有像素点,使用中值滤波填补
    int gridsize_;
    int alpha_;///weight_计算相关
    int n_point_;///控制点数
    cv::Mat src_img_;//原图像
    int src_width_;
    int src_height_;
    std::vector<cv::Point2d> pi_point_;//原控制点
    std::vector<cv::Point2d> qi_point_;//变形后的控制点
    ///参数信息
    double*weight_;//权重w*h*pt
    double*sum_weight_;//w*h
    cv::Point2d*deformation_pt_;//对应目标坐标
    cv::Point2d pstart_, qstart_;
    std::vector<cv::Point2d> pdiff_, qdiff_;
};

class MLSDAffine :public MLSDeformation//继承主类的子类
{
public:
    virtual bool InitMLSD(const cv::Mat& oriImg,const std::vector<cv::Point2i>&src_pt,int alpha=1, int gridsize=5);//写成virtual完全是因为从主类拷贝过来的,也可以认为方便接下来的子类继承他
    virtual cv::Mat Deformation(const std::vector<cv::Point2i> &dst_pt);
    explicit MLSDAffine();
    virtual~MLSDAffine();
private:
    double*a_affine_;///affine A参数
};

class MLSDSimilarity :public MLSDeformation
{
public:
    virtual bool InitMLSD(const cv::Mat& oriImg,const std::vector<cv::Point2i>&src_pt,int alpha=1, int gridsize=5);
    virtual cv::Mat Deformation(const std::vector<cv::Point2i> &dst_pt);
    explicit MLSDSimilarity();
    virtual~MLSDSimilarity();
private:
    double*us_;//us参数
    cv::Matx22d*a_similarity_;///similarity A参数
};

class MLSDRigid :public MLSDeformation
{
public:
    virtual bool InitMLSD(const cv::Mat& oriImg,const std::vector<cv::Point2i>&src_pt,int alpha=1, int gridsize=5);
    virtual cv::Mat Deformation(const std::vector<cv::Point2i> &dst_pt);
    explicit MLSDRigid();
    virtual~MLSDRigid();
private:
    double*ur_;//us参数
    cv::Point2d*pstart_rigid_;//
    cv::Matx22d*a_rigid_;///similarity A参数
};
#endif // MLS_DEFORMATION_H

 

 从上面的实现可以看出,实现了一个MLS变形的方法,里面有两个函数,分别是init和deformation,然后三个子类开始继承这个父类,然后分别实现了MLS的仿射变换,相似变换,刚性变化。

这里顺便扩展下几个变换的意义。

仿射变换:主要包括平移变换、旋转变换、缩放变换(也叫尺度变换)、倾斜变换(也叫错切变换、剪切变换、偏移变换)、翻转变换,有六个自由度。

仿射变换保持二维图形的“平直性”和“平行性”,但是角度会改变。 
“平直性”:变换后直线还是直线、圆弧还是圆弧。 
“平行性”:平行线还是平行线,直线上点的位置顺序不变

相似变换:相当于是等距变换和均匀缩放的一个复合,用S表示变换矩阵,即为 

 

左上角2×2矩阵为旋转部分,tx和ty为平移因子,它有4个自由度,即旋转,x方向平移,y方向平移和缩放因子s。相似变换前后长度比,夹角,虚圆点I,J保持不变。相似变换其实与相似三角形之间是有类似的。

在调用这些方法的时候,主要可以有以下几种方式。

刚性变换:只有物体的位置(平移变换)和朝向(旋转变换)发生改变,而形状不变。

调用上述类的方法:

 第一,直接调用子类:

MLSDRigid mlsr;
mlsr.InitMLSD(<#const cv::Mat &oriImg#>, <#const std::vector<cv::Point2i> &src_pt#>);

 

第二,调用父类,然后指针操作

    MLSDeformation *mls;
    mls = new MLSDAffine;
    mls->InitMLSD(src,src_pt,alpha, gridsize);

 

甚至可以写成switch case语句,不同的条件下,mls new不同的子类,然后调用他的method。

 

posted @ 2018-07-05 10:17  Anita-ff  阅读(2619)  评论(0编辑  收藏  举报