OpenCV使用标定图

本文由 @lonelyrains 出品,转载请注明出处。

文章链接: http://blog.csdn.net/lonelyrains/article/details/46915705

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

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

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

生成OpenCV识别的标定图列表的project: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>

使用标定图的校准project,參考OpenCV演示样例project: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

时间: 2024-10-15 11:01:26

OpenCV使用标定图的相关文章

OpenCV生成标定图

网上查了一下工业视觉标定板,少则几百大洋,多则几千大洋,就想在A4纸上山寨打印一个标定图,就是黑白方格相间的那种.A4纸的标准大小为210*297mm.搞了个把小时,其实想明白了之后很简单.从每个像素的角度考虑,考虑其最终落入哪个小方块,如果落入小方块的行列之和为奇数,则设置为白色.可以作为简单的上机面试题呀.首先准备一张跟A4纸比例相同的纯黑图片,3A4.bmp,可以用电脑自带的画图生成.然后该设置为白的地方设置为白就行了.代码如下 #include <opencv\cv.h> #inclu

opencv二值图反色处理

反色处理指的是:如果原先图像的背景是白色,而目标是黑色的话:经过反色处理后,背景变为白色,目标变为黑色. 在opencv中,对于二值图的反色处理有两种方法: 之前处理好的二值图的定义为:Mat  binaryImg; 1.直接使用opencv中的函数: //! inverts each bit of array (dst = ~src) CV_EXPORTS_W void bitwise_not(InputArray src, OutputArray dst, InputArray mask=n

基于OpenCV立体视觉标定和校正

这几天学习双目视觉标定,分别使用了两种工具:OpenCV和Matlab.Matlab的效果非常稳定,但是一开始OpenCV的效果很糟糕,要不是出现中断就是标定出来的结果数值很大.经过了几天的不断调试和更改,终于把OpenCV的立体视觉标定和校正的程序写出来了.立体标定时计算空间上的两台摄像机几何关系的过程,立体校正则是对个体图像进行纠正,保证这些图像可以从平面对准的两幅图像获得.程序的框架如下: 1.读取左右相机图片序列 双目相机的图片序列放在Demon的路径下,左右相机的图像的名字分别存放在两

OpenCV相机标定

相机标定 相机标定:简单的说,就是获得相机参数的过程.参数如:相机内参数矩阵,投影矩阵,旋转矩阵和平移矩阵等 什么叫相机参数? 简单的说,将现实世界中的人.物,拍成一张图像(二维).人或物在世界中的三维坐标,和图像上对应的二维坐标间的关系.表达两种不同维度坐标间的关系用啥表示?用相机参数. 相机的成像原理 先来看一下,相机的成像原理: 如图所示,这是一个相机模型.将物体简化看成一个点.来自物体的光,通过镜头,击中图像平面(图像传感器),以此成像.d0是物体到镜头的距离,di时镜头到图像平面的距离

OpenCV相机标定及距离估计(单目)

相机标定基本知识 对于摄像机模型,一幅视图是通过透视变换将三维空间中的点投影到图像平面.投影公式如下: 或者 这里(X, Y, Z)是一个点的世界坐标,(u, v)是点投影在图像平面的坐标,以像素为单位.A被称作摄像机矩阵,或者内参数矩阵.(cx, cy)是基准点(通常在图像的中心),fx, fy是以像素为单位的焦距.所以如果因为某些因素对来自于摄像机的一幅图像升采样或者降采样,所有这些参数(fx, fy, cx和cy)都将被缩放(乘或者除)同样的尺度.内参数矩阵不依赖场景的视图,一旦计算出,可

opencv生成灰度图并保存

#include <opencv2/opencv.hpp>#include <iostream> using namespace cv;using namespace std; //加载图片并显示灰度图void loadGrayImg(){ Mat src = imread("D:\\images\\1.jpg"); if (src.empty()) { cout <<"could load image..." <<

opencv相机标定(Python)

相机标定 相机标定的目的 获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像. 相机标定的输入 标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上). 相机标定的输出 摄像机的内参.外参系数. 拍摄的物体都处于三维世界坐标系中,而相机拍摄时镜头看到的是三维相机坐标系,成像时三维相机坐标系向二维图像坐标系转换.不同的镜头成像时的转换矩阵不同,同时可能

Opencv摄像头标定(参数+校正),但cvFindChessboardCorners不太稳定,必须标版

#include <cv.h> #include <highgui.h> #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int n_boards=0;//图像数目 canshu const int board_dt=20;//等20帧每棋盘视图 xin //int sn_board=0;//成功找到角点的图像数目 int board_

opencv中的图片流保存

做图片流处理的时候总是保存不对, 图片如下 用如下代码保存,其中Arr是byte数组 //IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, Channels); //IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); //cvZero(img); //img->imageData =(char*) Arr; //img->