Image perspective transformation
Perspective Transformation refers to a Transformation that makes the shadow plane (Perspective plane) rotate a certain Angle around the trace line (Perspective axis) according to the Perspective rotation law under the condition that the center, image point and target point are collinear, destroys the original projected ray beam, and still keeps the projected geometric figure on the shadow plane unchanged. Perspective transformation is based on the law of object imaging projection transformation, that is, the object is re-projected to a new imaging plane. Perspective transformation is often used in the research of robot visual navigation. Because of the oblique Angle between the camera field and the ground, the object image is distorted, so perspective transformation is usually used to correct the object image.
The principle of
There are eight unknowns in the equation system of perspective transformation, so the solution needs to find four groups of mapping points, and four points just determine a three-dimensional space.
API
Take the transformation matrix
public static Mat getPerspectiveTransform(Mat src, Mat dst, int solveMethod)
Copy the code
- Parameter 1: SRC, four pixel coordinates in the original image
- Parameter two: DST, four pixel coordinates in the target image
- Parameter 3: solveMethod, select the symbol of the method to calculate perspective transformation matrix. By default, select the Gaussian elimination method DECOMP_LU of the best spindle element
enum DecompTypes {
DECOMP_LU = 0.
DECOMP_SVD = 1.
DECOMP_EIG = 2.
DECOMP_CHOLESKY = 3.
DECOMP_QR = 4.
DECOMP_NORMAL = 16
};
Copy the code
Sign a | value | role |
---|---|---|
DECOMP_LU | 0 | Gaussian elimination method for optimum principal axis elements |
DECOMP_SVD | 1 | Singular value decomposition (SVD) method |
DECOMP_EIG | 2 | Eigenvalue decomposition method |
DECOMP_CHOLESKY | 3 | Cholesky decomposition method |
DECOMP_QR | 4 | QR decomposition method |
DECOMP_NORMAL | 16 | To use the normal equation formula, you can use it in conjunction with the previous symbol |
Perspective transformation
public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue)
Copy the code
-
Parameter 1: SRC, original image
-
Parameter 2: DST, output image after perspective transformation, same data type as SRC, but same size as Dsize
-
Parameter 3: M, 3*3 transformation matrix
-
Parameter 4: Dsize, output image size
-
Parameter 5: flags, interpolation method flags
// C++: enum InterpolationFlags
public 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;
Copy the code -
Parameter 6: borderMode, the flag of the pixel boundary extrapolation method. BORDER_CONSTANT or BORDER_REPLICATE
-
Parameter seven: borderValue, the number used to fill the border, 0 by default
operation
The following code realizes that the image taken by the camera whose line of sight is not perpendicular to the road plane is transformed into an image taken by the camera whose line of sight is perpendicular to the road plane through perspective transformation.
class PerspectiveTransformationActivity : AppCompatActivity() {
private lateinit var mBinding: ActivityPerspectiveTransformationBinding
private lateinit var mRgb: Mat
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
mBinding =
DataBindingUtil.setContentView(this, R.layout.activity_perspective_transformation)
val bgr = Utils.loadResource(this, R.drawable.road)
mRgb = Mat()
Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
showMat(mBinding.ivRoad, mRgb)
doPerspectiveTransform()
}
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 getPerspectiveTransform(a): Mat {
val srcPoints = ArrayList<Point>()
val p1 = Point(325.0000.374.0000)
srcPoints.add(p1)
val p2 = Point(597.0000.374.0000)
srcPoints.add(p2)
val p3 = Point(960.0000.505.0000)
srcPoints.add(p3)
val p0 = Point(0.0000.505.0000)
srcPoints.add(p0)
val srcMat = Converters.vector_Point2f_to_Mat(srcPoints)
val resultWidth = 500.0
val resultHeight = 500.0
val dstPoints = ArrayList<Point>()
val p5 = Point(0.0.0.0)
dstPoints.add(p5)
val p6 = Point(resultWidth, 0.0)
dstPoints.add(p6)
val p7 = Point(resultWidth, resultHeight)
dstPoints.add(p7)
val p4 = Point(0.0, resultHeight)
dstPoints.add(p4)
val dstMat = Converters.vector_Point2f_to_Mat(dstPoints)
return Imgproc.getPerspectiveTransform(srcMat, dstMat)
}
private fun doPerspectiveTransform(a) {
val transform = getPerspectiveTransform()
val dst = Mat()
Imgproc.warpPerspective(
mRgb,
dst,
transform,
Size(500.0.500.0),
Imgproc.INTER_NEAREST
)
showMat(mBinding.ivResult, dst)
}
override fun onDestroy(a) {
mRgb.release()
super.onDestroy()
}
}
Copy the code
The effect
The source code
Github.com/onlyloveyd/…
This article is formatted using MDNICE