仿射变换(affine transformation / affine map)

仿射变换,又称仿射映射。对图像的坐标向量进行一次线性变换和平移。特点是变换前后图像保持平直性(直线变换后任然是直线)和平行性(平行线变换后任然是平行线)。也就是二维平面上点的相对位置保持不变。

常见的仿射变换有:

  • 平移 (translation)
  • 翻转(flip)
  • 缩放 (scale)
  • 旋转 (rotation)
  • 错切 (shear)
    这些变换都是仿射变换的特色情况,仿射变换还可以产生许多其他形式的变换。

具体的原理和公式推导都不难,详细可见一下博客,写得逻辑清楚,通俗易懂。

opencv学习(三十五)之仿射变换warpAffine
OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)
OpenCV仿射变换+投射变换+单应性矩阵
OpenCV探索之路(八):重映射与仿射变换
opencv之仿射变换


opencv相关函数

void cv::warpAffine     (  
        InputArray      src,
        OutputArray     dst,
        InputArray      M,
        Size    dsize,
        int     flags = INTER_LINEAR,
        int     borderMode = BORDER_CONSTANT,
        const Scalar &      borderValue = Scalar() 
    )

Mat getAffineTransform( 
      const Point2f src[],
      const Point2f dst[] );

Mat cv::getRotationMatrix2D     (   Point2f     center,
        double      angle,
        double      scale 
    )   

void remap(
     InputArray src, 
     OutputArray dst,
     InputArray map2,
     int interpolation, 
     int borderMode = BORDER_CONSTANT,
     const Scalar& borderValue = Scalar());

相关函数的用法和解释见一下博客:
opencv学习(三十五)之仿射变换warpAffine
OpenCV探索之路(八):重映射与仿射变换

  • C++ 代码实现

/**************
旋转和缩放变换
srcimg,dstimg,offset 必须大小相同
offset 为CV_32F2C
**************/
void ImageTransform::rotationAndScale_form(Mat &srcimg, Mat &dstimg, Mat &offset, double angle, double scale)
{
    Point center = Point2f(float(srcimg.cols / 2), float(srcimg.rows / 2));

    Mat rotMat = getRotationMatrix2D(center, angle, scale);
    warpAffine(srcimg, dstimg, rotMat, dstimg.size());
    double *data = rotMat.ptr<double>(0, 0);
    for (int row = 0; row < srcimg.rows; row++)
    {
        for (int col = 0; col < srcimg.cols; col++)
        {
            float x = static_cast<float>(col*data[0] + row*data[1] + data[2]);
            float y = static_cast<float>(col*data[3] + row*data[4] + data[5]);
            float dx = x - col;
            float dy = y - row;
            offset.at(row, col) = Vec2f(dy, dx);
        }
    }
    return;
}

/**************
仿射变换
srcimg,dstimg,offset 必须大小相同
offset 为CV_32F2C
**************/
void ImageTransform::warp_form(Mat &srcimg, Mat &dstimg, Mat &offset)
{
    Point2f srcTri[3];
    Point2f dstTri[3];
    srcTri[0] = Point2f(0.0, 0.0);
    srcTri[1] = Point2f(static_cast<float>(srcimg.cols - 1), 0.0);
    srcTri[2] = Point2f(0.0, static_cast<float>(srcimg.rows - 1));


    dstTri[0] = Point2f(static_cast<float>(srcimg.cols * 0.0), static_cast<float>(srcimg.rows * 0.33));
    dstTri[1] = Point2f(static_cast<float>(srcimg.cols * 0.65), static_cast<float>(srcimg.rows * 0.35));
    dstTri[2] = Point2f(static_cast<float>(srcimg.cols * 0.15), static_cast<float>(srcimg.rows * 0.6));

    Mat matWarp = getAffineTransform(srcTri, dstTri);
    warpAffine(srcimg, dstimg, matWarp, dstimg.size());
    double *data = matWarp.ptr<double>(0, 0);
    for (int row = 0; row < srcimg.rows; row++)
    {
        for (int col = 0; col < srcimg.cols; col++)
        {
            float x = static_cast<float>(col*data[0] + row*data[1] + data[2]);
            float y = static_cast<float>(col*data[3] + row*data[4] + data[5]);
            float dx = x - col;
            float dy = y - row;
            offset.at(row, col) = Vec2f(dy, dx);
        }
    }
    return;
}


仿射变换(affine transformation / affine map)_第1张图片
程序运行结果

你可能感兴趣的:(图像处理,仿射变换,仿射映射,affine)