摄像头标定
Wikipedia,自由的百科全书
目录[隐藏] |
标定原理介绍
- 摄像机小孔模型 Cv照相机定标和三维重建#针孔相机模型和变形
标定程序1(opencv自带的示例程序)
简介
读者可以直接使用Opencv自带的摄像机标定示例程序,该程序位于 “/OpenCV/samples/c目录下的calibration.cpp”,程序的输入支持直接从USB摄像机读取图片标定,或者读取avi文件或者已经存放于电脑上图片进行标定。
使用说明
编译运行程序,如果未设置任何命令行参数,则程序会有提示,告诉你应该在你编译出来的程序添加必要的命令行,比如你的程序是calibration.exe(以windows操作系统为例)。则你可以添加如下命令行(以下加粗的字体所示):
calibration -w 6 -h 8 -s 2 -n 10 -o camera.yml -op -oe [<list_of_views.txt>]
调用命令行和参数介绍
Usage: calibration
-w <board_width> # 图片某一维方向上的交点个数 -h <board_height> # 图片另一维上的交点个数 [-n <number_of_frames>] # 标定用的图片帧数 # (if not specified, it will be set to the number # of board views actually available) [-d <delay>] # a minimum delay in ms between subsequent attempts to capture a next view # (used only for video capturing) [-s <square_size>] # square size in some user-defined units (1 by default) [-o <out_camera_params>] # the output filename for intrinsic [and extrinsic] parameters [-op] # write detected feature points [-oe] # write extrinsic parameters [-zt] # assume zero tangential distortion [-a <aspect_ratio>] # fix aspect ratio (fx/fy) [-p] # fix the principal point at the center [-v] # flip the captured images around the horizontal axis [input_data] # 输入数据,是下面三种之中的一种: # - 指定的包含图片列表的txt文件 # - name of video file with a video of the board # if input_data not specified, a live view from the camera is used
上图中,横向和纵向分别为9个交点和6个交点,对应上面的命令行的命令参数应该为: -w 9 -h 6。
- 经多次使用发现,不指定 -p参数时计算的结果误差较大,主要表现在对u0,v0的估计误差较大,因此建议使用时加上-p参数
list_of_views.txt
该txt文件表示的是你在电脑上面需要用以标定的图片列表。
view000.png view001.png #view002.png view003.png view010.png one_extra_view.jpg
上面的例子中,前面加“井号”的图片被忽略。
- 在windows的命令行中,有一种简便的办法来产生此txt文件。在CMD窗口中输入如下命令(假设当前目录里面的所有jpg文件都用作标定,并且生成的文件为a.txt)。
dir *.jpg /B >> a.txt
输入为摄像机或者avi文件时
"When the live video from camera is used as input, the following hot-keys may be used:/n" " <ESC>, 'q' - quit the program/n" " 'g' - start capturing images/n" " 'u' - switch undistortion on/off/n";
代码
请直接复制 calibration.cpp 中的相关代码。
标定程序2
OPENCV没有提供完整的示例,自己整理了一下,贴出来记录。
- 首先自制一张标定图片,用A4纸打印出来,设定距离,再设定标定棋盘的格子数目,如8×6,以下是我做的图片8×8
- 然后利用cvFindChessboardCorners找到棋盘在摄像头中的2D位置,这里cvFindChessboardCorners不太稳定,有时不能工作,也许需要图像增强处理。
- 计算实际的距离,应该是3D的距离。我设定为21.6毫米,既在A4纸上为两厘米。
- 再用cvCalibrateCamera2计算内参,
- 最后用cvUndistort2纠正图像的变形。
结果如下:
代码
具体的函数使用,请参考Cv照相机定标和三维重建#照相机定标
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> // OpenCV #include <cxcore.h> #include <cv.h> #include <highgui.h> #include <cvaux.h> void InitCorners3D(CvMat *Corners3D, CvSize ChessBoardSize, int Nimages, float SquareSize); void makeChessBoard(); int myFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH ); inline int drawCorssMark(IplImage *dst,CvPoint pt) /************************************************* Function: main_loop Description: 绘制一个十字标记 Calls: Called By: Input: RGB image, pt Output: Return: Others: 需要检查坐标是否越界 to do list *************************************************/ { const int cross_len = 4; CvPoint pt1,pt2,pt3,pt4; pt1.x = pt.x; pt1.y = pt.y - cross_len; pt2.x = pt.x; pt2.y = pt.y + cross_len; pt3.x = pt.x - cross_len; pt3.y = pt.y; pt4.x = pt.x + cross_len; pt4.y = pt.y; cvLine(dst,pt1,pt2,CV_RGB(0,255,0),2,CV_AA, 0 ); cvLine(dst,pt3,pt4,CV_RGB(0,255,0),2,CV_AA, 0 ); return 0; } /* declarations for OpenCV */ IplImage *current_frame_rgb