OpenCV中的相机标定

这篇具有很好参考价值的文章主要介绍了OpenCV中的相机标定。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

      之前在https://blog.csdn.net/fengbingchun/article/details/130039337 中介绍了相机的内参和外参,这里通过OpenCV中的接口实现对内参和外参的求解。
      估计相机参数的过程称为相机标定(camera calibration)。相机标定是使用已知的真实世界模式(例如棋盘)来估计相机镜头和传感器的外在参数(旋转和平移, Rotation(R) and Translation(t), 相机相对于某些世界坐标系的方向)和内在参数(例如镜头的焦距fx,fy、光学中心cx,cy、畸变系数k1,k2,k3,p1,p2)的过程,以减少相机缺陷引起的畸变误差。
      棋盘标定是执行相机标定和估计未知参数值的常用技术。棋盘非常适合用于相机标定:
      (1).它是平坦的(flat),棋盘上的所有点都在同一平面上;
      (2).有清晰的corners和points,它们都出现在直线上,易于在图像中检测到,棋盘上的正方形角非常适合定位它们,便于将3D真实世界坐标系中的点映射到相机2D像素坐标系上的点。
      OpenCV中相机标定步骤:
      (1).使用已知大小的棋盘格定义3D点的真实世界坐标;
      (2).从多幅图像捕获棋盘格的不同视点(different viewpoints);
      (3).查找不同图像的棋盘格的2D坐标:
            查找棋盘角:findChessboardCorners
            完善棋盘角:cornerSubPix
      (4).标定相机:calibrateCamera

     以下是C++的实现:

int test_opencv_camera_calibration()
{
#ifdef _MSC_VER
	std::string path = "../../../test_images/camera_calibration/*.jpg";
#else
	std::string path = "test_images/camera_calibration/*.jpg";
#endif
	std::vector<std::string> images;
	cv::glob(path, images, false);
	if (images.size() == 0) {
		std::cout << "Error: the requested images were not found: " << path << "\n";
		return -1;
	}

	auto pos = path.find_last_of("/");
	std::string path_result = path.substr(0, pos + 1);

	auto get_image_name = [](const std::string& image) {
#ifdef _MSC_VER
		auto pos = image.find_last_of("\\");
#else
		auto pos = image.find_last_of("/");
#endif
		auto name = image.substr(pos + 1, image.size());
		return name.substr(0, name.size() - 4);
	};

	// the dimensions of checkerboard
	const int CHECKERBOARD[2] = { 11, 13 }; // rows,cols

	// the world coordinates for 3D points
	std::vector<cv::Point3f> pts_3d_world_coord;
	for (auto i = 0; i < CHECKERBOARD[1]; ++i) {
		for (auto j = 0; j < CHECKERBOARD[0]; ++j)
			pts_3d_world_coord.push_back(cv::Point3f(j, i, 0));
	}

	// vector to store the pixel coordinates of detected checker board corners 
	std::vector<cv::Point2f> pts_corners;
	cv::Mat frame, gray;
	bool success = false;

	// store vectors of 3D points for each checkerboard image
	std::vector<std::vector<cv::Point3f> > pts_3d;
	// store vectors of 2D points for each checkerboard image
	std::vector<std::vector<cv::Point2f> > pts_2d;

	for (auto i = 0; i < images.size(); ++i) {
		frame = cv::imread(images[i]);
		if (frame.empty()) {
			std::cout << "Error: fail to read image: " << images[i] << "\n";
			return -1;
		}
		cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);

		// finding checker board corners
		success = cv::findChessboardCorners(gray, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), pts_corners, cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);
		if (!success) {
			std::cout << "Error: fail to find chess board corners: " << images[i] << "\n";
			return -1;
		}

		cv::TermCriteria criteria(cv::TermCriteria::EPS | cv::TermCriteria::MAX_ITER, 30, 0.001);

		// refining pixel coordinates for given 2d points
		cv::cornerSubPix(gray, pts_corners, cv::Size(11, 11), cv::Size(-1, -1), criteria);

		// displaying the detected corner points on the checker board
		cv::drawChessboardCorners(frame, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), pts_corners, success);

		pts_3d.push_back(pts_3d_world_coord);
		pts_2d.push_back(pts_corners);

		//cv::imshow("Image", frame);
		//cv::waitKey(0);
		cv::imwrite(path_result + "result_" + get_image_name(images[i]) + ".png", frame);
	}

	cv::Mat camera_matrix, dist_coeffs, R, t;
	cv::calibrateCamera(pts_3d, pts_2d, cv::Size(gray.rows, gray.cols), camera_matrix, dist_coeffs, R, t);
	std::cout << "camera_matrix:\n" << camera_matrix << "\n"; // 3*3 matrix
	std::cout << "dist_coeffs:\n" << dist_coeffs << "\n"; // 5*1 vector
	std::cout << "R:\n" << R << "\n"; // each image, 3*1 vector
	std::cout << "t:\n" << t << "\n"; // each image, 3*1 vector

	return 0;
}

      终端输出结果如下:5幅测试图像来自于手机拍摄

OpenCV中的相机标定

      其中测试图像1.jpg角点检测结果如下所示:

OpenCV中的相机标定

      以下是参考C++实现的Python代码:

import cv2
import numpy as np
import glob
from sys import platform

def get_image_name(path):
	if platform == "win32":
		pos = path.rfind("\\")
	elif platform == "linux":
		pos = path.rfind("/")
	else:
		raise Exception(f"Error: Unsupported platform: {platform}")
	
	return path[pos+1:len(path)-4]

def camera_calibration(checkerboard_size, path):
	images = glob.glob(path)
	if len(images) == 0:
		raise Exception(f"Error: the requested images were not found: {path}")

	if platform == "win32":
		pos = images[0].rfind("\\")
	elif platform == "linux":
		pos = images[0].rfind("/")
	else:
		raise Exception(f"Error: Unsupported platform: {platform}")

	path_result = images[0][0:pos+1]

	# the world coordinates for 3D points
	pts_3d_world_coord = np.zeros((1, checkerboard_size[0] * checkerboard_size[1], 3), np.float32)
	pts_3d_world_coord[0,:,:2] = np.mgrid[0:checkerboard_size[0], 0:checkerboard_size[1]].T.reshape(-1, 2)
	#print(f"pts_3d_world_coord: {pts_3d_world_coord}")

	# store vectors of 3D points for each checkerboard image
	pts_3d = []
	# store vectors of 2D points for each checkerboard image
	pts_2d = []

	for name in images:
		frame = cv2.imread(name)
		if frame is None:
			raise Exception(f"Error: fail to read image: {frame}")

		gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
		ret, pts_corners = cv2.findChessboardCorners(gray, checkerboard_size, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
		if ret != True:
			raise Exception(f"Error: fail to find chess board corners: {name}")
		
		criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
		# refining pixel coordinates for given 2d points
		pts_corners = cv2.cornerSubPix(gray, pts_corners, (11,11), (-1,-1), criteria)

		# displaying the detected corner points on the checker board
		frame = cv2.drawChessboardCorners(frame, checkerboard_size, pts_corners, ret)

		pts_3d.append(pts_3d_world_coord)
		pts_2d.append(pts_corners)

		#cv2.imshow("Image", frame)
		#cv2.waitKey(0)
		cv2.imwrite(path_result + "result_" + get_image_name(name) + ".png", frame)

	ret, camera_matrix, dist_coeffs, R, t = cv2.calibrateCamera(pts_3d, pts_2d, gray.shape[::-1], None, None)
	print(f"Camera matrix:\n{camera_matrix}")
	print(f"dist_coeffs:\n{dist_coeffs}")
	print(f"R:\n{R}")
	print(f"t:\n{t}")

if __name__ == "__main__":
	# the dimensions of checkerboard
	CHECKERBOARD = (11, 13)
	# images path
	path = "../../test_images/camera_calibration/*.jpg"
	camera_calibration(CHECKERBOARD, path)

	print("test finish")

      终端输出结果如下:与C++一致

OpenCV中的相机标定

      GitHub:https://github.com/fengbingchun/OpenCV_Test文章来源地址https://www.toymoban.com/news/detail-418207.html

到了这里,关于OpenCV中的相机标定的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用OpenCV进行相机标定(张正友标定,有代码)

    理论部分可以参考其他博客或者视觉slam十四讲 相机标定主要是为了获得相机的内参矩阵K和畸变参数 内参矩阵K 畸变系数:径向畸变(k1,k2,k3), 切向畸变(p1,p2) 径向畸变公式 切向畸变公式 张正友标定方法能够提供一个比较好的初始解,用于后序的最优化. 这里用棋盘格进行标定,如

    2024年02月07日
    浏览(39)
  • OpenCV实战(23)——相机标定

    我们已经了解了相机如何通过在 2D 传感器平面上投射光线来拍摄 3D 场景,生成的图像准确地表示了在捕获图像的瞬间从特定视点观察场景。然而,图像形成过程消除了与其所表示场景元素的深度有关的所有信息。为了恢复场景的 3D 结构和摄像机的 3D 姿态,我们需要对相机参

    2024年02月08日
    浏览(52)
  • opencv相机标定

      当你把摄像机放在一个特定的位置,在它的后面放一个目标图像,或者是把摄像机放到某个物体上,摄像机周围的物体是什么形状,你需要知道这些信息。 当你在计算机上处理图像时,会使用以下三个参数: 1.像素坐标(pixel):像素坐标是相机中每个点的世界坐标(x,y

    2024年02月16日
    浏览(32)
  • 相机标定原理及应用(opencv)

    在机器视觉领域,相机的标定是一个关键的环节,它决定了机器视觉系统能否有效的定位,能否有效的计算目标物。相机的标定基本上可以分为两种,第一种是相机的自标定;第二种是依赖于标定参照物的标定方法。前者是相机拍摄周围物体,通过数字图像处理的方法和相关

    2024年02月22日
    浏览(38)
  • Opencv_棋盘格标定相机

    文章内容: 读取棋盘格图片进行标定 生成棋盘格图片 保存标定后的内容 棋盘格下载:https://gitee.com/liangbo1996/chessboard_27mm

    2024年01月19日
    浏览(37)
  • Python之OpenCV相机标定

    本文结合OpenCV官方样例,对官方样例中的代码进行修改,使其能够正常运行,并对自己采集的数据进行实验和讲解。 OpenCV使用棋盘格板进行标定,如下图所示。为了标定相机,我们需要输入一系列三维点和它们对应的二维图像点。在黑白相间的棋盘格上,二维图像点很容易通

    2024年02月03日
    浏览(44)
  • Opencv 相机内参标定及使用

    目录 一、功能描述 二、标定板制作 三、图像采集 四、标定内参 方法一:Matlab标定  方法二:C++程序标定 五、使用内参 1.本文用于记录通过 Opencv 进行相机内参标定和对内参的使用来进行图像畸变矫正。         1)相机矩阵:包括焦距(fx,fy),光学中心(Cx,Cy),完

    2024年01月24日
    浏览(38)
  • OpenCV相机标定全过程

    一、OpenCV标定的几个常用函数 findChessboardCorners() 棋盘格角点检测 第一个参数是输入的棋盘格图像(可以是8位单通道或三通道图像); 第二个参数是棋盘格内部的角点的行列数(注意:不是棋盘格的行列数,如棋盘格的行列数分别为4、8,而内部角点的行列数分别是3、7,因

    2024年02月04日
    浏览(46)
  • python opencv实现相机内参标定

    使用python opencv 标定相机内参。 (1)从网络上下载一张棋盘格图片,粘贴到word文档上,设定尺寸大小为合适值,作为标定板。 (2)在不同距离,不同角度下用手机相机拍摄棋盘图片。 (3)调用 opencv findChessboardCorners 和 cornerSubPix 函数提取棋盘的角点。 (4)调用 opencv cal

    2024年02月13日
    浏览(50)
  • opencv C++ 张正友相机标定

    2023年08月16日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包