aihot  2017-05-21 11:04:15  OpenCV |   查看评论   

  仿射变换(affine transformation),又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间.它是一种二维坐标到二维坐标之间的线性变换,保持二维图形的”平直性”(straightness,即变换后直线还是直线不会打弯,圆弧还是圆弧)和”平行性”(parallelness,保持二维图形间的相对位置关系不变,平行线还是平行线,而直线上点的位置顺序不变,但向量间夹角可能会发生变化)。

 
一个任意的仿射变换都能表示为:乘以一个矩阵(线性变换)接着再加上一个向量(平移)。仿射变换能够表示:旋转(rotation)、平移(translation)、缩放(scale)、翻转(flip)和错切(剪切、shear)操作。事实上,仿射变换代表了两幅图像之间的关系。通常使用2*3矩阵来表示仿射变换。
 
         有了仿射变换矩阵后,计算目的图像的公式为:
 
dst(x,y)= src(M11x + M12y + M13, M21x + M22y + M23)
 
这里对OpenCV中warpAffine函数进行了提取,目前支持uchar和float两种类型,经测试,与OpenCV3.1结果完全一致。
 
实现代码warpAffine.hpp:
  1. // fbc_cv是免费软件,并且使用与OpenCV相同的许可证  
  2. #ifndef FBC_CV_WARP_AFFINE_HPP_  
  3. #define FBC_CV_WARP_AFFINE_HPP_  
  4.   
  5. /* reference: include/opencv2/imgproc.hpp 
  6.           modules/imgproc/src/imgwarp.cpp 
  7. */  
  8.   
  9. #include <typeinfo>  
  10. #include "core/mat.hpp"  
  11. #include "solve.hpp"  
  12. #include "imgproc.hpp"  
  13. #include "remap.hpp"  
  14.   
  15. namespace fbc {  
  16.   
  17. // 从三对对应点计算仿射变换
  18. FBC_EXPORTS int getAffineTransform(const Point2f src1[], const Point2f src2[], Mat_<double, 1>& dst);  
  19.   
  20. // 对图像应用仿射变换
  21. // 该功能无法正常工作
  22. // 支持类型:uchar / float
  23. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  24. int warpAffine(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst, const Mat_<_Tp2, chs2>& M_,  
  25.     int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar())  
  26. {  
  27.     FBC_Assert(src.data != NULL && dst.data != NULL && M_.data != NULL);  
  28.     FBC_Assert(src.cols > 0 && src.rows > 0 && dst.cols > 0 && dst.rows > 0);  
  29.     FBC_Assert(src.data != dst.data);  
  30.     FBC_Assert(typeid(double) == typeid(_Tp2) && M_.rows == 2 && M_.cols == 3);  
  31.     FBC_Assert((typeid(uchar).name() == typeid(_Tp1).name()) || (typeid(float).name() == typeid(_Tp1).name())); // uchar/float  
  32.   
  33.     double M[6];  
  34.     Mat_<double, 1> matM(2, 3, M);  
  35.     M_.convertTo(matM);  
  36.   
  37.     int interpolation = flags & INTER_MAX;  
  38.     if (interpolation == INTER_AREA)  
  39.         interpolation = INTER_LINEAR;  
  40.   
  41.     if (!(flags & WARP_INVERSE_MAP)) {  
  42.         double D = M[0] * M[4] - M[1] * M[3];  
  43.         D = D != 0 ? 1. / D : 0;  
  44.         double A11 = M[4] * D, A22 = M[0] * D;  
  45.         M[0] = A11; M[1] *= -D;  
  46.         M[3] *= -D; M[4] = A22;  
  47.         double b1 = -M[0] * M[2] - M[1] * M[5];  
  48.         double b2 = -M[3] * M[2] - M[4] * M[5];  
  49.         M[2] = b1; M[5] = b2;  
  50.     }  
  51.   
  52.     int x;  
  53.     AutoBuffer<int> _abdelta(dst.cols * 2);  
  54.     int* adelta = &_abdelta[0], *bdelta = adelta + dst.cols;  
  55.     const int AB_BITS = MAX(10, (int)INTER_BITS);  
  56.     const int AB_SCALE = 1 << AB_BITS;  
  57.   
  58.     for (x = 0; x < dst.cols; x++) {  
  59.         adelta[x] = saturate_cast<int>(M[0] * x*AB_SCALE);  
  60.         bdelta[x] = saturate_cast<int>(M[3] * x*AB_SCALE);  
  61.     }  
  62.   
  63.     Range range(0, dst.rows);  
  64.   
  65.     const int BLOCK_SZ = 64;  
  66.     short XY[BLOCK_SZ*BLOCK_SZ * 2], A[BLOCK_SZ*BLOCK_SZ];;  
  67.     int round_delta = interpolation == INTER_NEAREST ? AB_SCALE / 2 : AB_SCALE / INTER_TAB_SIZE / 2, y, x1, y1;  
  68.   
  69.     int bh0 = std::min(BLOCK_SZ / 2, dst.rows);  
  70.     int bw0 = std::min(BLOCK_SZ*BLOCK_SZ / bh0, dst.cols);  
  71.     bh0 = std::min(BLOCK_SZ*BLOCK_SZ / bw0, dst.rows);  
  72.   
  73.     for (y = range.start; y < range.end; y += bh0) {  
  74.         for (x = 0; x < dst.cols; x += bw0) {  
  75.             int bw = std::min(bw0, dst.cols - x);  
  76.             int bh = std::min(bh0, range.end - y);  
  77.   
  78.             Mat_<short, 2> _XY(bh, bw, XY);  
  79.             Mat_<_Tp1, chs1> dpart;  
  80.             dst.getROI(dpart, Rect(x, y, bw, bh));  
  81.   
  82.             for (y1 = 0; y1 < bh; y1++) {  
  83.                 short* xy = XY + y1*bw * 2;  
  84.                 int X0 = saturate_cast<int>((M[1] * (y + y1) + M[2])*AB_SCALE) + round_delta;  
  85.                 int Y0 = saturate_cast<int>((M[4] * (y + y1) + M[5])*AB_SCALE) + round_delta;  
  86.   
  87.                 if (interpolation == INTER_NEAREST) {  
  88.                     x1 = 0;  
  89.                     for (; x1 < bw; x1++) {  
  90.                         int X = (X0 + adelta[x + x1]) >> AB_BITS;  
  91.                         int Y = (Y0 + bdelta[x + x1]) >> AB_BITS;  
  92.                         xy[x1 * 2] = saturate_cast<short>(X);  
  93.                         xy[x1 * 2 + 1] = saturate_cast<short>(Y);  
  94.                     }  
  95.                 } else {  
  96.                     short* alpha = A + y1*bw;  
  97.                     x1 = 0;  
  98.                     for (; x1 < bw; x1++) {  
  99.                         int X = (X0 + adelta[x + x1]) >> (AB_BITS - INTER_BITS);  
  100.                         int Y = (Y0 + bdelta[x + x1]) >> (AB_BITS - INTER_BITS);  
  101.                         xy[x1 * 2] = saturate_cast<short>(X >> INTER_BITS);  
  102.                         xy[x1 * 2 + 1] = saturate_cast<short>(Y >> INTER_BITS);  
  103.                         alpha[x1] = (short)((Y & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE +  
  104.                             (X & (INTER_TAB_SIZE - 1)));  
  105.                     }  
  106.                 }  
  107.             }  
  108.   
  109.             if (interpolation == INTER_NEAREST) {  
  110.                 remap(src, dpart, _XY, Mat_<float, 1>(), interpolation, borderMode, borderValue);  
  111.             } else {  
  112.                 Mat_<ushort, 1> _matA(bh, bw, A);  
  113.                 remap(src, dpart, _XY, _matA, interpolation, borderMode, borderValue);  
  114.             }  
  115.         }  
  116.     }  
  117.   
  118.     return 0;  
  119. }  
  120.   
  121. // 命名空间fbc
  122.   
  123. #endif // FBC_CV_WARP_AFFINE_HPP_  

 

 

除特别注明外,本站所有文章均为 赢咖4注册 原创,转载请注明出处来自OpenCV代码提取:warpAffine函数的实现

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]