自制摄像头+鱼眼镜头校正+极线校正+直接输出双目视频
来源:互联网 发布:淘宝客服销售技巧 编辑:程序博客网 时间:2024/06/08 12:04
#include"stdafx.h"#include <iostream> #include <cv.hpp> #include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/core/core.hpp>#include"ocam_functions.cpp"using namespace cv;using namespace std;void main(){struct ocam_model ocam_left, ocam_right; // our ocam_models for the fisheye and catadioptric camerasget_ocam_model(&ocam_left, "./left_calib_results.txt");get_ocam_model(&ocam_right, "./right_calib_results.txt");int width = 1280;int height = 720;IplImage *dst_persp_left = cvCreateImage(cvSize(height, width), 8, 3); // undistorted perspective and panoramic imageIplImage *dst_persp_right = cvCreateImage(cvSize(height, width), 8, 3);CvMat* left_mapx_persp = cvCreateMat(width, height, CV_32FC1);CvMat* left_mapy_persp = cvCreateMat(width, height, CV_32FC1);CvMat* right_mapx_persp = cvCreateMat(width, height, CV_32FC1);CvMat* right_mapy_persp = cvCreateMat(width, height, CV_32FC1);float sf = 5;//DWORD dwStart = timeGetTime();create_perspecive_undistortion_LUT(left_mapx_persp, left_mapy_persp, &ocam_left, sf);create_perspecive_undistortion_LUT(right_mapx_persp, right_mapy_persp, &ocam_right, sf);//DWORD dwEnd = timeGetTime();//cout<<"time "<<dwEnd-dwStart<<" ms"<<endl;Mat rmap[2][2];FileStorage fs("remap.yml", CV_STORAGE_READ);if (fs.isOpened()){fs["MapLx"] >> rmap[0][0];fs["MapLy"] >> rmap[0][1];fs["MapRx"] >> rmap[1][0];fs["MapRy"] >> rmap[1][1];fs.release();}elsecout << "Error: can not save the intrinsic parameters\n";VideoCapture camera(0);camera.set(CV_CAP_PROP_FRAME_WIDTH, width * 2);camera.set(CV_CAP_PROP_FRAME_HEIGHT, height);if (!camera.isOpened()) {cout << "Failed to open camera." << std::endl;return;}//Change the image to video and read frame from the cameraMat frame;Mat frame_L, frame_R;IplImage* Left;IplImage* Right;bool imsave = false;bool left_show = true;char img_name[256];int fn = 0;//cvNamedWindow("left", 0);//cvNamedWindow("right", 0);int w = 720, h = 1280;CvSize size = cvSize(2 * w, h);IplImage* src_resize = cvCreateImage(size, IPL_DEPTH_8U, 3); //创建视频 文件格式大小的图片CvVideoWriter *writer = 0;double fps = 25;writer = cvCreateVideoWriter("out4.avi", CV_FOURCC('X', 'V', 'I', 'D'), fps, cvSize(2 * w, h)); while (1) {if (!camera.read(frame)) {cout << "Failed to read frame" << std::endl;break;}frame_L = frame.rowRange(0, height).colRange(0, width);frame_R = frame.rowRange(0, height).colRange(width, width * 2);frame_L = frame_L.t();flip(frame_L, frame_L, 0);frame_R = frame_R.t();flip(frame_R, frame_R, 0);IplImage src1(frame_L);cvRemap(&src1, dst_persp_left, left_mapx_persp, left_mapy_persp, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));IplImage src2(frame_R);cvRemap(&src2, dst_persp_right, right_mapx_persp, right_mapy_persp, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));Mat saveimg1(dst_persp_left);Mat saveimg2(dst_persp_right);remap(saveimg1, frame_L, rmap[0][0], rmap[0][1], CV_INTER_LINEAR);remap(saveimg2, frame_R, rmap[1][0], rmap[1][1], CV_INTER_LINEAR);if (left_show){imshow("left", frame_L);}/*imshow("right", frame_R);*/char cc = waitKey(10);if (cc == 's'){imsave = true;}if (cc == 'q'){break;}if (imsave){destroyWindow("left");//IplImage* Left, *Right;IplImage im_temp = frame_L; Left = cvCloneImage(&im_temp);IplImage im_temp1 = frame_L;Right = cvCloneImage(&im_temp1);cvSetImageROI(src_resize, cvRect(0, 0, w, h));cvCopy(Left, src_resize);cvResetImageROI(src_resize);cvSetImageROI(src_resize, cvRect(w, 0, w, h));cvCopy(Right, src_resize);cvResetImageROI(src_resize);cvNamedWindow("Myavi",0);cvShowImage("Myavi", src_resize);waitKey(10);cvWriteFrame(writer, src_resize); //保存图片为视频流格式 left_show = false;}}cvReleaseImage(&Left);cvReleaseImage(&Right);cvReleaseImage(&src_resize);camera.release();cvReleaseImage(&dst_persp_left);cvReleaseImage(&dst_persp_right);cvReleaseMat(&left_mapx_persp);cvReleaseMat(&left_mapy_persp);cvReleaseMat(&right_mapx_persp);cvReleaseMat(&right_mapy_persp);}
<span style="font-size:24px;color:#66ff99;">上面的源程序为读取鱼眼广角相机获取的双目视频,并且实时的采集,实时校正,最后将其保存为视频,供后续双目立体计算使用;</span>
<span style="font-size:24px;color:#66ff99;">下面贴出需要的ocam_functions.cpp文件:</span>
#include "ocam_functions.h"#define M_PI 3.1415926//------------------------------------------------------------------------------int get_ocam_model(struct ocam_model *myocam_model, char *filename){ double *pol = myocam_model->pol; double *invpol = myocam_model->invpol; double *xc = &(myocam_model->xc); double *yc = &(myocam_model->yc); double *c = &(myocam_model->c); double *d = &(myocam_model->d); double *e = &(myocam_model->e); int *width = &(myocam_model->width); int *height = &(myocam_model->height); int *length_pol = &(myocam_model->length_pol); int *length_invpol = &(myocam_model->length_invpol); FILE *f; char buf[CMV_MAX_BUF]; int i; //Open file if(!(f=fopen(filename,"r"))) { printf("File %s cannot be opened\n", filename);<span style="white-space:pre"></span> return -1; } //Read polynomial coefficients fgets(buf,CMV_MAX_BUF,f); fscanf(f,"\n"); fscanf(f,"%d", length_pol); for (i = 0; i < *length_pol; i++) { fscanf(f," %lf",&pol[i]); } //Read inverse polynomial coefficients fscanf(f,"\n"); fgets(buf,CMV_MAX_BUF,f); fscanf(f,"\n"); fscanf(f,"%d", length_invpol); for (i = 0; i < *length_invpol; i++) { fscanf(f," %lf",&invpol[i]); } //Read center coordinates fscanf(f,"\n"); fgets(buf,CMV_MAX_BUF,f); fscanf(f,"\n"); fscanf(f,"%lf %lf\n", xc, yc); //Read affine coefficients fgets(buf,CMV_MAX_BUF,f); fscanf(f,"\n"); fscanf(f,"%lf %lf %lf\n", c,d,e); //Read image size fgets(buf,CMV_MAX_BUF,f); fscanf(f,"\n"); fscanf(f,"%d %d", height, width); fclose(f); return 0;}//------------------------------------------------------------------------------void cam2world(double point3D[3], double point2D[2], struct ocam_model *myocam_model){ double *pol = myocam_model->pol; double xc = (myocam_model->xc); double yc = (myocam_model->yc); double c = (myocam_model->c); double d = (myocam_model->d); double e = (myocam_model->e); int length_pol = (myocam_model->length_pol); double invdet = 1/(c-d*e); // 1/det(A), where A = [c,d;e,1] as in the Matlab file double xp = invdet*( (point2D[0] - xc) - d*(point2D[1] - yc) ); double yp = invdet*( -e*(point2D[0] - xc) + c*(point2D[1] - yc) ); double r = sqrt( xp*xp + yp*yp ); //distance [pixels] of the point from the image center double zp = pol[0]; double r_i = 1; int i; for (i = 1; i < length_pol; i++) { r_i *= r; zp += r_i*pol[i]; } //normalize to unit norm double invnorm = 1/sqrt( xp*xp + yp*yp + zp*zp ); point3D[0] = invnorm*xp; point3D[1] = invnorm*yp; point3D[2] = invnorm*zp;}//------------------------------------------------------------------------------void world2cam(double point2D[2], double point3D[3], struct ocam_model *myocam_model){ double *invpol = myocam_model->invpol; double xc = (myocam_model->xc); double yc = (myocam_model->yc); double c = (myocam_model->c); double d = (myocam_model->d); double e = (myocam_model->e); int width = (myocam_model->width); int height = (myocam_model->height); int length_invpol = (myocam_model->length_invpol); double norm = sqrt(point3D[0]*point3D[0] + point3D[1]*point3D[1]); double theta = atan(point3D[2]/norm); double t, t_i; double rho, x, y; double invnorm; int i; if (norm != 0) { invnorm = 1/norm; t = theta; rho = invpol[0]; t_i = 1; for (i = 1; i < length_invpol; i++) { t_i *= t; rho += t_i*invpol[i]; } x = point3D[0]*invnorm*rho; y = point3D[1]*invnorm*rho; point2D[0] = x*c + y*d + xc; point2D[1] = x*e + y + yc; } else { point2D[0] = xc; point2D[1] = yc; }}//------------------------------------------------------------------------------void create_perspecive_undistortion_LUT( CvMat *mapx, CvMat *mapy, struct ocam_model *ocam_model, float sf){ int i, j; int width = mapx->cols; //New width int height = mapx->rows;//New height float *data_mapx = mapx->data.fl; float *data_mapy = mapy->data.fl; float Nxc = height/2.0; float Nyc = width/2.0; float Nz = -width/sf; double M[3]; double m[2]; for (i=0; i<height; i++) for (j=0; j<width; j++) { M[0] = (i - Nxc); M[1] = (j - Nyc); M[2] = Nz; world2cam(m, M, ocam_model); *( data_mapx + i*width+j ) = (float) m[1]; *( data_mapy + i*width+j ) = (float) m[0]; }}//------------------------------------------------------------------------------void create_panoramic_undistortion_LUT ( CvMat *mapx, CvMat *mapy, float Rmin, float Rmax, float xc, float yc ){ int i, j; float theta; int width = mapx->width; int height = mapx->height; float *data_mapx = mapx->data.fl; float *data_mapy = mapy->data.fl; float rho; for (i=0; i<height; i++) for (j=0; j<width; j++) { theta = -((float)j)/width*2*M_PI; // Note, if you would like to flip the image, just inverte the sign of theta rho = Rmax - (Rmax-Rmin)/height*i; *( data_mapx + i*width+j ) = yc + rho*sin(theta); //in OpenCV "x" is the *( data_mapy + i*width+j ) = xc + rho*cos(theta); }}<span style="font-family: Arial, Helvetica, sans-serif;"></span>
<span style="font-size:24px;color:#3333ff;">以及上面代码需要的头文件ocam_function.h:</span>
<span style="font-family: Arial, Helvetica, sans-serif;">#include <stdlib.h></span>
#include <stdio.h>#include <float.h>#include <math.h>#include <cv.h>#include <highgui.h>#define CMV_MAX_BUF 1024#define MAX_POL_LENGTH 64struct ocam_model{ double pol[MAX_POL_LENGTH]; // the polynomial coefficients: pol[0] + x"pol[1] + x^2*pol[2] + ... + x^(N-1)*pol[N-1] int length_pol; // length of polynomial double invpol[MAX_POL_LENGTH]; // the coefficients of the inverse polynomial int length_invpol; // length of inverse polynomial double xc; // row coordinate of the center double yc; // column coordinate of the center double c; // affine parameter double d; // affine parameter double e; // affine parameter int width; // image width int height; // image height};/*------------------------------------------------------------------------------ This function reads the parameters of the omnidirectional camera model from a given TXT file------------------------------------------------------------------------------*/int get_ocam_model(struct ocam_model *myocam_model, char *filename);/*------------------------------------------------------------------------------ WORLD2CAM projects a 3D point on to the image WORLD2CAM(POINT2D, POINT3D, OCAM_MODEL) projects a 3D point (point3D) on to the image and returns the pixel coordinates (point2D). POINT3D = [X;Y;Z] are the coordinates of the 3D point. OCAM_MODEL is the model of the calibrated camera. POINT2D = [rows;cols] are the pixel coordinates of the reprojected point Copyright (C) 2009 DAVIDE SCARAMUZZA Author: Davide Scaramuzza - email: davide.scaramuzza@ieee.org NOTE: the coordinates of "point2D" and "center" are already according to the C convention, that is, start from 0 instead than from 1.------------------------------------------------------------------------------*/void world2cam(double point2D[2], double point3D[3], struct ocam_model *myocam_model);/*------------------------------------------------------------------------------ CAM2WORLD projects a 2D point onto the unit sphere CAM2WORLD(POINT3D, POINT2D, OCAM_MODEL) back-projects a 2D point (point2D), in pixels coordinates, onto the unit sphere returns the normalized coordinates point3D = [x;y;z] where (x^2 + y^2 + z^2) = 1. POINT3D = [X;Y;Z] are the coordinates of the 3D points, such that (x^2 + y^2 + z^2) = 1. OCAM_MODEL is the model of the calibrated camera. POINT2D = [rows;cols] are the pixel coordinates of the point in pixels Copyright (C) 2009 DAVIDE SCARAMUZZA Author: Davide Scaramuzza - email: davide.scaramuzza@ieee.org NOTE: the coordinates of "point2D" and "center" are already according to the C convention, that is, start from 0 instead than from 1.------------------------------------------------------------------------------*/void cam2world(double point3D[3], double point2D[2], struct ocam_model *myocam_model);/*------------------------------------------------------------------------------ Create Look Up Table for undistorting the image into a perspective image It assumes the the final image plane is perpendicular to the camera axis------------------------------------------------------------------------------*/void create_perspecive_undistortion_LUT( CvMat *mapx, CvMat *mapy, struct ocam_model *ocam_model, float sf);/*------------------------------------------------------------------------------ Create Look Up Table for undistorting the image into a panoramic image It computes a trasformation from cartesian to polar coordinates Therefore it does not need the calibration parameters The region to undistorted in contained between Rmin and Rmax xc, yc are the row and column coordinates of the image center------------------------------------------------------------------------------*/void create_panoramic_undistortion_LUT ( CvMat *mapx, CvMat *mapy, float Rmin, float Rmax, float xc, float yc );
1 0
- 自制摄像头+鱼眼镜头校正+极线校正+直接输出双目视频
- 鱼眼镜头畸变校正模型
- 鱼眼镜头畸变校正方法
- 鱼眼镜头畸变校正-OpenCV3.1.0和Matalb2012a
- 鱼眼镜头畸变校正的一些参考链接
- 双目相机的畸变校正以及平行校正(极线校正)的入门问题总结
- 双目相机的畸变校正以及平行校正(极线校正)的入门问题总结
- 双目相机的畸变校正以及平行校正(极线校正)的入门问题总结
- 双目相机的畸变校正以及平行校正(极线校正)的入门问题总结
- 双目相机的畸变校正以及平行校正(极线校正)的入门问题总结
- 相机去畸变,以及双目平行校正----极线校正(二)————之双目平行校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(二)————之双目平行校正详细过程
- 双目定标和双目校正
- 双目定标与双目校正
- 双目定标与双目校正
- 双目定标和双目校正
- 双目定标和双目校正
- 双目校正:杂谈
- 使用CSS将图片转换成黑白(灰色、置灰)
- 开篇
- 绝对定位
- Swift元组
- 常用链接
- 自制摄像头+鱼眼镜头校正+极线校正+直接输出双目视频
- Xcode 8遇见新问题打印 subsystem: com.apple.siri等
- apktool下载地址
- Android Studio 使用JNI
- Mybatis 生成Oracle 数据库代码生成器
- explain详解
- 第18个python程序:命名变量代码函数
- 应聘时漂亮的回答
- [leetcode] 402. Remove K Digits 解题报告