Android(安卓)OpenCV(十一):图像仿射变换
16lz
2021-01-26
仿射变换
仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。 仿射变换能够保持图像的“平直性”,包括旋转,缩放,平移,错切操作。一般而言,仿射变换矩阵为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
更多相关文章
- 2D平面中关于矩阵(Matrix)跟图形变换的讲解
- Android(安卓)View学习笔记(二):View滑动方式总结
- Android绘图机制与处理技巧——Android图像处理之色彩特效处理
- Android简单、高性能的高斯模糊(毛玻璃)效果(附源码)
- Android(安卓)数据持久化(SQLite数据存储)
- Android线程与并行,AsyncTask(AsyncTask回调方法、AsyncTask泛型参
- 图像处理-矩阵变换
- Android:分析onXXX事件监听器中的两个参数position和id
- 【Android】Android中WebView实现Java与JS交互