OpenCV使用标定图

本文由 @lonelyrains 出品,转载请注明出处。 
文章链接: http://blog.csdn.net/lonelyrains/article/details/46915705


上一步生成标定图参考上一篇文章 OpenCV生成标定图

在生成标定图之后,需要用A4纸打印下来,才能拿到摄像头下面摆弄。


笔者使用的是imagelist图片列表的方式使用标定图,即先用摄像头拍一部分图片,然后再由下面说的校准工程校准得到畸变参数——主要原因是还没有搞清楚怎么实时获取这个摄像头(海康威视)的视频流,目前都是通过http从浏览器上登录访问——OpenCV的校准示例本身是支持基于标定板视频流的实时校准的。


生成OpenCV识别的标定图列表的工程:opencv248\sources\samples\cpp\imagelist_creator.cpp。 使用命令示例:imagelist_creator imagelist.yaml *.png。得到imagelist.yaml如下:

<?xml version="1.0"?>
<opencv_storage>
<images>
  "1.png" "2.png" "3.png" "4.png" "5.png" "6.png" "7.png" "8.png"</images>
</opencv_storage>

使用标定图的校准工程,参考OpenCV示例工程:opencv248\sources\samples\cpp\calibration.cpp。使用命令示例:calibration  -w 9 -h 6 -pt chessboard -o camera.yaml -op -oe -su imagelist.xml。得到camera.yaml其中最关键的是摄像机内参数矩阵、畸变参数矩阵:

%YAML:1.0
calibration_time: "07/16/15 14:58:18"
camera_matrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 5.5977614554147385e+002, 0., 4.3513787505786939e+002, 0.,
       4.1717385931117281e+002, 2.3329672151206768e+002, 0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ -4.0702020878986456e-001, 2.5025002728793899e-001,
       -3.7768192568471098e-003, -9.1190914257643463e-004,
       -1.0546751146845158e-001 ]

庆幸的是calibration.cpp中已经包含了如何对一张畸变图片进行校准。整理出关键代码为:

#include <time.h>

void loadCameraParams(Mat &cameraMatrix, Mat &distCoeffs)
{
	FileStorage fs( "camera.yaml", FileStorage::READ);

    fs ["camera_matrix"] >> cameraMatrix;
    fs ["distortion_coefficients"] >> distCoeffs;
}

Mat calibrator(Mat &view)
{
	vector<string> imageList;
	static bool bLoadCameraParams = false;
	static Mat cameraMatrix, distCoeffs, map1, map2;
	Mat rview;
	Size imageSize,newImageSize;

	if(!view.data)
		return Mat();

	imageSize.width = view.cols;
	imageSize.height = view.rows;

	newImageSize.width = imageSize.width;
	newImageSize.height = imageSize.height;

	if(bLoadCameraParams == false)
	{
		loadCameraParams(cameraMatrix, distCoeffs);
		bLoadCameraParams = true;
		initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
		getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, newImageSize, 0), newImageSize, CV_16SC2, map1, map2);
	}
	
	//undistort( view, rview, cameraMatrix, distCoeffs, cameraMatrix );
	remap(view, rview, map1, map2, INTER_LINEAR);

	//imshow("Image View", rview);
	//int c = 0xff & waitKey();

	rview.copyTo(view);

	return view;
}


途中遇到的问题和解决步骤:

1、使用摄像头拍完标定图片,使用,发现调用过程中崩溃。即对着摄像头照了的很多张图片,依然未找到一张能正确识别棋盘的。

2、使用OpenCV自带的图片opencv248\sources\samples\cpp\leftXX.jpg,转成png,成功执行。在识别到的棋盘中描出了角点。

3、为了减小问题出现的因素,尽量控制单一变量,使用行列同leftXX.jpg相同的标定板图片:宽9个小方格、高6个小方格。仍然不能识别。

4、怀疑是摄像头的畸变太严重,导致图片识别不了,就用手机摄像头试了一下。因为手机摄像头的畸变非常小,基本可以忽略。结果虽然也不能识别。但是将手机对着显示器拍照拍得的原始图片对着leftXX.jpg使用灰色边框,结果可以识别了!

5、再用摄像头拍的图片,使用灰色边框,发现仍然识别不了。如果摄像头畸变太严重导致识别不了,貌似也不太合情理,因为都是数字游戏呀。方格应该可以比较好识别吧。畸变看起来也不是比leftXX.jpg大太多。剩下的只能怀疑是打印纸的黑方格的黑色不明显,用毛笔涂黑(也是醉了)。

6、最后终于可以识别一部分图片了!也算大功告成吧。顺便鄙视一把国内打印店的打印机质量,黑方格颜色太浅,咋leftXX.jpg外国打印机就打得那么神颜色。


原始畸变图片、校准工具描了角点的畸变图片和校正图片,取了同一张,分别如下:





增加了命令行的批处理文件,标定校准工具、图片打包下载链接:http://download.csdn.net/detail/lonelyrains/8906705


已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页