OpenCV之getOptimalNewCameraMatrix

去畸变后的图像四周会出现黑色区域,如果畸变较大,如鱼眼镜头,四周黑色区域将会更大。
opencv中给我们提供了一个函数getOptimalNewCameraMatrix(),用于去除畸变矫正后图像四周黑色的区域。

该函数根据给定参数alpha计算最优的新相机内参矩阵。alpha=0,则去除所有黑色区域,alpha=1,则保留所有原始图像像素,其他值则得到介于两者之间的效果。

通过该函数,我们得到新的相机内参矩阵,然后利用initUndistortRectifyMap()即可获得用于remap()的映射矩阵。

主要步骤

获取内切和外切矩形

通过将整个图像划分9*9网格,然后对每个网格点去畸变。
通过比较这些去畸变后的网格点坐标,确定内切和外切矩形。

源码中提到:Get inscribed and circumscribed rectangles in normalized (independent of camera matrix) coordinates.
这是因为,在调用icvGetRectangles()获取内切和外切矩形时,R和newCameraMatrix为空。从cvUndistortPoints()源码可以知道,当R和newCameraMatrix为空,尤其是newCameraMatrix为空时,像素点去畸变后得到的是相机坐标系下的坐标。

static void
icvGetRectangles(const CvMat* cameraMatrix, const CvMat* distCoeffs,
	const CvMat* R, const CvMat* newCameraMatrix, CvSize imgSize,
	cv::Rect_<float>& inner, cv::Rect_<float>& outer)
{
   
	const int N = 9;
	int x, y, k;
	cv::Ptr<CvMat> _pts(cvCreateMat(1, N * N, CV_32FC2));
	CvPoint2D32f* pts = (CvPoint2D32f*)(_pts->data.ptr);

	for (y = k = 0; y < N; y++)
		for (x = 0; x < N; x++)
			pts[k++] = cvPoint2D32f((float)x * imgSize.width / (N - 1),
				(float)y * imgSize.height / (N - 1));
	// 由于R和newCameraMatrix为0,因此,去畸变后的坐标为相机坐标系下的坐标,(如 mm)
	cvUndistortPoints(_pts, _pts, cameraMatrix, distCoeffs, R, newCameraMatrix);
	
	float iX0 = -FLT_MAX, iX1 = FLT_MAX, iY0 = -FLT_MAX, iY1 = FLT_MAX;
	float oX0 = FLT_MAX, oX1 = -FLT_MAX, oY0 = FLT_MAX, oY1 = -FLT_MAX;
	// find the inscribed rectangle.
	// the code will likely not work with extreme rotation matrices (R) (>45%)
	for (y = k = 0; y < N; y++)
		for (x = 0; x < N; x++)
		{
   
			CvPoint2D32f p = pts[k++];
			oX0 = MIN(oX0, p.x);
			oX1 = MAX(oX1, p.x);
			oY0 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值