双目相机图像校正(五)

本文来自公众号:机器人视觉

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
公众号:机器人视觉

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值