透视变换(perspective transformation)

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。如下图所示

透视变换(perspective transformation)_第1张图片

透视变换

透视变换的原理和公式推导见如下博客
【图像处理】透视变换 Perspective Transformation
【OpenCV】透视变换 Perspective Transformation(续)
opencv之仿射变换
图像几何变换之透视变换
图像变换——向前映射和向后映射

opencv 相关函数

Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst)
// Calculate a perspective transform from four pairs of the corresponding points.
// src – Coordinates of quadrangle vertices in the source image.
// dst – Coordinates of the corresponding quadrangle vertices in the destination image.
 
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
// Apply a perspective transform to an image.
// src – Source image.
// dst – Destination image that has the size dsize and the same type as src.
// M – 3*3 transformation matrix.
// dsize – Size of the destination image.
// flags – Combination of interpolation methods and the optional flag WARP_INVERSE_MAP that means that M is the inverse transformation (dstsrc).
// borderMode – Pixel extrapolation method. When borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image that corresponds to the “outliers” in the source image are not modified by the function.
// borderValue – Value used in case of a constant border. By default, it is 0.


void perspectiveTransform(InputArray src, OutputArray dst, InputArray mtx)
Parameters:	
src – Source two-channel or three-channel floating-point array. Each element is a 2D/3D vector to be transformed.
dst – Destination array of ***the same size and type as src*** .
mtx – 3x3 or 4x4 floating-point transformation matrix.

  • c++ 代码实现

void ImageTransform::perspective_form(Mat &srcimg, Mat &dstimg, Mat &offset)
{
	Point2f quad_src[4];
	Point2f quad_dst[4];
	quad_src[0] = Point2f(0.0*srcimg.cols, 0.0*srcimg.rows);
	quad_src[1] = Point2f(srcimg.cols - 1, 0.0*srcimg.rows);
	quad_src[2] = Point2f(0.0*srcimg.cols, srcimg.rows - 1);
	quad_src[3] = Point2f(srcimg.cols - 1, srcimg.rows - 1);

	quad_dst[0] = Point2f(0.1*srcimg.cols, 0.1*srcimg.rows);
	quad_dst[1] = Point2f(srcimg.cols - 1, 0.0*srcimg.rows);
	quad_dst[2] = Point2f(0.0*srcimg.cols, srcimg.rows - 1);
	quad_dst[3] = Point2f(0.9*srcimg.cols, srcimg.rows - 1);

	Mat persMat = getPerspectiveTransform(quad_src, quad_dst);

	vector points, points_tran;
	for (int row = 0; row < srcimg.rows; row++)
	{
		for (int col = 0; col < srcimg.cols; col++)
		{
			points.push_back(Point2f(col, row));
		}
	}

	perspectiveTransform(points, points_tran, persMat);

	int count = 0;
	for (int row = 0; row < srcimg.rows; row++)
	{
		uchar *pixel = srcimg.ptr(row);
		float *dxy = offset.ptr(row);
		for (int col = 0; col < srcimg.cols; col++)
		{
			int x = static_cast(points_tran[count].x);
			int y = static_cast(points_tran[count].y);
			uchar *new_pixel = dstimg.ptr(y);

			new_pixel[3 * x] = pixel[3 * col]; //最近邻插值
			new_pixel[3 * x + 1] = pixel[3 * col + 1];
			new_pixel[3 * x + 2] = pixel[3 * col + 2];


			dxy[2 * col] = points_tran[count].y - row;
			dxy[2 * col + 1] = points_tran[count].x - col;
			count++;
		}
	}

	return;

}
透视变换(perspective transformation)_第2张图片

程序运行结果

你可能感兴趣的:(图像处理)