本人由于实际需要入手了一款双目免驱usb摄像头,因为需要做深度估计,故需要标定内参,双目相机标定主要是为了获得摄像头的内参(f,1/dx,1/dy,cx,cy)、畸变参数(k1,k2,k3,p1,p1)和外参(R,t),用于接下来的双目校正和深度图生成。
具体标定步骤如下:
一、获得棋盘格图像
大多数双目标定都是用棋盘格进行标定,如下所示:
这里有一段c++代码,用于生成棋盘格图像:
//双目采集图像程序
#include<opencv2/opencv.hpp>
#include<stdlib.h>
using namespace cv;
using namespace std;
#define WIDTH 1280 //双目分辨率,根据自己摄像头型号选择数值
#define HEIGHT 480 //双目分辨率,根据自己摄像头型号选择数值
int main(int argc, char *argv[])
{
VideoCapture capture(0);
if (!capture.isOpened())
{
cout<<"can not open the camera"<<endl; cin.get(); exit(1);
}
capture.set(CV_CAP_PROP_FRAME_WIDTH, WIDTH);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);
string left_road;
string right_road;
int num = 0;
int count = 0;
Rect leftRect(0, 0, WIDTH/2, HEIGHT); //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height
Rect rightRect(WIDTH/2, 0, WIDTH/2, HEIGHT);
while (1) {
Mat frame; capture>>frame; //载入图像
if (frame.empty())
{
//判断图像是否载入 cout<<"can not load the frame"<<endl;
} else {
count++;
if (count == 1) {
cout<<frame.cols<<" "<<frame.rows<<endl;
}
Mat leftImg,rightImg;
frame(leftRect).copyTo(leftImg); //将一幅图分割成单独的左目图像
frame(rightRect).copyTo(rightImg); //将一幅图分割成单独的右目图像
imshow("left",leftImg);
imshow("right",rightImg);
char q=waitKey(30);
if (q == 27) { //按esc退出
break;
}
if (q == 32) //按空格保存,保存到项目的build文件夹下
{
num++;
cout << num;
left_road = "F:\\graph\\left\\" + to_string(num) + ".png";
right_road = "F:\\graph\\right\\"+to_string(num) + ".png";
imwrite(left_road, leftImg);
imwrite(right_road, rightImg);
}
}
}
}
dd对应的CMakeLists.txx文件为
cmake_minimum_required( VERSION 2.8)
project(biaoding)
# set( CMAKE_CXX_FLAGS "-std=c++11 -03")
find_package(OpenCV)
include_directories(${OpenCV})
add_executable(main src/main.cpp)
target_link_libraries(main ${OpenCV_LIBS})
代码执行后,点击空格即可保存图像,大概采集50张左右。
生成棋盘格后,拿双目相机对棋盘格进行不同位姿的多次拍照采样,一般在60张左右即可(因为后期标定时需要舍弃掉不合格的图像,因此越多素材越好)。分别将左目和右目的图像存在两个文件夹中。图像如下:
左目图:
右目图:
二、matlab标定工具箱
1、打开标定工具箱
在命令行输入stereoCameraCalibrator,出现如下界面:
将上面的“Skew”、“Tangential Distortion”以及“3 Coefficients”等选项选上,将“2 Coefficients”选项去掉,如下:
2、载入图像
点击添加图像
出现如下界面:
Camera1代表左摄像头,Camera2代表右摄像头,分别选择存放着左右图像的文件夹,需要特别注意的是棋盘格的边长应该根据打印的实际大小填写,单位可以选择,然后点击OK,程序会自动检测采集的图像到底有多少可以使用,可以说MATLAB2015的这个工具十分挑剔,如果角度不好的话,将使用不了,因此在采集图像时,最好多的采集一些。
3.标定
点击
按钮,开始标定:
左下方的直方图为左右图像的标定误差,点击误差较大的直方图,可以直接在左边的图像对中找到对应的图像,右键选择“Remove and Recalibrate”,可以重复上述步骤,直到认为误差满足标定需求为止。一般Overall Mean Error小于0.3就可以了。
4、导出参数
点击
在这里插入图片描述选择Export camera parameters,并点击“OK”。
在这里插入图片描述
三、读取参数
标定结束后,会得到如下标定参数:
TranslationOfCamera2:相机2相对于相机1的偏移矩阵,可以直接使用。
RotationOfCamera2:相机2相对于相机1的旋转矩阵,需要转置之后才能使用。
CameraParameters1与CameraParameters2为左右摄像头的单独标定参数。CameraParameters1与CameraParameters2中包含如下文件:
IntrinsicMatrix存放的是摄像头的内参,只与摄像机的内部结构有关,需要先转置再使用。
RadialDistortion:径向畸变,摄像头由于光学透镜的特性使得成像存在着径向畸变,可由K1,K2,K3确定。
TangentialDistortion:切向畸变,由于装配方面的误差,传感器与光学镜头之间并非完全平行,因此成像存在切向畸变,可由两个参数P1,P2确定。