OpenCV之相机畸变矫正

opencv 4.4

vs2017

代码是借用人家的,具体哪篇也忘了~

程序运行后按Y键持续检测角点直到输出

角点找不到的原因分析 这里设置标定板的角点数错误,行列应该设置为你标定板最大格数-1,我的标定板是7行10列这里就设置(6,9)

另外还有可能标定板离的太近

Size patternsize = Size(6,9); /* 标定板上每行、列的角点数 */

另外个容易出问题的地方在这里 COLOR_RGB2GRAY,由于opencv版本的变化这里可能会报错,老的版本可能是cv::CV_RGB2GRAY,主体意思就是把传进来的图片变成灰度图

cvtColor(imageInput, gray, COLOR_RGB2GRAY);

 

#include "pch.h"
#include 
#include 
#include "opencv2/opencv_modules.hpp"
#include 
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include 
#include "opencv2/stitching/detail/autocalib.hpp"
#include "opencv2/stitching/detail/blenders.hpp"
#include "opencv2/stitching/detail/timelapsers.hpp"
#include "opencv2/stitching/detail/camera.hpp"
#include "opencv2/stitching/detail/exposure_compensate.hpp"
#include "opencv2/stitching/detail/matchers.hpp"
#include "opencv2/stitching/detail/motion_estimators.hpp"
#include "opencv2/stitching/detail/seam_finders.hpp"
#include "opencv2/stitching/detail/warpers.hpp"
#include "opencv2/stitching/warpers.hpp"
#include "opencv2/xfeatures2d.hpp"

#include 
#include 
#include 
using namespace std;
using namespace cv;
using namespace cuda;


using namespace cv;
using namespace std;


int main() {
	int image_count = 1;          /* 图像数量 */
	Size image_size;               /* 图像的尺寸 */
	Size patternsize = Size(6,9); /* 标定板上每行、列的角点数 */

	vector> corner_all; /* 保存检测到的所有角点 */

	VideoCapture capture;
	
	capture.open(0);


	// 原图像
	Mat imageInput;// = imread("F://fisheye.png");

	for (int i = 0; i < image_count;)
	{
		capture >> imageInput;

		if (imageInput.empty())
		{
			cout << "empty image!!!\n";
			return 0;
		}

		imshow("src", imageInput);

		// 只是为了获得键盘而已
		switch (waitKey(10))
		{
		case 'q':
			return 0;
			break;
		case 'y':
			break;
		default:
			continue;
			break;
		}

		i++;
		// 用于观察检验输出
		printf("第%d张图片\t", i);

		if (i == 1) //读入第一张图片时获取图像宽高信息
		{
			// 列宽,行高
			image_size.width = imageInput.cols;
			image_size.height = imageInput.rows;
			cout << "image_size.width = " << image_size.width << endl;
			cout << "image_size.height = " << image_size.height << endl;
		}

		Mat gray;
		cvtColor(imageInput, gray, COLOR_RGB2GRAY);
		vector corner_single; /* 缓存每幅图像上检测到的角点 */

		/* 提取角点 */
		bool patternfound = findChessboardCornersSB(gray, patternsize, corner_single); //findChessboardCorners(gray, patternsize, corner_single);
		// 如果找到了
		if (patternfound)
		{
			/* 亚像素精确化 */
			TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER , 100, 0.101);
			cornerSubPix(gray, corner_single, Size(10, 10), Size(-1, -1), criteria);
			corner_all.push_back(corner_single); //保存亚像素角点

			/* 在图像上显示角点位置 */
			drawChessboardCorners(gray, patternsize, corner_single, patternfound); //用于在图片中标记角点
			imshow("drawChessboardCorners", gray);                                 //显示图片
		}
		else
		{
			cout << "can not find chessboard corners!\n"; //找不到角点
			i--;
			continue;
		}

		cout << "\n******************\n";
	}

	int total = corner_all.size();
	cout << "已收集的棋盘图个数:" << total << endl;

	/***************************** 以下是摄像机标定 ************************************************/
	cout << "\n[开始标定]>>>>>>\n";

	Size square_size = Size(10, 10); /* 实际测量得到的标定板上每个棋盘格的大小 */

	/* calibrateCamera的参数 */
	vector> object_points; /* 保存标定板上角点的三维坐标 */
	// imagePoints
	// imageSize上面已经获得
	Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 摄像机内参数矩阵 */
	Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));   /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */
	vector rvecs;                                      /* 每幅图像的旋转向量 */
	vector tvecs;                                      /* 每幅图像的平移向量 */

	/* 初始化标定板上角点的三维坐标 */
	for (int count = 0; count < image_count; count++)
	{
		vector single_object_points;
		// 每列
		for (int i = 0; i < patternsize.height; i++)
		{
			// 每行
			for (int j = 0; j < patternsize.width; j++)
			{
				Point3f realPoint;
				/* 假设标定板放在世界坐标系中z=0的平面上 */
				realPoint.x = i * square_size.width;
				realPoint.y = j * square_size.height;
				realPoint.z = 0;
				single_object_points.push_back(realPoint);
			}
		}
		object_points.push_back(single_object_points);
	}

	calibrateCamera(object_points, corner_all, image_size, cameraMatrix, distCoeffs, rvecs, tvecs);
	cout << "[标定完成]\n";

	/*********************************** 对标定结果进行评价 **********************************************/
	cout << "\n[开始评价标定结果]>>>>>>\n";
	//每张图片上总的角点数
	int cornerNum = patternsize.width * patternsize.height;
	double err_single = 0.0; /* 每幅图像的误差 */
	double err_total = 0.0;  /* 所有图像的误差的总和 */
	double err_mean = 0.0;   /* 所有图像的平均误差 */

	vector imagePoints2; /* 保存重新计算得到的投影点 */

	for (int i = 0; i < image_count; i++)
	{
		/* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
		projectPoints(object_points[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);

		/* 计算新的投影点和旧的投影点之间的误差*/
		// 每张图像的角点
		vector corner_single = corner_all[i];
		// 声明原结果的角点矩阵
		Mat mat_corner_single = Mat(1, corner_single.size(), CV_32FC2);
		// 声明评测结果的角点矩阵
		Mat mat_imagePoints2 = Mat(1, imagePoints2.size(), CV_32FC2);
		// 每个角点
		for (int j = 0; j < corner_single.size(); j++)
		{
			// 给原结果的角点矩阵赋值
			mat_corner_single.at(0, j) = Vec2f(corner_single[j].x, corner_single[j].y);
			// 给评测结果的角点矩阵赋值
			mat_imagePoints2.at(0, j) = Vec2f(imagePoints2[j].x, imagePoints2[j].y);
		}

		// 取2范数
		err_single = norm(mat_imagePoints2, mat_corner_single, NORM_L2);

		err_total += err_single;
	}

	// 平均误差
	err_mean = err_total / cornerNum;

	cout << "[总体平均误差]:" << err_mean << "像素" << endl;
	cout << "[评价完成!]" << endl;

	cout << "cameraMatrix:\n"
		<< cameraMatrix << endl;
	cout << "distCoeffs:\n"
		<< distCoeffs << endl;

	/************************ 显示定标结果 ******************************/
	cout << "[矫正图像]>>>>>>" << endl;
	Mat result;

	undistort(imageInput, result, cameraMatrix, distCoeffs);
	imshow("result", result);
	waitKey();
	return 0;
}

 运行结果:

控制台输出结果图

OpenCV之相机畸变矫正_第1张图片

相机原始图像

 OpenCV之相机畸变矫正_第2张图片

 灰度后取角点并画出

OpenCV之相机畸变矫正_第3张图片

输出结果信息

OpenCV之相机畸变矫正_第4张图片

 

实际看到的输出结果还是畸变的 这里要再看了,代码只是验证大致矫正流程

另外是了下海康的鱼眼相机,也是可以的 效果emmmmm一般般 还有很多改进的地方

你可能感兴趣的:(OpenCV,opencv,计算机视觉)