自动驾驶AVM环视算法--鱼眼相机的畸变矫正原理和实测(图片和视频测试)

参考:金书世界

测试工程和视频:

链接:https://pan.baidu.com/s/11GNLuIxcONGCeobp0MbXFQ?pwd=0z6l 提取码:0z6l 

1、平面相机的成像和坐标系如下所示

说明

1、f(ud,vd)就是以图像中心为原点坐标(和p(x,y)坐标相对,就是坐表原点不同)。

2、p(x,y)就是在图像坐标系下的坐标点,坐标点的为图像的左上角点,这个和世界图像的保存数据的坐标一直。

3、假设xy坐标系的原点是uv坐标系的中点,相对的偏移量为cx和cy,就可以得出ud=x+cx,vd=y+cy。

4、P(Xc,Yc,Zc)就是相机坐标系下的坐标。

根据相似的三角形可以得出

AB/COuv=AOc/OcOuv=PB/pC=Xc/ud=Zc/f=Yc/vd

得出

Xc/ud=Zc/fx

Yc/vd=Zc/fy

得出

ud=fx(Xc/Zc)

vd=fy(Yc/Zc)

得出

x=fx(Xc/Zc)-cx

y=fy(Yc/Zc)-cy

2、鱼眼相机的成像坐标变换

参考:https://ww2.mathworks.cn/help/vision/ug/fisheye-calibration-basics.html

由上述的公式可以得出

上述公式中的ud和vd就是平面图像的坐标点,u和v 就是鱼眼图像坐标

根据上述的的计算公式就可以实现图像的畸变矫正

测试代码如下所示

void CjsAVMtoolDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
		//MFC弹出命令窗体
	AllocConsole();
	freopen("CONOUT$", "w", stdout);
	//MFC弹出命令窗体
	// TODO: 在此添加控件通知处理程序代码
	float  a[4] = { 160,-0.0005,0,0 };
	int cx = 640, cy = 360;//图像的中心点
	float fx = 100, fy = 100;//虚拟焦距
	float p = 0.0;
	Mat src = imread("test.jpg");
	Mat dst(src.rows, src.cols, CV_8UC3, Scalar(0, 0, 0));
	if (src.empty()) {
		printf("不能加载图像!\n");
	}
	namedWindow("原图", WINDOW_AUTOSIZE);
	imshow("原图", src);

	//像素读取方式:直接读取
	int height = src.rows;
	int width = src.cols;
	int ch = src.channels();
	js_Transplane2Fisheye_V1(&dst, src, a, fx, fy, cx, cy);
	//js_Transplane2Fisheye_V2(&dst, src, a, fx, fy, cx, cy);



	imshow("直接读取像素图", dst);
}

int js_Transplane2Fisheye_V1(Mat *Dst,Mat Src,float *a,float fx,float fy,int cx,int cy)
{
	for (int row = 0; row < Src.rows ; row++) {//h
		for (int col = 0; col < Src.cols; col++) {//w

			float x1 = ((float)(col - cx));
			float y1 = ((float)(row - cy));
			float p = sqrtf(x1 * x1 + y1 * y1);
			float x2 = x1 / (a[0] + a[1] * p * p + a[2] * p * p * p + a[3] * p * p * p * p);
			float y2 = y1 / (a[0] + a[1] * p * p + a[2] * p * p * p + a[3] * p * p * p * p);
			int ud = fx * x2 + cx + 0.5;
			int vd = fy * y2 + cy + 0.5;
			if (((ud >= 0) && (ud < Src.cols)) && ((vd >= 0) && (vd < Src.rows)))
			{
				Dst->at<Vec3b>(vd, ud) = Src.at<Vec3b>(row, col);
			}
		}
	}
	return 0;
}

测试图片和测试结果(测试结果图像存在无效的计算点)

输入图像

校正后图像

由于当前计算是完成算法的畸变矫正存在一定的流程缺陷,以下是升级版本后的测试结果

主要是使用迭代的当时计算

f(x+△x)=f(x)+△x*f‘’(x)

得出

(f(x+△x)-f(x))/f‘’(x)=△x

得出

(f(cur)-f(pre))/f'(pre)=cur-pre

得出

cur=pre+(f(cur)-f(pre))/f‘(pre)

每次计算完成后会更新cur之后将cur幅值给pre继续迭代,知道cur和pre的插值达到阈值后停止迭代或者是计算次数达到阈值后停止,就可以计算出坐标点cur的值。

测试视频

鱼眼相机畸变矫正

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AVM环视系统的视频校正主要包括对视频中的每一帧进行畸变矫正和图像拼接,这里提供一些相关的OpenCV代码供参考: ```python import cv2 import numpy as np # 标定板格点数 board_w = 9 board_h = 6 # 棋盘格角点坐标 objp = np.zeros((board_w * board_h, 3), np.float32) objp[:, :2] = np.mgrid[0:board_w, 0:board_h].T.reshape(-1, 2) # 存储棋盘格角点坐标和图像中对应点坐标的数组 objpoints = [] # 3D points in real world space imgpoints = [] # 2D points in image plane. # 读取棋盘格标定图片 img = cv2.imread('calibration.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 棋盘格角点检测 ret, corners = cv2.findChessboardCorners(gray, (board_w, board_h), None) # 如果检测到棋盘格角点,进行标定 if ret == True: objpoints.append(objp) imgpoints.append(corners) img = cv2.drawChessboardCorners(img, (board_w, board_h), corners, ret) # 相机内参、畸变系数等标定参数计算 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) # 视频校正 cap = cv2.VideoCapture('test.mp4') fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, 30.0, (1280, 720)) while cap.isOpened(): ret, frame = cap.read() if ret == True: # 畸变矫正 h, w = frame.shape[:2] newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h)) dst = cv2.undistort(frame, mtx, dist, None, newcameramtx) # 图像拼接 dst1 = cv2.warpPerspective(dst, H, (w, h)) dst2 = cv2.warpPerspective(dst, H, (w, h)) dst3 = cv2.warpPerspective(dst, H, (w, h)) dst4 = cv2.warpPerspective(dst, H, (w, h)) dst = cv2.add(dst1, dst2) dst = cv2.add(dst, dst3) dst = cv2.add(dst, dst4) # 写入视频文件 out.write(dst) # 显示结果 cv2.imshow('frame', dst) if cv2.waitKey(1) & 0xFF == ord('q'): break else: break # 释放资源 cap.release() out.release() cv2.destroyAllWindows() ``` 这里H是通过图像校正算法(如SIFT、SURF等)计算出来的单应性矩阵,四个 `dst` 分别对应四个摄像头采集的图像。最终将四个 `dst` 进行图像拼接,得到完整的车辆周围环境全景图像,并将校正后的视频帧写入输出视频文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值