opencv相机标定

opencv相机标定

#include<opencv2/opencv.hpp>

//返回一张图片的角点坐标
std::vector<cv::Point2f> myFindCorners(int rows, int cols, cv::Mat mat);
//获得图片的角点集
std::vector<std::vector<cv::Point2f>> getImagePoints(std::vector<cv::Mat> mat_vec);
//获得图片
std::vector<cv::Mat> getMatVector(std::string filePath = "");

//获取世界坐标系坐标
std::vector<std::vector<cv::Point3f>> getObjectPoints(cv::Size board_size,cv::Size square_size) {

	std::vector<std::vector<cv::Point3f>> objectPoints;
	
	for (int t = 0; t < 4; t++)
	{
		std::vector<cv::Point3f> object_points;
		for (int i = 0; i < board_size.height; i++)
		{
			for (int j = 0; j < board_size.width; j++)
			{
				cv::Point3f realPoint;
				/* 假设标定板放在世界坐标系中z=0的平面上 */
				realPoint.x = i * square_size.width;
				realPoint.y = j * square_size.height;
				realPoint.z = 0;
				object_points.push_back(realPoint);
			}
		}
		objectPoints.push_back(object_points);
	}

	return objectPoints;
}

//相机标定
int main() {

	//标定板尺寸
	cv::Size board_size(9, 6);

	//标定格子在世界坐标系下的尺寸(mm)
	cv::Size square_size(30, 30);

	//cv::Mat mat = cv::imread("D://pic//calibration.png", CV_LOAD_IMAGE_UNCHANGED);
	cv::Mat mat = cv::imread("D://pic//calibration//cali_2.jpg",CV_LOAD_IMAGE_UNCHANGED);
	cv::Mat dst(mat.size(), mat.type());
	cv::Size imageSize(mat.cols, mat.rows);
	//cv::Mat mat = cv::imread("D://pic//GCalibData//536.230_0.000.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	//myFindCorners(9, 6, mat);

	cv::Mat cameraMatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));			// 摄像机内参数矩阵
	cv::Mat distCoeffs = cv::Mat(1, 5, CV_32FC1, cv::Scalar::all(0));			// 摄像机的5个畸变系数:k1,k2,p1,p2,k3

	std::vector<cv::Mat> rvecsMat;												// 存放所有图像的旋转向量,每一副图像的旋转向量为一个mat
	std::vector<cv::Mat> tvecsMat;												// 存放所有图像的平移向量,每一副图像的平移向量为一个mat
	
	//重投影误差
	double error = cv::calibrateCamera(getObjectPoints(board_size, square_size),
		getImagePoints(getMatVector()), 
		imageSize, cameraMatrix, distCoeffs, rvecsMat, tvecsMat, CV_CALIB_FIX_K3);
	
	std::cout << "重投影误差:" << error << std::endl << 
		"内参矩阵:" << std::endl << cameraMatrix << std::endl << 
		"畸变系数:" << distCoeffs << std::endl;

	//畸变校正
	//方法一:使用initUndistortRectifyMap和remap两个函数配合实现
	cv::Mat mapx, mapy;
	cv::Mat R = cv::Mat::eye(3, 3, CV_32F);
	//这个函数使用于计算无畸变和修正转换关系
	cv::initUndistortRectifyMap(cameraMatrix, distCoeffs, 
		R, cv::Mat(), mat.size(), CV_32FC1, mapx, mapy);
	//一幅图像中某位置的像素放置到另一个图片指定位置
	remap(mat,dst,mapx, mapy, cv::INTER_LINEAR);

	//方法二:不需要转换矩阵的方式,使用undistort函数实现
	//cv::undistort(mat, dst, cameraMatrix, distCoeffs);
	
	return 0;
}

std::vector<cv::Mat> getMatVector(std::string filePath) {

	std::vector<cv::Mat> mat_vec;

	mat_vec.push_back(cv::imread("D://pic//calibration//cali_1.jpg", CV_LOAD_IMAGE_UNCHANGED));
	mat_vec.push_back(cv::imread("D://pic//calibration//cali_2.jpg", CV_LOAD_IMAGE_UNCHANGED));
	mat_vec.push_back(cv::imread("D://pic//calibration//cali_3.jpg", CV_LOAD_IMAGE_UNCHANGED));
	mat_vec.push_back(cv::imread("D://pic//calibration//cali_4.jpg", CV_LOAD_IMAGE_UNCHANGED));

	return mat_vec;
}

std::vector<std::vector<cv::Point2f>> getImagePoints(std::vector<cv::Mat> mat_vec) {

	std::vector<std::vector<cv::Point2f>> imagePoints;

	for (std::vector<cv::Mat>::iterator it = mat_vec.begin(); it != mat_vec.end(); it++) {
		imagePoints.push_back(myFindCorners(9, 6, *it));
	}

	return imagePoints;
}

std::vector<cv::Point2f> myFindCorners(int rows, int cols, cv::Mat mat) {
	cv::Mat mat_copy = mat;
	cv::Mat gray;
	cv::cvtColor(mat_copy, gray, CV_BGRA2GRAY);

	//棋盘规格,长宽-1
	int h = rows;
	int w = cols;

	//保存角点
	std::vector<cv::Point2f> corners;
	corners.resize(gray.cols * gray.rows);
	memset(corners.data(), 0, corners.size() * sizeof(cv::Point2f));

	//使用棋盘坐标
	bool patternWasFound = cv::findChessboardCorners(gray, cv::Size(h, w),
		corners, cv::CALIB_CB_ADAPTIVE_THRESH);

	if (!patternWasFound) {
		std::cout << "获取角点失败" << std::endl;
		return cv::Mat();
	}

	//画角点
	//cv::drawChessboardCorners(mat_copy, cv::Size(h, w), corners, patternWasFound);

	//算法收敛,迭代次数或EPS
	cv::TermCriteria termCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 20, 0.1);

	//亚像素角点检测
	cv::cornerSubPix(gray, corners, cv::Size(5, 5), cv::Size(-1, -1), termCriteria);
	//将检测到的亚像素角点绘制到原图上
	//std::cout << corners.size() << std::endl;

	return corners;

	/*
	for (std::vector<cv::Point2f>::iterator it = corners.begin();
		it != corners.end(); it++)
	{
		cv::circle(mat_copy, *it, 3, cv::Scalar(0, 0, 255), 1, 8, 0);
	}
	//cv::calibrateCamera(,);
	//cv::namedWindow("corners", CV_WINDOW_AUTOSIZE);
	//cv::imshow("corners", corners);

	return mat_copy;
	*/
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值