Android 版 OpenCV 透视变换和仿射变换详解
在 Android 版本的 OpenCV 中,透视变换(Perspective Transformation) 和 仿射变换(Affine Transformation) 是两种常见的几何变换,用于图像校正、变形、对齐等任务。本文将详细介绍它们的原理、实现方法及应用场景。
1. 透视变换(Perspective Transformation)
1.1 透视变换概述
透视变换用于将图像从一种视角转换到另一种视角。例如,将倾斜的文本矫正为正视角,或者将拍摄的名片校正成标准矩形。
• 输入: 四个原始点(图像中的四个角)
• 输出: 变换后的四个点(目标位置的四个角)
• 公式:
透视变换使用 3×3 矩阵,计算方式如下:
其中:
• 是原始坐标
• 是变换后的坐标
• 是缩放因子
• 是透视变换矩阵的参数
1.2 透视变换实现
步骤
-
选取原始图像中的 四个顶点。
-
设定变换后的 四个目标点(通常是矩形)。
-
计算透视变换矩阵 getPerspectiveTransform()
-
进行透视变换 warpPerspective()
示例代码
scss
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
public class PerspectiveTransform {
public static Bitmap applyPerspectiveTransform(Bitmap inputBitmap) {
// 将 Bitmap 转换为 Mat
Mat srcMat = new Mat();
Utils.bitmapToMat(inputBitmap, srcMat);
// 定义源点(选取原图中的四个角点)
Point srcPoints[] = {
new Point(50, 50), // 左上角
new Point(450, 50), // 右上角
new Point(50, 400), // 左下角
new Point(450, 400) // 右下角
};
MatOfPoint2f srcMatOfPoint = new MatOfPoint2f(srcPoints);
// 定义目标点(变换后的矩形区域)
Point dstPoints[] = {
new Point(0, 0),
new Point(500, 0),
new Point(0, 500),
new Point(500, 500)
};
MatOfPoint2f dstMatOfPoint = new MatOfPoint2f(dstPoints);
// 计算透视变换矩阵
Mat perspectiveMatrix = Imgproc.getPerspectiveTransform(srcMatOfPoint, dstMatOfPoint);
// 进行透视变换
Mat outputMat = new Mat();
Imgproc.warpPerspective(srcMat, outputMat, perspectiveMatrix, new Size(500, 500));
// 转换回 Bitmap
Bitmap outputBitmap = Bitmap.createBitmap(outputMat.cols(), outputMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(outputMat, outputBitmap);
return outputBitmap;
}
}
应用场景
• 文档扫描矫正(拍摄歪斜的文档,并修正为正面视角)
• 车牌识别(校正角度,提取车牌)
• 图像投影校正(如投影仪的画面修正)
2. 仿射变换(Affine Transformation)
2.1 仿射变换概述
仿射变换用于对图像进行 缩放、旋转、平移、剪切 ,但不会改变图像的平行性。其特点是:
• 直线仍然是直线
• 平行线仍然平行
• 输入: 三个原始点
• 输出: 变换后的三个点
• 公式:
仿射变换使用 2×3 矩阵,计算方式如下:
2.2 仿射变换实现
步骤
-
选择原始图像中的 三个点。
-
设定变换后的 目标点。
-
计算仿射变换矩阵 getAffineTransform()
-
进行仿射变换 warpAffine()
示例代码
scss
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
public class AffineTransform {
public static Bitmap applyAffineTransform(Bitmap inputBitmap) {
// 转换 Bitmap 为 Mat
Mat srcMat = new Mat();
Utils.bitmapToMat(inputBitmap, srcMat);
// 选择三个原始点
Point srcPoints[] = {
new Point(50, 50),
new Point(200, 50),
new Point(50, 200)
};
MatOfPoint2f srcMatOfPoint = new MatOfPoint2f(srcPoints);
// 目标点(变换后的新位置)
Point dstPoints[] = {
new Point(10, 100),
new Point(200, 50),
new Point(100, 250)
};
MatOfPoint2f dstMatOfPoint = new MatOfPoint2f(dstPoints);
// 计算仿射变换矩阵
Mat affineMatrix = Imgproc.getAffineTransform(srcMatOfPoint, dstMatOfPoint);
// 进行仿射变换
Mat outputMat = new Mat();
Imgproc.warpAffine(srcMat, outputMat, affineMatrix, srcMat.size());
// 转换回 Bitmap
Bitmap outputBitmap = Bitmap.createBitmap(outputMat.cols(), outputMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(outputMat, outputBitmap);
return outputBitmap;
}
}
应用场景
• 旋转图像(如倾斜文本校正)
• 面部对齐(将不同角度的人脸归一化)
• 图像增强(调整物体位置)
3. 透视变换 vs 仿射变换
变换类型 | 需要点数 | 适用场景 | 是否保持平行性 | 是否允许透视扭曲 |
---|---|---|---|---|
透视变换 | 4 | 视角矫正、车牌校正 | 否 | 是 |
仿射变换 | 3 | 旋转、缩放、平移 | 是 | 否 |
总结
• 透视变换 适用于 角度矫正,如文档扫描、车牌识别。
• 仿射变换 适用于 缩放、旋转、平移,如图像对齐、人脸对齐。
• 在 Android 版 OpenCV 中,可以使用 Imgproc.getPerspectiveTransform() 和 Imgproc.getAffineTransform() 计算变换矩阵,并用 warpPerspective() 或 warpAffine() 进行变换。