仿射变换

仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。 仿射变换能够保持图像的“平直性”,包括旋转,缩放,平移,错切操作。一般而言,仿射变换矩阵为23的矩阵,第三列的元素起着平移的作用,前面两列的数字对角线上是缩放,其余为旋转或者错切的作用。
仿射变换是一种二维坐标(x, y)到二维坐标(u, v)的线性变换。数学表达式如下:

对应的齐次坐标系如下


仿射变换保持了二维图形的“平直性”(直线经仿射变换后依然为直线)和“平行性”(直线之间的相对位置关系保持不变,平行线经仿射变换后依然为平行线,且直线上点的位置顺序不会发生变化)。非共线的三对对应点确定一个唯一的仿射变换。

API

计算旋转矩阵

public static Mat getRotationMatrix2D(Point center, double angle, double scale) 
  • 参数一:center,图像旋转的中心位置
  • 参数二:angle,图像旋转的角度,单位为度,正值为逆时针旋转
  • 参数三:scale,两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1

生成的旋转矩阵与旋转角度和旋转中心的关系。

举例说明,若scale为2,angle为90度,则m1为旋转矩阵

计算仿射矩阵(三点)

public static Mat getAffineTransform(MatOfPoint2f src, MatOfPoint2f dst)
  • 参数一:src,原图像中的三个像素坐标
  • 参数二:dst,目标图像中的三个像素坐标
  • 返回值:2*3 的变换矩阵。透视变换是3*3的矩阵,仿射则是2*3的矩阵

仿射变换

public static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue) 
  • 参数一:src,原图

  • 参数二:dst,透视变换后输出图像,与src数据类型相同,但是尺寸与dsize相同

  • 参数三:M,2*3变换矩阵

  • 参数四:dsize,输出图像的尺寸

  • 参数五:flags,插值方法标志

    // C++: enum InterpolationFlagspublic static final int        INTER_NEAREST = 0,        INTER_LINEAR = 1,        INTER_CUBIC = 2,        INTER_AREA = 3,        INTER_LANCZOS4 = 4,        INTER_LINEAR_EXACT = 5,        INTER_MAX = 7,        WARP_FILL_OUTLIERS = 8,        WARP_INVERSE_MAP = 16;
  • 参数六:borderMode,像素边界外推方法的标志。BORDER_CONSTANT 或者BORDER_REPLICATE

边界填充 作用
BORDER_CONSTANT 0 用特定值填充,如iiiiii|abcdefgh|iiiiiii
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|abcdefgh|ijklmno
BORDER_REFLECT101 4 与BORDER_REFLECT_101相同
BORDER_DEFAULT 4 与BORDER_REFLECT_101相同
BORDER_ISOLATED 16 不关心感兴趣区域之外的部分
  • 参数七:borderValue,填充边界使用的数值,默认情况下为0

操作

class AffineActivity : AppCompatActivity() {         private lateinit var mBinding: ActivityAffineBinding    private lateinit var mRgb: Mat    override fun onCreate(savedInstanceState: Bundle?) {             super.onCreate(savedInstanceState)        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_affine)        mRgb = Mat()        val bgr = Utils.loadResource(this, R.drawable.lena)        Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)        bgr.release()        showMat(mBinding.ivLena, mRgb)    }    private fun showMat(view: ImageView, source: Mat) {             val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)        Utils.matToBitmap(source, bitmap)        view.setImageBitmap(bitmap)    }    private fun rotateMatrix(degree: Double, scale: Double) {             val center = Point(mRgb.width() / 2.0, mRgb.height() / 2.0)        val matrix = Imgproc.getRotationMatrix2D(center, degree, scale)        val size = mRgb.size()        val dst = Mat()        Imgproc.warpAffine(mRgb, dst, matrix, size)        showMat(mBinding.ivResult, dst)        dst.release()    }    private fun threePointsMatrix() {             val srcPoints = arrayOfNulls<Point>(3)        val dstPoints = arrayOfNulls<Point>(3)        srcPoints[0] = Point(0.0, 0.0)        srcPoints[1] = Point(0.0, mRgb.width() - 1.0)        srcPoints[2] = Point(mRgb.height() - 1.0, mRgb.width() - 1.0)        dstPoints[0] = Point(mRgb.width() * 0.11, mRgb.width() * 0.2)        dstPoints[1] = Point(mRgb.width() * 0.15, mRgb.width() * 0.7)        dstPoints[2] = Point(mRgb.width() * 0.81, mRgb.width() * 0.85)        val transform = Imgproc.getAffineTransform(            MatOfPoint2f(srcPoints[0], srcPoints[1], srcPoints[2]),            MatOfPoint2f(dstPoints[0], dstPoints[1], dstPoints[2])        )        val dst = Mat()        val size = mRgb.size()        Imgproc.warpAffine(mRgb, dst, transform, size)        showMat(mBinding.ivResult, dst)        dst.release()    }    override fun onCreateOptionsMenu(menu: Menu?): Boolean {             menuInflater.inflate(R.menu.menu_affine, menu)        return true    }    override fun onOptionsItemSelected(item: MenuItem): Boolean {             title = item.title        when (item.itemId) {                 R.id.affine_rotate_scale -> rotateMatrix(120.0, 1.2)            R.id.affine_three_points -> threePointsMatrix()        }        return true    }}

效果

源码

https://github.com/onlyloveyd/LearningAndroidOpenCV

更多相关文章

  1. 2D平面中关于矩阵(Matrix)跟图形变换的讲解
  2. Android(安卓)View学习笔记(二):View滑动方式总结
  3. Android绘图机制与处理技巧——Android图像处理之色彩特效处理
  4. Android简单、高性能的高斯模糊(毛玻璃)效果(附源码)
  5. Android(安卓)数据持久化(SQLite数据存储)
  6. Android线程与并行,AsyncTask(AsyncTask回调方法、AsyncTask泛型参
  7. 图像处理-矩阵变换
  8. Android:分析onXXX事件监听器中的两个参数position和id
  9. 【Android】Android中WebView实现Java与JS交互

随机推荐

  1. 如何学习画插画?手绘插画学习教程
  2. <JVM中篇:字节码与类的加载篇>04-再谈类的加
  3. vue 简单使用
  4. 【Rocky Linux】Rocky Linux 8.5版本全新
  5. 【阿里云镜像】切换阿里巴巴开源镜像站镜
  6. 部署YUM源仓库与NFS共享存储服务
  7. 使用阿里云镜像站NTP服务搭建NTP服务器(基
  8. 干货分享:服务器托管的注意事项有哪些?
  9. WGS84从GPS中获取的坐标系,转换为百度BD-0
  10. 干货分享:服务器托管的注意事项有哪些?