【學習OpenCV】仿射變換函式warpAffine、旋轉
阿新 • • 發佈:2019-02-10
理論
翻開任意一本影象處理的書,都會講到影象的幾何變換,這裡麵包括:仿射變換(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度
更多請參考: