opencv 透视变换矫正图像畸变

简述

在图像处理中,因为镜头角度等原因,容易导致图像出现倾斜、变形等情况,为了方便后续处理我们常常需要进行图像矫正,其中主要技术原理是两种变换类型--仿射变换(Affine Transformation)和透视变换(Perspective Transformation)。

详解

仿射变换是二维坐标间的线性变换,故而变换后的图像仍然具有原图的一些性质,包括“平直性”以及“平行性”,常用于图像翻转(Flip)、旋转(Rotations)、平移(Translations)、缩放(Scale operations)等,具体到代码应用可以参见OpenCV官方介绍。

但是仿射变换不能矫正一些变形,如矩形区域的部分发生变化最终变成梯形,这时候矫正就需要用到透视变换。透视变换(Perspective Transformation),又称投影映射(Projective Mapping)、投射变换等,是三维空间上的非线性变换,即通过一个3x3的变换矩阵将原图投影到一个新的视平面,在视觉上的直观表现就是产生或消除了远近感。

步骤

1、首先第一步,先获取透视变换的变换矩阵,通过下面这个方法来获取:

Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[]) 

输入原始图像和变换之后的图像的4组对应点,便可以得到变换矩阵。

2、透视变换。图像的透视变换由以下函数完成(该函数是针对图像的包装,其本质调用cv::perspectiveTransform进行向量坐标的变换):

void cv::warpPerspective (
		InputArray 	src, 
		OutputArray 	dst, 
		InputArray 	M, 
		Size 	dsize, 
		int 	flags = INTER_LINEAR, 
		int 	borderMode = BORDER_CONSTANT, 
		const Scalar &borderValue = Scalar(0)
)

src是输入图像,dst是输出图像,M是3x3变换矩阵,dsize是输出图像的大小,flags指定像素插补方法以及矩阵倒置标志cv::WARP_INVERSE_MAP,CV_INTER_LINEAR填充所有目标图像的像素,如果部分图像落在边界外,那么它们的值将被设定为fillval
borderMode指定边沿像素的推算模式,其中BORDER_CONSTANT指边沿像素用borderValue替换,因为默认是0,所以我们变换后的图像边界可能会出现黑边,此时可以指定BORDER_REPLICATE对边界像素进行复制。

实例:

int TransforMatrix(vector<cv::Point2f> screenPoints,vector<cv::Point2f> wallPoints)
{
	int screenPts_Len = screenPoints.size();
	int wallPts_Len = wallPoints.size();
	if (screenPts_Len != 4  || wallPts_Len != 4)
	{
		return PROJ_FAIL;
	}
	
	//原始图像四角点
	cv::Point2f *pts_src;
	//目标图像四角点
	cv::Point2f *pts_dst;	
	//3 X 3变换矩阵
	Mat m_MapMatrix;

	//【0】映射对应点对
	for (int k = 0; k < 4; k++)
	{
		pts_src[k] = wallPoints[k];
		pts_dst[k] = screenPoints[k];
	}

	//【1】求得映射矩阵 m_MapMatrix 是3 x 3 变换矩阵
	m_MapMatrix = getPerspectiveTransform(pts_src, pts_dst);
	
	//【2】透视变换
	//m_foreImg 与 screenImg大小相同
	//m_dstWidth、m_dstHeight指目标函数宽、高
	warpPerspective(m_foreImg, screenImg, m_MapMatrix, Size(m_dstWidth, m_dstHeight), CV_INTER_LINEAR , BORDER_REPLICATE);
	
        //screenImg为转换后的图像
	return PROJ_OK;
}

附两篇关于“透视变换”的博客:

https://blog.csdn.net/xiaowei_cqu/article/details/26471527

https://blog.csdn.net/u012590570/article/details/51355600

  • 2
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
鱼眼图像畸变校正的透视变换原理如下: 1. 首先,需要确定图像中的两个灭点,这可以通过球面透视投影得到。 2. 然后,根据灭点的位置,确定仿射变换矩阵,将图像进行仿射变换。 3. 最后,对变换后的图像进行裁剪,得到最终的校正图像。 下面是一个使用OpenCV进行鱼眼图像畸变校正的Python代码示例: ```python import cv2 import numpy as np # 读取鱼眼图像 img = cv2.imread('fisheye.jpg') # 确定灭点 h, w = img.shape[:2] K = np.array([[w, 0, w/2], [0, w, h/2], [0, 0, 1]]) D = np.array([0, 0, 0, 0]) newK = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(K, D, (w, h), np.eye(3)) map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), newK, (w, h), cv2.CV_16SC2) img_undistorted = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT) # 确定仿射变换矩阵 src_points = np.float32([[0, 0], [w-1, 0], [0, h-1], [w-1, h-1]]) dst_points = np.float32([[w/4, h/4], [w*3/4, h/4], [0, h], [w, h]]) M = cv2.getPerspectiveTransform(src_points, dst_points) # 进行仿射变换 img_transformed = cv2.warpPerspective(img_undistorted, M, (w, h)) # 裁剪图像 img_corrected = img_transformed[int(h/4):int(h*3/4), int(w/4):int(w*3/4)] # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Undistorted Image', img_undistorted) cv2.imshow('Transformed Image', img_transformed) cv2.imshow('Corrected Image', img_corrected) cv2.waitKey(0) cv2.destroyAllWindows() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值