图像标定 求相机内参外参
来源:互联网 发布:软件系统功能分析 编辑:程序博客网 时间:2024/04/27 23:07
下文为使用最小二乘的方法对一幅图像进行标定,求得相机的内参、外参的参数。
Calibration
Process of camera calibration:
1. Load calibration piture andfind the corner by using “cvFindChessboardCorners” Opencv function. Then drawit in the raw piture.
2. Store the corner information,Create the matrix U (160*12) in the formula below.
3. Use to estimate the parameters of M.
Use the formula below to solve IntrinsicParameters and Extrinsic Parameters.
4. The Codelist below:
#include <cv.h>#include <highgui.h>#include <stdio.h>#include <stdlib.h>#include <math.h>int n_boards = 1; const int board_dt = 10;int board_w = 10;int board_h = 8;int x_coordinate[10] = {4,3,2,1,0,0,0,0,0,0};int y_coordinate[10] = {0,0,0,0,0,1,2,3,4,5};int main(int argc, char* argv[]) {int board_n = board_w * board_h;CvSize board_sz = cvSize( board_w, board_h );cvNamedWindow( "Calibration" );//ALLOCATE STORAGECvMat* image_points = cvCreateMat(n_boards*board_n,2,CV_32FC1);CvMat* object_points = cvCreateMat(n_boards*board_n,3,CV_32FC1);CvMat* point_counts = cvCreateMat(n_boards,1,CV_32SC1);CvMat* intrinsic_matrix = cvCreateMat(3,3,CV_32FC1);CvMat* distortion_coeffs = cvCreateMat(4,1,CV_32FC1);IplImage* image = 0;IplImage* gray_image = 0;//for subpixelCvPoint2D32f* corners = new CvPoint2D32f[ board_n ];int corner_count;image = cvLoadImage( "picture1.jpg",1);//求角点if(gray_image == 0 && image) //We'll need this for subpixel accurate stuffgray_image = cvCreateImage(cvGetSize(image),8,1); int found = cvFindChessboardCorners(image,board_sz,corners,&corner_count, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS );//Get Subpixel accuracy on those cornerscvCvtColor(image, gray_image, CV_BGR2GRAY);cvFindCornerSubPix(gray_image, corners, corner_count, cvSize(11,11),cvSize(-1,-1), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));//Draw itcvDrawChessboardCorners(image, board_sz, corners, corner_count, found); cvShowImage( "Calibration", image );//存储角点信息 // If we got a good board, add it to our data if( corner_count == board_n ) {for(int i = 0; i < board_h; ++i)for( int j = 0; j < board_w; ++j ) {int k = i*board_w+j;CV_MAT_ELEM(*image_points, float,k,0) = corners[k].x;CV_MAT_ELEM(*image_points, float,k,1) = corners[k].y;CV_MAT_ELEM(*object_points,float,k,0) = x_coordinate[j];CV_MAT_ELEM(*object_points,float,k,1) = y_coordinate[j];CV_MAT_ELEM(*object_points,float,k,2) = (8-i);} }//构造P矩阵CvMat* U_matrix = cvCreateMat(2*board_n,12,CV_32FC1);float Even_line[12];float Odd_line[12];memset(Even_line,0.0f,sizeof(float)*12);memset(Odd_line,0.0f,sizeof(float)*12);Even_line[3] = Odd_line[7] = 1;for(int i = 0,j = 0; i < 2*board_n; i+=2,j++){Even_line[0] = Odd_line[4] = CV_MAT_ELEM(*object_points,float,j,0);Even_line[1] = Odd_line[5] = CV_MAT_ELEM(*object_points,float,j,1);Even_line[2] = Odd_line[6] = CV_MAT_ELEM(*object_points,float,j,2);Even_line[11] = -CV_MAT_ELEM(*image_points,float,j,0);Odd_line[11] = -CV_MAT_ELEM(*image_points,float,j,1);Even_line[8] = Even_line[11]*Even_line[0];Even_line[9] = Even_line[11]*Even_line[1];Even_line[10] = Even_line[11]*Even_line[2];Odd_line[8] = Odd_line[11]*Odd_line[4];Odd_line[9] = Odd_line[11]*Odd_line[5];Odd_line[10] = Odd_line[11]*Odd_line[6];for(int j = 0;j < 12;j++) CV_MAT_ELEM(*U_matrix,float,i,j) = Even_line[j];for(int j = 0;j < 12;j++) CV_MAT_ELEM(*U_matrix,float,i+1,j) = Odd_line[j];}//计算内参、外参CvMat* UtU = cvCreateMat(12,12,CV_32FC1);cvGEMM(U_matrix,U_matrix,1,NULL,1,UtU,CV_GEMM_A_T);CvMat* UtU_evects = cvCreateMat(12,12,CV_32FC1);CvMat* UtU_evals = cvCreateMat(1, 12,CV_32FC1);cvEigenVV(UtU,UtU_evects,UtU_evals,0);double UtU_evals_min_val;CvPoint min_loc;cvMinMaxLoc(UtU_evals,&UtU_evals_min_val,NULL,&min_loc,NULL,NULL);CvMat* M = cvCreateMat(12,1,CV_32FC1);for(int i = 0;i < 12;i++) CV_MAT_ELEM(*M,float,i,0) = CV_MAT_ELEM(*UtU_evects,float,min_loc.x,i);CvMat* A1 = cvCreateMat(3,1,CV_32FC1);CvMat* A2 = cvCreateMat(3,1,CV_32FC1);CvMat* A3 = cvCreateMat(3,1,CV_32FC1);CvMat* b = cvCreateMat(3,1,CV_32FC1);for(int i = 0;i < 3;i++) CV_MAT_ELEM(*A1,float,i,0) = CV_MAT_ELEM(*M,float,i,0);for(int i = 4;i < 7;i++) CV_MAT_ELEM(*A2,float,i-4,0) = CV_MAT_ELEM(*M,float,i,0);for(int i = 8;i < 11;i++) CV_MAT_ELEM(*A3,float,i-8,0) = CV_MAT_ELEM(*M,float,i,0);for(int i = 3,j = 0;i < 12;i+=4,j++) CV_MAT_ELEM(*b,float,j,0) = CV_MAT_ELEM(*M,float,i,0);float a3 =cvNorm(A3,NULL,CV_L2,NULL);float Rho = -1/a3;CvMat* r1 = cvCreateMat(3,1,CV_32FC1);CvMat* r2 = cvCreateMat(3,1,CV_32FC1);CvMat* r3 = cvCreateMat(3,1,CV_32FC1);for(int i = 0;i < 3;i++)CV_MAT_ELEM(*r3,float,i,0) = Rho*CV_MAT_ELEM(*A3,float,i,0);float u0 = pow(Rho,2)*(cvDotProduct(A1,A3));float v0 = pow(Rho,2)*(cvDotProduct(A2,A3));CvMat* Cross_a1_a3 = cvCreateMat(3,1,CV_32FC1);CvMat* Cross_a2_a3 = cvCreateMat(3,1,CV_32FC1);cvCrossProduct(A1,A3,Cross_a1_a3);cvCrossProduct(A2,A3,Cross_a2_a3);float cos_theta = -((cvDotProduct(Cross_a1_a3,Cross_a2_a3))/(cvNorm(Cross_a1_a3,NULL,CV_L2,NULL)*cvNorm(Cross_a2_a3,NULL,CV_L2,NULL)));float theta = acos(cos_theta);float alpha = pow(Rho,2)*cvNorm(Cross_a1_a3,NULL,CV_L2,NULL)*sin(theta);float beta = pow(Rho,2)*cvNorm(Cross_a2_a3,NULL,CV_L2,NULL)*sin(theta);for(int i = 0;i < 3;i++)CV_MAT_ELEM(*r1,float,i,0) = (1/(cvNorm(Cross_a2_a3,NULL,CV_L2,NULL)))*CV_MAT_ELEM(*Cross_a2_a3,float,i,0);cvCrossProduct(r3,r1,r2);float K_element[9] = {alpha,-alpha*cos_theta,u0,0,beta/sin(theta),v0,0,0,1};CvMat* K = cvCreateMat(3,3,CV_32FC1);for(int i = 0;i < 3;i++) for(int j = 0;j < 3;j++) CV_MAT_ELEM(*K,float,i,j) = K_element[i*3+j];CvMat* t = cvCreateMat(3,1,CV_32FC1);CvMat* K_invert = cvCreateMat(3,3,CV_32FC1);cvInvert(K,K_invert,CV_LU);cvGEMM(K_invert,b,1,NULL,NULL,t,0);for(int i = 0;i < 3;i++) CV_MAT_ELEM(*t,float,i,0) = Rho*CV_MAT_ELEM(*t,float,i,0);//显示内参、外参printf("Intrinsic Parameters:\n");printf("alpha =%15.8f\n",alpha);printf("beta =%15.8f\n",beta);printf("theta =%15.8f\n",theta*57.29577951);printf("u0 =%15.8f\n",u0);printf("v0 =%15.8f\n",v0);printf("Extrinsic Parameters:\n");printf("r1 = [%15.8f %15.8f %15.8f]'\n",CV_MAT_ELEM(*r1,float,0,0),CV_MAT_ELEM(*r1,float,1,0),CV_MAT_ELEM(*r1,float,2,0));printf("r2 = [%15.8f %15.8f %15.8f]'\n",CV_MAT_ELEM(*r2,float,0,0),CV_MAT_ELEM(*r2,float,1,0),CV_MAT_ELEM(*r2,float,2,0)); printf("r3 = [%15.8f %15.8f %15.8f]'\n",CV_MAT_ELEM(*r3,float,0,0),CV_MAT_ELEM(*r3,float,1,0),CV_MAT_ELEM(*r3,float,2,0));printf("t = [%15.8f %15.8f %15.8f]'\n",CV_MAT_ELEM(*t,float,0,0),CV_MAT_ELEM(*t,float,1,0),CV_MAT_ELEM(*t,float,2,0));cvWaitKey(0); return 0;}
5 The result list below:
0 0
- 图像标定 求相机内参外参
- 相机内参外参
- 1、单目相机内参标定(camera_calibration_internal)
- 相机标定获得内参矩阵及其他参数
- 相机的内参及外参详细解释
- 3D重建之相机校准:相机的内参与外参
- opencv中3D点根据相机参数投影成2D点+solvePnP函数计算相机姿态+2D坐标到3D+相机参数calibration(标定与配准,求得深度彩色相机的内参与外参,再进行配准)
- Baxter学习笔记5-Kinect摄像头标定(内参和外参)篇
- matlab摄像机标定内参
- openCV---相机内外参标定
- 内参、外参、畸变参数三种参数与相机的标定方法与相机坐标系的理解
- 2、单目相机外参标定(camera_calibration_external)
- VINS(三)初始化与相机IMU外参标定
- 张正友相机标定Opencv实现以及标定流程&&标定结果评价&&图像矫正流程解析
- 双目相机标定之OpenCV获取左右相机图像+MATLAB单目标定+双目标定
- 相机标定
- 相机标定
- 相机标定
- 装饰者模式
- OSX上配置emacs的C/C++开发环境
- Head First Python(Web开发)
- UITextField改变return键显示的字
- UE-行文-js-20141125
- 图像标定 求相机内参外参
- Jenkins中无法启动子进程的解决办法
- 算法导论第十五章之钢条切割问题(自顶向下法)
- CToolTipCtrl使用详细解说
- rsync 安装使用详解
- HDOJ 1014 模拟
- 带checkbox的ListView实现(三)——CheckableImageView的实现方法
- 数值统计
- 算法导论第十五章之钢条切割问题(自底向上版本)