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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM