• 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。

  • 相关阅读:
    作业3
    学习进度
    作业2
    介绍自己,并介绍github注册过程和初步使用
    mysql显示中文乱码问题解决
    数学能力测试
    C++ Primer总结
    shell脚本
    完全二叉树
    test命令的测试功能
  • 原文地址:https://www.cnblogs.com/Anita9002/p/9266876.html
Copyright © 2020-2023  润新知