最近遇到一個函數,在調用的時候出現問題,記錄下實現過程。
#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。