1. 程式人生 > >【學習OpenCV】仿射變換函式warpAffine、旋轉

【學習OpenCV】仿射變換函式warpAffine、旋轉

理論

翻開任意一本影象處理的書,都會講到影象的幾何變換,這裡麵包括:仿射變換(affine transformation)、投影變換(projecttive transformation)。前者針對的是平面上的物體位姿變化,如水平/垂直方向位移、旋轉、縮小/放大,常見的應用有ORC字元識別。後者針對的是三維空間中的位置變化,受限於物體依然是平面的,也稱為二維投影變換,常見的應用有車牌識別。

影象變換:以上所有變換均可以通過矩陣描述,將輸入影象與變換矩陣進行矩陣乘法得到變換後的影象座標。顯然,這種方式非常適合程式設計實現。

opencv仿射變換函式說明

opencv提供了,從變換矩陣計算,到影象變換,每個流程的一攬子解決方案。

1、getAffineTransform

Mat getAffineTransform(InputArray src, InputArray dst)
該函式需要已知變換前與變換後的座標,返回相應的變換矩陣,至於是何種變換無需事先知道。適用於目標檢測場合,通過檢測得到的特徵點進行影象匹配。


2、getRotationMatrix2D

Mat getRotationMatrix2D(Point2f center, double angle, double scale)
已知旋轉中心座標(座標原點為影象左上端點)、旋轉角度(單位為度°,順時針為負,逆時針為正)、放縮比例,返回旋轉/放縮矩陣。與getAffineTransform相比,無需知道變換後坐標,適用於一般情況下的影象變換。

3、warpAffine

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
根據etAffineTransform或getRotationMatrix2D得到的變換矩陣,計算變換後的影象。
src為輸入影象

dst為變換後圖像,型別與src一致。

M為變換矩陣,需要通過其它函式獲得,當然也可以手動輸入。

dsize為輸出影象的大小

flags,插值演算法,詳細如下:

enum InterpolationFlags{
    /** nearest neighbor interpolation */
    INTER_NEAREST        = 0,  //最近鄰插值
    /** bilinear interpolation */
    INTER_LINEAR         = 1, //雙線性插值
    /** bicubic interpolation */
    INTER_CUBIC          = 2, //雙三次插值
    /** resampling using pixel area relation. It may be a preferred method for image decimation, as
    it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST
    method. */
    INTER_AREA           = 3, //區域插值,使用象素關係重取樣。當影象縮小時候,該方法可以避免波紋出現。當影象放大時,類似於 <span style="font-family: Arial, Helvetica, sans-serif;">INTER_NEAREST</span>方法
    /** Lanczos interpolation over 8x8 neighborhood */
    INTER_LANCZOS4       = 4, //Lanczos插值(超過8×8畫素鄰域的Lanczos插值)
    /** mask for interpolation codes */
    INTER_MAX            = 7,
    /** flag, fills all of the destination image pixels. If some of them correspond to outliers in the
    source image, they are set to zero */
    WARP_FILL_OUTLIERS   = 8, //填充所有輸出影象的象素
    /** flag, inverse transformation

    For example, polar transforms:
    - flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$
    - flag is set: \f$dst(x,y) = src( \phi , \rho )\f$
    */
    WARP_INVERSE_MAP     = 16  //逆變換
};
borderMode,邊界處理方式
enum BorderTypes {
    BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i`
    BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
    BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`
    BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`
    BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
    BORDER_TRANSPARENT = 5, //!< `uvwxyz|absdefgh|ijklmno`

    BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_ISOLATED    = 16 //!< do not look outside of ROI
};



opencv實現影象旋轉(其它仿射變換的流程與此一致)

	Mat src;
	Mat dst(src.size(),src.type());
...
	cv::Point2f center(x0,y0);
	double ang = -30;
	cv::Mat rotMat = cv::getRotationMatrix2D(center,ang,1);
	cv::warpAffine(src,dst,rotMat,src.size());
順時針旋轉30度

更多請參考: