Bootstrap

opencv4.0+VS2017 C++自带例程的相机标定详细过程

新入菜鸟一枚,在学习的路上刚刚起程,记录第一步。
为了省钱又想要一个像素高的摄像头,买了一个没有校正的会出现畸变的摄像头,自己校正。
参考各位前辈的博客,我总结了标定的两种方法:
(1)利用cmd+vs+自带例程cpp
(2)利用自带例程cpp+vs
个人感觉第二种简单。
开始介绍之前,我先做以下为铺垫,方便两种方法,也适合像我一样的菜鸟扫盲。

OpenCV不是软件,而是一个大的库,函数库。我们下载后会生成一个名叫:OpenCV的文件夹,之后跟VS所做的配置就是降这个库作为外部库和VS链接到一起,方便我们调用。
我们在vs里开始都要先建立一个项目,在这个项目下再添加项,开始我们的编程。我采用的是c++语言,可参考这个网站扫盲:http://www.weixueyuan.net/cpp/rumen/1/。
编程最开始写的例如:#include“opencv2/opencv.hpp”,就是对头文件内部的函数进行调用,每当我们写一个,头文件里就会出现相应的头文件。

接下来开始说OpenCV这个文件夹,我们依次打开文件夹“OpenCV/sources/samples/cpp”,这里边的内容就是今天我们要用到的。

第一种方法

参考文章:https://blog.csdn.net/mars_xiaolei/article/details/88845836
https://blog.csdn.net/yibeiyese/article/details/80636203
在“OpenCV/sources/samples/cpp”下我们要用到的cpp为“imagelist_creator.cpp”、“calibration.cpp”,一个用来给照片生成列表的,第二个是标定的源码。

1获取用于标定的照片

要给摄像头校正就要知道摄像头的内部外部参数,这些参数影响了成像效果,具体什么参数,可看书《学习OpenCV》或者自己查。
标定的过程就是得出这些参数,并输出一个类似格式的文件“**.xml”,这个文件包含相关的参数。标定需要标定板,标定板有多种,我采用的是棋牌的(chessboard)还有圆点(circles)等。
获取图片就是用摄像头从各个角度拍到标定板,方便获得平移和扭转的变化量。我们可以自己拍,我是自己拍的,他们说也可以利用例程提供的,但我没用,我觉得不能反映出我摄像头的对图像的畸变程度。例程提供照片“opencv\sources\samples\data”,也包括标定板在内。我使用的是自己拍的照片,直接在显示屏上拍的,如下:
我的图片
红色是拍摄时光线的问题,不是故意调的,我这是彩色图,图片数目要多,不能少,要排序方便后边操作。

2生成照片列表(.xml格式,例bbbbbb.xml)

在vs中新建项目(项目的文件地址确定好,名字自己定,比如:A),添加项,添加现有项找到我们刚说的“imagelist_creator.cpp”,编译运行,然后在项目文件夹里找到A.exe运行程序.。
在开始菜单下的搜索框里输入:cmd 回车。这时候弹出的界面里,提示符前边是C盘,然而我们工作的路径一般不是C盘。我们更改到我们使用的文件夹,也方便我们能知道生成的文件在哪里。这一步主要是生成列表文件,路径更改方式,提示符处输入,例如:
cd E:\opencv_test\imagelist 回车
这时还是C盘后提示符,接着输入:
E: 回车
接着就变成了:“E:\opencv_test\imagelist | ”这样的,说明路径更改过来了。
接着输入:
A.exe bbbbbb.xml p(1).jpg ………………p(15).jpg 回车 //每一项中间有空格
就可以得到一个bbbbbb.xml文件,用记事本打开,然后把图片信息补全,想我的这样:
图二

3编译标定源码

我们仍然需要的是生成的.exe文件,所以建项目自己随意,怎么方便怎么来。添加项,现有项,找到“calibration.cpp”,在编译之前需要在程序最顶端,添加:
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
可以试着不添加,一般会报错。
编译完会生成一个.exe文件,假如名为c.exe

4标定

调出cmd,方法同上。路径调整到c.exe 所在的文件夹,把bbbbbb.xml也拖到这个文件夹,图片就不用了,因为,刚才在xml文件里已经定义了图片的地址。
在调整路径后的命令提示符处开始输入:
c.exe -w=9 -h=6 -tp=chessboard -o=cccccc.xml -op -oe -su bbbbbb.xml 回车
得到一个相机参数文件,用于校正,cccccc.xml文件
以上参数定义和数值适用于我说到的标定板,其他的标定板,需要更改,更改方式,参考我提到的两篇文章。

第二种方法

简单很多
参考文章:https://blog.csdn.net/u013498583/article/details/71404323
https://blog.csdn.net/Li_haiyu/article/details/82782400

1打开OpenCV文件夹

按路径“opencv\sources\samples\cpp\tutorial_code\calib3d\camera_calibration”打开,可以看到这么几个文件:
在这里插入图片描述
第一个文件:标定源码
第二个文件:标定时标定板相关的参数(需要更改)
第三个文件:是我们要得到的文件(上一种方法里的cccccc.xml文件)
第四个文件:图片列表文件(上一种方法里的bbbbbb.xml文件)

2在VS中修改文件

在VS中新建项目,新建项,现有项,将“camera_calibration.cpp”、“VID5”和“in_VID5”文件都打开。
(1)“VID5”
将图片格式和路径改成自己准备的图片路径和格式:
在这里插入图片描述
(2)“in_VID5”
第19句,将路径改为你所保存的“VID5”的路径:
在这里插入图片描述
将第27句中间的数字该为你准备的图片数字,有多少张图,写多少:
在这里插入图片描述
(3)“camera_calibration.cpp”
在最前边加上:
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
然后在主函数部分找到这么一句话,如图中的277句话,原来是:
const string inputSettingsFile = parser.get(0);
改为:
const string inputSettingsFile =argc > 1 ? argv[1] : “E:/OPEN_TEST/XJBD/camera_calibration/in_VID5.xml”;
“E:/OPEN_TEST/XJBD/camera_calibration/in_VID5.xml”是你保存的“in_VID5.xml”的地址。
在这里插入图片描述

3编译cpp文件

编译后就得到我们需要的相机参数文件。

最后是校正,就简单很多。

参看:https://blog.csdn.net/Li_haiyu/article/details/82782400
https://blog.csdn.net/u013498583/article/details/71404323

补充

参看:https://blog.csdn.net/qq_35239859/article/details/86151058

前两个文章主要是调用图片进行校正,个人觉得没有意义,第三个使用直接摄像头读取图片,给了两种方法。

我自己写了一个,写完之后发现了问题,找到第三个。是因为我发现校正后的畸变程度更加严重,不知哪儿有问题,继续学习中。https://blog.csdn.net/qq_35239859/article/details/86151058 这个文章中有个命令的作用我贴出来。
在这里插入图片描述
直接用这个程序,读出来的图像时左右翻转,也就是镜像的,所以解释一下,我把它去了。
我是这样写的:

#include <opencv2/opencv.hpp>
#include <opencv2/calib3d/calib3d.hpp>
using namespace std;
using namespace cv;


int main(int argc, char** argv)
{

	cv::VideoCapture cap;
	cap.open(0);
	if (!cap.isOpened())
		return 0;
	/// 从摄像头读取图像
	cv::Mat src;
	for (;;)
	{
		cap >> src;
		//imshow("1", src);
		Mat distortion = src.clone();
		//imshow("2", distortion);
		Mat camera_matrix = Mat(3, 3, CV_32FC1);
		Mat distortion_coefficients;


		//导入相机内参和畸变系数矩阵
		FileStorage file_storage("E:/OPEN_TEST/Project_cup/out_camera_data.xml", FileStorage::READ);
		file_storage["camera_matrix"] >> camera_matrix;
		cout << camera_matrix << endl;
		file_storage["distortion_coefficients"] >> distortion_coefficients;
		cout << distortion_coefficients << endl;
		file_storage.release();

		//矫正
		undistort(src, distortion, camera_matrix, distortion_coefficients);
		if (src.empty()) break;
		if (cv::waitKey(15) >= 0) break;  //这一句一定要有,不然会死循环,不显示图像
		imshow("img", src);
		imshow("undistort", distortion);
	}
	waitKey(0);
	cap.release();
	cv::destroyAllWindows();
}

最后就是我存在的问题,校正后为什么还变差了,扭曲更严重,有知道的请指教
在这里插入图片描述

;