1、读取左右相机图像,使用Opencv和MATLAB标定结果对图像进行校正
//对焊缝图像进行校准
//load image
Mat img_left = imread("leftimage.bmp");
if (img_left.empty())
cout << "empty" << endl;
Mat img_right = imread("rightimage.bmp");
if (img_left.empty())
cout << "empty" << endl;
//相机标定
//相机参数
cv::Mat cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, R, T;
cam2intrinsics = (cv::Mat_<double>(3, 3) <<
3069.2482, -0.8951, 620.5357,
0, 3069.2450, 532.7122,
0, 0, 1
);
//cam2intrinsics = cam1intrinsics.t();
cam2distCoeffs = (cv::Mat_<double>(5, 1) << -0.0593, 3.4501, 0.0003, -8.5614, 0);
cam1intrinsics = (cv::Mat_<double>(3, 3) <<
3061.6936, -0.8869, 641.3042,
0, 3058.8751, 508.9555,
0, 0, 1
);
//cam1intrinsics = cam2intrinsics.t();
cam1distCoeffs = (cv::Mat_<double>(5, 1) << -0.0133, 0.6503, 0.0029, -0.0049, 0);
//cv::Mat Rx;
R = (cv::Mat_<double>(3, 3) << 0.9989, 0.0131, -0.0439,
-0.0121, 0.9996, 0.0233,
0.0441, -0.0228, 0.9987);
T = (cv::Mat_<double>(3, 1) << -73.8389, 2.6712, 3.3792);
const int imageWidth = 1292; //摄像头的分辨率
const int imageHeight = 964;
Size imagesSize = Size(imageWidth, imageHeight);
//rectify
cv::Mat R1, R2, P1, P2, Q;
Rect validRoi[2];
stereoRectify(cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q,
CALIB_ZERO_DISPARITY, -1, Size(imageWidth, imageHeight), &validRoi[0], &validRoi[1]);
Mat map1x, map1y, map2x, map2y;
initUndistortRectifyMap(cam1intrinsics, cam1distCoeffs, R1, P1, imagesSize, CV_32FC1, map1x, map1y);
initUndistortRectifyMap(cam2intrinsics, cam2distCoeffs, R2, P2, imagesSize, CV_32FC1, map2x, map2y);
remap(img_left, img_left, map1x, map1y, INTER_LINEAR);//重点!!!!!
remap(img_right, img_right, map2x, map2y, INTER_LINEAR);
//draw line
int i = 0;
while (i + 35 < img_left.rows)
{
i += 35;
for (int j = 0; j < img_left.cols; j++)
{
img_left.ptr<Vec3b>(i)[j][0] = 255;
img_right.ptr<Vec3b>(i)[j][0] = 255;
img_left.ptr<Vec3b>(i)[j][1] = 255;
img_right.ptr<Vec3b>(i)[j][1] = 255;
img_left.ptr<Vec3b>(i)[j][2] = 255;
img_right.ptr<Vec3b>(i)[j][2] = 255;
}
}
//imwrite("img_left1.bmp", img_left);//left image
imshow("img_left", img_left);//left image
//imwrite("img_right1.bmp", img_right);//left image
imshow("img_right", img_right);//right image
waitKey(100000);
system("pause");
程序new
//对图像进行校准
//load image
Mat img_left = imread("leftimage1.bmp",0);
if (img_left.empty())
cout << "empty" << endl;
Mat img_right = imread("rightimage1.bmp",0);
if (img_left.empty())
cout << "empty" << endl;
//相机标定
//相机参数
cv::Mat cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, R, T;
cam2intrinsics = (cv::Mat_<double>(3, 3) <<
3093.80948089389, 0, 635.282959025333,
0, 3093.31859709039, 538.353641774543,
0, 0, 1
);
//cam2intrinsics = cam1intrinsics.t();
cam2distCoeffs = (cv::Mat_<double>(5, 1) << -0.0136408529341437,0.410972366786061,0.00141152267600137,0.00156479081987528,0);
cam1intrinsics = (cv::Mat_<double>(3, 3) <<
3090.19954941876,0, 645.459991284445,
0, 3087.46040317723, 499.199553083610,
0, 0, 1
);
//cam1intrinsics = cam2intrinsics.t();
cam1distCoeffs = (cv::Mat_<double>(5, 1) << 0.00709414207541548, -0.621034720332236, 0.00181213959853048,-0.00445584443364885,0);
//cv::Mat Rx;
R = (cv::Mat_<double>(3, 3) << 0.998813476711113,0.0130140387339405,-0.0469283873161040,
-0.0121882898770942,0.999766574040534,0.0178393671727963,
0.0471495952276442,-0.0172462235601136,0.998738946593545);
T = (cv::Mat_<double>(3, 1) << -73.8737526477805,2.83165895481716,2.37441573307819);
const int imageWidth = 1292; //摄像头的分辨率
const int imageHeight = 964;
Size imagesSize = Size(imageWidth, imageHeight);
cout<<"imagesSize"<<imagesSize<<endl;
cv::Mat R1, R2, P1, P2, Q;
Rect validRoi[2];
stereoRectify(cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q,
CALIB_ZERO_DISPARITY, -1, Size(imageWidth, imageHeight), &validRoi[0], &validRoi[1]);
Mat map1x, map1y, map2x, map2y;
initUndistortRectifyMap(cam1intrinsics, cam1distCoeffs, R1, P1, imagesSize, CV_32FC1, map1x, map1y);
initUndistortRectifyMap(cam2intrinsics, cam2distCoeffs, R2, P2, imagesSize, CV_32FC1, map2x, map2y);
remap(img_left, img_left, map1x, map1y, INTER_LINEAR);//重点!!!!!
remap(img_right, img_right, map2x, map2y, INTER_LINEAR);
imwrite("img_left1.bmp", img_left);//left image
imshow("img_left", img_left);//left image
imwrite("img_right1.bmp", img_right);//left image
imshow("img_right", img_right);//right image
// 显示在一幅图像上
Mat Imgshow(img_left.rows,2*img_left.cols,CV_8UC1,Scalar(0));
img_left.copyTo(Imgshow.colRange(0,img_left.cols));
img_right.copyTo(Imgshow.colRange(img_left.cols,2*img_left.cols));
cvtColor(Imgshow,Imgshow,CV_GRAY2BGR);
// 等间距画线
for(int i=0;i<Imgshow.cols;i+=20)
line(Imgshow,Point(0,i),Point(Imgshow.cols-1,i),Scalar(0,255,0));
imshow("Contrast",Imgshow);
waitKey();
imwrite("steroVision.jpg",Imgshow);
2、读取标定板图像,对图像进行校正
// TestCamera1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char spath;
Mat Im_src;
Size boardsize(9,6);
vector<vector<Point3f>> Objectpoint; // 世界坐标系
vector<vector<Point2f>> Imagepoint_l; // 像素坐标系
vector<vector<Point2f>> Imagepoint_r;
vector<Point3f> Objcorner; // 世界坐标系
vector<Point2f> Imgcorner; // 像素坐标系
int i,j;
// 检测角点(试验)
/* bool findresult=findChessboardCorners(Im_src, boardsize, Imgcorner, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE);
if(findresult)
{
cornerSubPix(Im_src, Imgcorner, Size(11, 11), Size(-1, -1),TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
drawChessboardCorners(Im_src, boardsize, Mat(Imgcorner), findresult);
//cout<<Imgcorner<<endl;
namedWindow("Dst");
imshow("Dst",Im_src);
waitKey();
}
else
{
cout<<"Failed!"<<endl;
return -1;
}*/
// 检测角点(文件列表)
// 左图
std::vector<std::string> filelist;
vector<Mat> Imgsrc_l; // 左图象列表
char str[100];
Imgcorner.swap(vector<Point2f>()); // 清空原内容
for(i=1;i<15;i++) // 列表赋值
{
if(i==10)
continue;
sprintf(str,"C:\\Users\\Administrator\\Desktop\\谷歌浏览器下载\\TestCamera1\\TestCamera1\\image2\\left%02d.jpg",i);
filelist.push_back(str);
}
// 打开、检测
for(i=0;i<boardsize.height;i++)
for(j=0;j<boardsize.width;j++)
Objcorner.push_back(Point3f(25.0*i,25.0*j,0.0)); // 高前宽后
for(i=0;i<filelist.size();i++)
{
Im_src=imread(filelist[i],0); // 不加就读成CV_8UC4
//Mat src;
//cvtColor(Im_src,src,CV_GRAY2RGB);
Imgsrc_l.push_back(Im_src);
bool findresult=findChessboardCorners(Im_src,boardsize,Imgcorner);
cornerSubPix(Im_src, Imgcorner, Size(11, 11), Size(-1, -1),TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
if(Imgcorner.size()==boardsize.area()) // 若检测到的点数吻合,添加到列表中。
{
cout<<filelist[i]<<" succeed!"<<endl;
Objectpoint.push_back(Objcorner);
Imagepoint_l.push_back(Imgcorner);
}
}
// 标定参数
Mat cameraMatrix_l,cameraMatrix_r; // 相机矩阵
Mat distCoeffs_l,distCoeffs_r; // 畸变矩阵
vector<Mat> rvecs,tvecs; // 旋转和平移
calibrateCamera(Objectpoint,Imagepoint_l,Im_src.size(),cameraMatrix_l,distCoeffs_l,rvecs,tvecs);
cout<<"cameraMatrix:"<<endl<<cameraMatrix_l<<endl;
cout<<"distCoeffs:"<<endl<<distCoeffs_l<<endl;
for(i=0;i<rvecs.size();i++)
cout<<"rvecs:"<<endl<<rvecs[i]<<endl;
for(i=0;i<tvecs.size();i++)
cout<<"tvecs:"<<endl<<tvecs[i]<<endl;
// 矫正畸变
/* Mat undistl,undistr,map1,map2;
initUndistortRectifyMap(cameraMatrix_l,distCoeffs_l,Mat(),Mat(),Im_src.size(),CV_32FC1,map1,map2);
remap(Imgsrc_l[0],undistl,map1,map2,INTER_LINEAR);
imshow("Undistort_l",undistl); // 显示矫正的图像
waitKey();*/
// 右图
vector<Mat> Imgsrc_r; // 右图象列表
for(i=1;i<15;i++) // 列表赋值
{
if(i==10)
continue;
sprintf(str,"C:\\Users\\Administrator\\Desktop\\谷歌浏览器下载\\TestCamera1\\TestCamera1\\image2\\right%02d.jpg",i);
Im_src=imread(str,0);
//Mat src;
//cvtColor(Im_src,src,CV_GRAY2RGB);
Imgsrc_r.push_back(Im_src);
bool findresult=findChessboardCorners(Im_src,boardsize,Imgcorner);
cornerSubPix(Im_src, Imgcorner, Size(11, 11), Size(-1, -1),TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
if(Imgcorner.size()==boardsize.area()) // 若检测到的点数吻合,添加到列表中。
{
cout<<str<<" succeed!"<<endl;
Imagepoint_r.push_back(Imgcorner);
}
}
rvecs.swap(vector<Mat>());
tvecs.swap(vector<Mat>());
calibrateCamera(Objectpoint,Imagepoint_r,Im_src.size(),cameraMatrix_r,distCoeffs_r,rvecs,tvecs);
cout<<"cameraMatrix:"<<endl<<cameraMatrix_r<<endl;
cout<<"distCoeffs:"<<endl<<distCoeffs_r<<endl;
for(i=0;i<rvecs.size();i++)
cout<<"rvecs:"<<endl<<rvecs[i]<<endl;
for(i=0;i<tvecs.size();i++)
cout<<"tvecs:"<<endl<<tvecs[i]<<endl;
/* initUndistortRectifyMap(cameraMatrix_r,distCoeffs_r,Mat(),getOptimalNewCameraMatrix(cameraMatrix_r,distCoeffs_r,Im_src.size(),1),Im_src.size(),CV_32FC1,map1,map2);
imwrite("map1.bmp",map1);
remap(Imgsrc_r[0],undistr,map1,map2,INTER_LINEAR);
imshow("Undistort_r",undistr); // 显示矫正的图像
waitKey();*/
// 双目标定
Mat rotation,translation,essential,foundation;
stereoCalibrate(Objectpoint,
Imagepoint_l,
Imagepoint_r,
cameraMatrix_l,
distCoeffs_l,
cameraMatrix_r,
distCoeffs_r,
Im_src.size(),
rotation,translation,essential,foundation,
TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 30, 1e-6),
CV_CALIB_FIX_INTRINSIC );
cout<<"Rotation:"<<endl<<rotation<<endl;
cout<<"Translation:"<<endl<<translation<<endl;
// 双目校正
Mat R1,R2,P1,P2,Q;
Rect roi1,roi2;
stereoRectify(cameraMatrix_l,distCoeffs_l,cameraMatrix_r,distCoeffs_r.t(),Im_src.size(),rotation,translation,R1,R2,P1,P2,Q,CV_CALIB_ZERO_DISPARITY,-1,Im_src.size(),&roi1,&roi2);
cout<<R1<<endl<<R2<<endl;
cout<<P1<<endl<<P2<<endl;
Mat mX1,mX2,mY1,mY2;
mX1=Mat(Im_src.size(),CV_32FC1);
mX2=Mat(Im_src.size(),CV_32FC1);
mY1=Mat(Im_src.size(),CV_32FC1);
mY2=Mat(Im_src.size(),CV_32FC1);
initUndistortRectifyMap(cameraMatrix_l,distCoeffs_l,R1,P1,Im_src.size(),CV_32FC1,mX1,mY1); // 计算无畸变的校正映射
initUndistortRectifyMap(cameraMatrix_r,distCoeffs_r,R2,P2,Im_src.size(),CV_32FC1,mX2,mY2);
//imwrite("mX1.bmp",mX1);
Mat Imgl_ste,Imgr_ste;
/*cvtColor(Imgsrc_l[0],Imgl_ste,CV_GRAY2BGR);
cvtColor(Imgsrc_r[0],Imgr_ste,CV_GRAY2BGR);*/
Imgsrc_l[4].copyTo(Imgl_ste); // 取第5幅试验
Imgsrc_r[4].copyTo(Imgr_ste);
imshow("Before L",Imgl_ste);
waitKey();
imshow("Before R",Imgr_ste);
waitKey();
// 重新映射
remap(Imgl_ste,Imgl_ste,mX1,mY1,INTER_LINEAR);
remap(Imgr_ste,Imgr_ste,mX2,mY2,INTER_LINEAR);
/*imshow("stereo left",Imgl_ste);
waitKey();
imwrite("sterol.jpg",Imgl_ste);
imshow("stereo right",Imgr_ste);
waitKey();
imwrite("steror.jpg",Imgr_ste);*/
// 显示在一幅图像上
Mat Imgshow(Imgl_ste.rows,2*Imgl_ste.cols,CV_8UC1,Scalar(0));
Imgl_ste.copyTo(Imgshow.colRange(0,Imgl_ste.cols));
Imgr_ste.copyTo(Imgshow.colRange(Imgr_ste.cols,2*Imgr_ste.cols));
cvtColor(Imgshow,Imgshow,CV_GRAY2BGR);
// 等间距画线
for(i=0;i<Imgshow.cols;i+=20)
line(Imgshow,Point(0,i),Point(Imgshow.cols-1,i),Scalar(0,255,0));
imshow("Contrast",Imgshow);
waitKey();
imwrite("steroVision.jpg",Imgshow);
return 0;
}
3、使用matlab校正结果对图像直接进行校正 将matlab标定结果放在stereoParams.mat文件中
load stereoParams.mat
for i = 1:19
img1=imread(['./L',num2str(i),'.bmp']);
img2=imread(['./R',num2str(i),'.bmp']);
disp(i);
[J1,J2]=rectifyStereoImages(img1,img2,stereoParams,'OutputView','valid');
imwrite(J1,['./RL',num2str(i),'.bmp']);
imwrite(J2,['./RR',num2str(i),'.bmp']);
end
disp('Finished')
线结构光传感器标定(相机标定+结构光标定)完整流程(一) https://blog.csdn.net/qq_27353621/article/details/120787942 UR机器人手眼标定(二) https://blog.csdn.net/qq_27353621/article/details/121603215 双目相机标定(三) https://blog.csdn.net/qq_27353621/article/details/121031972 双目相机下目标三维坐标计算(四) https://blog.csdn.net/qq_27353621/article/details/121744002
|