精华内容
下载资源
问答
  • 基于Bouguet’s Calibration Toolbox工具箱进行二次开发用于投影仪标定,与相机标定过程有所不同
  • 详细介绍了投影机模型,并提出一种简单、高精度的投影仪参数标定算法,该算法将投影仪当作一个逆向的相机,使用一块带有圆形标志点的平面标定板对投影仪进行标定标定过程中,使用两组不同方向的光栅图像建立投影仪图像...
  • 投影仪标定工具箱

    2016-09-22 19:21:16
    投影仪标定工具箱
  • 提出一种基于双目视觉的投影仪标定算法,将投影仪视为逆向相机,利用一个辅助相机捕获投影于不同位置标定平面,确立摄像图像与标定平面之间的对应关系,然后利用极线原理得到摄像图像与投影仪图像之间的对应关系...
  • 相机+投影仪系统标定 写在前面 1.写的比较详细,所以拆分成几部分。 2.使用Matlab添加额外的工具箱完成标定。 3.使用棋盘格标定相机、投影仪标定工具下载地址 1.相机标定工具箱Bouguet’s Calibration Toolbox ,...
  • 投影仪-相机标定程序

    2019-04-03 20:43:15
    在对投影仪标定工作上开源并且广泛使用的有两个DEMOS.一个是2009年Projcamcalib,这个应该容易找到源代码。另外一个是2012年布朗大学提出的一个投影仪标定方法,发表论文为《Simple, Accurate, and Robust Projector...
  • 相机与投影仪标定

    千次阅读 2018-07-23 21:11:19
    今天在阅读文献的时候,看到有篇论文中可以实现在一组实验中,同时进行相机与投影仪标定,主要步骤如下: 1) 在测量系统中安置好相机与投影仪的位置,并保证实验进行中,二者与系统的相对位置不会发生变化; 2...

    今天在阅读文献的时候,看到有篇论文中可以实现在一组实验中,同时进行相机与投影仪的标定,主要步骤如下:

    1) 在测量系统中安置好相机与投影仪的位置,并保证实验进行中,二者与系统的相对位置不会发生变化;

    2) 接着,将制作好的标定板摆放在相机与投影仪共同的视角范围内,并固定位置,保证其状态相对系统静止;

    3) 使用相机拍摄下仅有标定板的照片,保存;

    4) 使用投影仪向标定板投射网格图案,并使用相机拍摄下带有网格图案的标定板照片,保存;

    5) 在相机与投影仪共同视角范围内,将标定板摆放在多个不同位置,重复上述两个拍摄过程,存下一组照片(至少有3个不同标定板位置的两种照片),用于后续计算,即结束标定实验。

    所拍摄的照片有两种,即仅有标的标定板的照片和带有网格图案的标定板照片,其中,仅有标定板的照片用于进行相机标定,而带有网格图案的标定板照片用于进行投影仪标定。

    我认为投影仪打光在标定板上,标定板本身的特征信息会对格雷码光栅的解码带来干扰,造成格雷码解码错误率较高。

    大家对于上述方法有啥看法或是建议呢?

    欢迎大家加入知识星球,进行讨论呀。

    这里写图片描述

    这里写图片描述

    展开全文
  • 系统标定棋盘格用于系统的标定,在三维测量系统中起到很重要的作用,标定摄像投影仪
  • 投影仪标定程序

    2015-03-29 16:21:46
    投影仪标定程序,反投影精度在1个象素之内
  • 投影仪标定的几种思路

    千次阅读 热门讨论 2019-07-30 15:36:34
    投影仪标定的几种思路 单相机-投影仪的结构光三维重建系统中,投影仪标定是必不可少的步骤。通常,会将投影仪当作逆向的相机来进行标定。下面,将会介绍几种投影仪标定方法。 相位法(精度高、实现较难) 该...

    投影仪标定的几种思路

    单相机-投影仪的结构光三维重建系统中,投影仪标定是必不可少的步骤。通常,会将投影仪当作逆向的相机来进行标定。下面将介绍几种投影仪标定方法(以下名称是我自己根据方法原理命名的,大神轻喷)。


    • 相位法(精度高、实现较难)
      该种方法将投影仪当作逆向的相机模型来进行标定,通过计算投影仪投射的相位信息计算出世界坐标系z=0平面和投影仪“成像平面”之间的关系,具体标定步骤如下:
      S1:按照合适的角度固定好相机和投影仪,标定过程中保证二者相对静止;
      S2:准备好标定板,可以使用打印的标定板,也可以使用陶瓷标定板;
      S3:投影仪关闭,相机拍摄标定板图片;
      S4:投影仪投射多频相移图片(投射x方向和y方向的条纹图片),相机同时进行拍摄;
      S5:改变系统相对标定板的位姿,重复步骤S3、S4,拍摄>15组的数据;
      S6:使用拍摄的标定板图片进行相机标定,获得相机的内外参并保存每个标定板上的角点位置信息;
      S7:投影仪标定;
      S7.1:处理每组多频相移图片,分别计算出x方向和y方向上的绝对相位图,并将相位图的范围转换到图像行列范围;
      S7.2:根据每张图片的角点位置和相位图计算出每个角点对应的投影仪“像点坐标”;
      S7.3:根据”像点坐标“-标定板角点世界坐标的对应关系使用相机标定计算投影仪内外参;
      S8:已知每次场景下的相机外参和投影仪外参,计算出相机和投影仪之间的相对位姿。

    • 投射标定图案法(精度较低、实现较为简单)
      该种方法将投影仪当作逆向的相机模型来进行标定,通过让投影仪投射标定图案来建立世界坐标系下z=0平面和投影仪“成像平面”之间的关系,具体标定步骤如下:
      S1:按照合适的角度固定好相机和投影仪,标定过程中保证二者相对静止;
      S2:将打印好的标定板(棋盘格/圆形阵列)贴到较为平整的白板上;
      S3:投影仪关闭,相机拍摄打印的标定板图片;
      S4:投影仪打开,将标定图案投射到白板上,相机拍摄投射的标定板图片;
      S5:改变系统相对白板的位姿,重复步骤S3、S4,拍摄>15组的数据;
      S6:使用拍摄的打印标定板图片进行相机标定,获得相机内外参并保存每个标定板上图案位置信息;
      S7:投影仪标定;
      S7.1:检测投影标定图案图片上的所有角点信息,并且根据对应的外参计算出所有角点在世界坐标系下的坐标;
      S7.2:根据角点-世界坐标的对应关系使用相机标定方法标定投影仪内外参。
      S8:已知每次场景下的相机外参和投影仪外参,计算出相机和投影仪之间的相对位姿。

    • 八参数标定法(该方法我实现过,但是没有达到论文中说的那种精度)
    • 该种方法将投影仪建模为新的模型(从算法原理上看,我个人认为是逆向针孔模型),直接将投影仪的标定简化为8个未知参数的标定,具体标定步骤如下:
      S1:按照合适的角度固定好相机和投影仪,标定过程中保证二者相对静止;
      S2:准备好标定板,可以使用打印的标定板,也可以使用陶瓷标定板;
      S3:投影仪关闭,相机拍摄标定板图片;
      S4:投影仪投射多频相移图片(仅投射y方向条纹),相机同时进行拍摄;
      S5:改变系统相对标定板的位姿,重复步骤S3、S4,拍摄>15组的数据;
      S6:使用拍摄的标定板图片进行相机标定,获得相机的内外参并保存每个标定板上的角点位置信息;
      S7:投影仪标定;
      S7.1:处理每组多频相移图片,计算出y方向上的绝对相位图;
      S7.2:计算出每个位姿下标定板上角点在相机坐标系下的坐标;
      S7.3:根据角点位置信息计算出该角点在绝对相位图中的相位值;
      S7.4:根据以下公式计算出未知参数 a 1 − a 8 a_{1}-a_{8} a1a8

    S8:投影仪的内参即包含在参数 a 1 − a 8 a_{1}-a_{8} a1a8中,已知 ( x c , y c , z c ) (x_{c}, y_{c}, z_{c}) (xc,yc,zc) a 1 − a 8 a_{1}-a_{8} a1a8 θ \theta θ之间的关系,可以计算出该像素点对应的三维坐标(相机坐标系下)。

    大家好,我主要的研究方向有:
    1)主流的结构光三维测量方法,包括:线扫,格雷码,相移,散斑等;
    2)摄像机标定和投影仪标定;
    3)点云处理;
    4)图像处理;
    5)Halcon应用;
    6)机器视觉相机选型。

    对以上研究方向感兴趣的朋友可以关注我的微信公众号:

    展开全文
  • 根据射影变换原理建立投影仪图像和摄像图像的基本对应关系,然后对基本对应关系的误差使用二元四次函数拟合并进行补偿的方法建立两者的准确对应关系,进而获得平板上圆形标志点在投影仪上的准确图像坐标,完成投影...
  • (1)相机和投影仪摆好角度,将打印棋盘贴到白板上。 (2)相机拍摄仅带有打印棋盘的白板,图片命名为“camera1.jpg”;再将投影仪打开,将棋盘图片投射到白板上,相机拍摄投射的棋盘图片,命名为“projector.jpg”...

    标定步骤:

    (1)相机和投影仪摆好角度,将打印棋盘贴到白板上。

    (2)相机拍摄仅带有打印棋盘的白板,图片命名为“camera1.jpg”;再将投影仪打开,将棋盘图片投射到白板上,相机拍摄投射的棋盘图片,命名为“projector.jpg”;

    (3)移动白板,改变其相对相机-投影仪的相对位置,重复(2)步骤,不过命名.2jpg;

    (4)拍摄十组图片后,将cameraX.jpg保存在“cameraCalibdata.txt”,将projectorX。jpg保存到“projectCalibdata.txt”;

    (5)程序开始–》结束

    #include “cameraCalib.h”
    #include “projectCalib.h”
    using namespace cv;
    using namespace std;
    int main()
    {
    Size BoardSize = Size(13, 6); /存储打印棋盘标定板的行数和列数/
    Size Square_Size = Size(10, 10); /存储打印棋盘标定板的高度和宽度/
    Size ProjectBoardSize = Size(13, 6); /存储投影仪投射的棋盘的行数和列数/
    Size ProjectImageSize = Size(1280, 720); /存储投影仪投射的图片的像素行列数/
    Size Project_GridWidthANDHeigh = Size(80, 80); /投影仪的图像的棋盘的高度和宽度(像素表示)/
    Size EdgePixel = Size(160, 160); /投影仪的图像的边缘多余的像素/

    string ProjectFilename("projectCalibdata.txt");
    string CameraFileName("cameraCalibdata.txt");	/*提取图片信息的txt*/
    
    vector<vector<Point2f>> Project_ProjectROIPoints;/*投影仪投射的棋盘被摄像机捕捉后得到的角点*/
    vector<vector<Point2f>> Project_Image_Points;	/*投影仪的图像的角点*/
    vector<vector<Point2f>> Camera_ImagePoints;		/* 相机标定时保存检测到的所有图片的所有角点 */
    vector<vector<Point2f>> Camera_WorldPoints;		/*相机标定时所有角点对应的世界坐标[Xw,Yw]*/
    vector<vector<Point3f>> Project_Object_Points;
    												/*投影仪投射的棋盘的真实世界坐标[ Xw , Yw , Zw ]*/
    vector<Mat> Homography_AllImage;				/*相机标定时图像坐标与世界坐标之间的单应性矩阵*/
    
    /*摄像机标定*/
    cameraCalib(CameraFileName, BoardSize, Camera_ImagePoints);
    
    /*投影仪标定*/
    cout << "-----开始投影机标定-------" << endl;
    if (0 == projectorFindROICorners(ProjectFilename, ProjectBoardSize, Project_ProjectROIPoints))
    {
    	cout << "角点检测失败" << endl;
    }
    
    projectCameraTOWorld(Camera_ImagePoints, Project_ProjectROIPoints,Camera_WorldPoints,Homography_AllImage,
    	Project_Object_Points, BoardSize, Square_Size);
    system("pause");
    ProjectorCalib(Project_Object_Points, Project_Image_Points, ProjectImageSize, ProjectBoardSize, Project_GridWidthANDHeigh, EdgePixel);
    
    
    waitKey(0);
    return 0;
    

    }
    #include “projectCalib.h”
    #include
    #include
    #include “opencv2/calib3d/calib3d.hpp”
    #include “opencv2/imgproc/imgproc.hpp”

    Rect g_rectangle;//用于存储矩形框的信息
    bool g_bDrawingBox = false;//鼠标是否按下的标志
    bool stopDrawingFlag = false;/停止取图标志位/
    Mat tempROI; /用于保存ROI图像/
    RNG g_rng(12345);//RNG是随机数生成器

    bool projectorFindROICorners(const string & FILENAME,Size &BOARDSIZE, vector<vector> & ROI2Image_points_seq)
    {
    ifstream fin(FILENAME); /* 标定所用图像文件的路径 /
    vector ROI_points_buf; /
    缓存每幅图像上检测到的角点坐标 */
    int cornersROI_count = 0;/每幅roi图像上检测到的角点坐标个数/

    string filename; 
    int projector_image_count = 0;/*图像的数量*/
    /*---------------------------------检测角点坐标---------------------------------*/
    while(getline(fin, filename))
    {
    	projector_image_count++;/*图像读取个数+1*/
    	cout << "image_cout:-->" << projector_image_count << endl;
    	cout << "    " << filename << endl;
    	Mat srcImage = imread(filename);/*读取原图像*/
    	Mat tempImage;					/*用于画图的图像*/
    	namedWindow(filename,0);
    	while (!stopDrawingFlag)
    	{
    		setMouseCallback(filename, on_MouseHandle, (void*)&srcImage);
    		srcImage.copyTo(tempImage);//每次都用srcImg覆盖一下画面,当鼠标弹起时才会改变srcImg
    		if (g_bDrawingBox)
    			DrawRectangle(tempImage, g_rectangle);
    		imshow(filename, tempImage);
    		if (waitKey(10) == 27) break;
    	}
    	stopDrawingFlag = 0;
    	waitKey(500);//暂停0.5S	
    	cvDestroyWindow("ROI");
    	const char* str_filename = filename.c_str();
    	cvDestroyWindow(str_filename);
    	cout << "-------------第 " << projector_image_count << "张图片ROI提取完成,开始角点检测--------------" << endl;
    	if (0 == findChessboardCorners(tempROI, BOARDSIZE, ROI_points_buf, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK))
    	{
    		cout << "can not find chessboard corners!\n"; //找不到角点
    		waitKey(0);
    		return false;
    		 //exit(1);
    	}
    	else
    	{
    		Mat view_grayImage;
    		cvtColor(tempROI, view_grayImage, CV_RGB2GRAY);
    		cornerSubPix(view_grayImage, ROI_points_buf, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
    		drawChessboardCorners(view_grayImage, BOARDSIZE, ROI_points_buf, false); //用于在图片中标记角点
    		imshow("Projector Calibration", view_grayImage);//显示图片
    		waitKey(500);//暂停0.5S	
    		cornersROI_count = ROI_points_buf.size();
    		cout << "----cornersROI_count = " << cornersROI_count << endl;
    		for (int i = 0; i < cornersROI_count; i++)
    		{
    			ROI_points_buf[i].x += g_rectangle.x;
    			ROI_points_buf[i].y += g_rectangle.y;/*对ROI图像的角点进行补全*/
    			//cout << ROI_points_buf[i].x << "  , " << ROI_points_buf[i].y << endl;
    		}
    		ROI2Image_points_seq.push_back(ROI_points_buf);/*进栈保存*/
    	}
    	cout << "--------------第 " << projector_image_count << "张图片角点检测完成--------------" << endl;
    }
    int total = ROI2Image_points_seq.size();/*成功提取角点图片的个数*/
    cout << "----总图片数: " << total<<"提取角点完成----" << endl;
    /*------------------------------------------------------------------------------*/
    
    return true;
    

    }

    void projectCameraTOWorld(vector<vector> & IMAGE_POINTS,
    vector<vector> & ROI2Image_points_seq,
    vector<vector> & WORLD_POINTS,
    vector & HOMOGRAPHY_ALLImage,
    vector<vector> & WORLD_POINTS_Homogeneous,Size & BOARD_SIZE,Size & SQUARE_PRINT_SIZE)
    {
    /对WORLD_POINTS进行初始化/
    for (int i = 0; i < IMAGE_POINTS.size(); i++)
    {

    	vector<Point2f> tempImagePoints;
    	for (int j = 0; j<BOARD_SIZE.height; j++)
    	{
    		for (int k = 0; k<BOARD_SIZE.width; k++)
    		{
    			Point2f realPoint;
    			/* 假设标定板放在世界坐标系中z=0的平面上 */
    			realPoint.x = k * SQUARE_PRINT_SIZE.width;
    			realPoint.y = j * SQUARE_PRINT_SIZE.height;
    			tempImagePoints.push_back(realPoint);
    		}
    	}
    	WORLD_POINTS.push_back(tempImagePoints);
    	
    }
    
    //system("pause");
    /*计算所有的单应性矩阵*/
    for (int t = 0; t < IMAGE_POINTS.size(); t++)
    {
    	Mat h(3,3,CV_32FC1);
    	h = findHomography(IMAGE_POINTS[t], WORLD_POINTS[t]);
    	HOMOGRAPHY_ALLImage.push_back(h);
    }
    /*将计算出来的WORLD_POINTS变为[X , Y , Z ],其中Z=0*/
    for (int t = 0; t < ROI2Image_points_seq.size(); t++)
    {
    	vector<Point3f> EveryImagePoints;
    	for (int j = 0; j < ROI2Image_points_seq[t].size(); j++)
    	{
    
    		Mat temProppoint=Mat(3, 1, CV_32FC1, Scalar(0));
    		Mat temCrappoint=Mat(3, 1, CV_32FC1, Scalar(0));
    		Mat homo = Mat(3, 3, CV_32FC1, Scalar(0));
    		Mat homo2 = Mat(3, 3, CV_32FC1, Scalar(0));
    		
    		Point3f realPoint;
    		float Szc;
    		temCrappoint.at<float>(0, 0) = ROI2Image_points_seq[t][j].x;
    		temCrappoint.at<float>(1, 0) = ROI2Image_points_seq[t][j].y;
    		temCrappoint.at<float>(2, 0) = 1.0;
    		//HOMOGRAPHY_ALLImage[t].convertTo(HOMOGRAPHY_ALLImage[t], CV_32FC1);
    		//temCrappoint.convertTo(temCrappoint, CV_32FC1);
    		homo = HOMOGRAPHY_ALLImage[t].clone();
    		homo.convertTo(homo2, CV_32FC1);
    		temProppoint = homo2 * temCrappoint;
    		realPoint.z = temProppoint.at<float>(2, 0);
    		Szc = realPoint.z;
    		realPoint.x = temProppoint.at<float>(0, 0) / Szc;
    		realPoint.y = temProppoint.at<float>(1, 0) / Szc;
    		realPoint.z = 0.0;
    		EveryImagePoints.push_back(realPoint);
    	}
    	WORLD_POINTS_Homogeneous.push_back(EveryImagePoints);
    }
    cout << "投影仪投射棋盘的角点的世界坐标计算完成" << endl;
    

    }

    void ProjectorCalib(vector<vector> & Projector_Object_points,
    vector<vector> & Projector_Image_points,
    const Size & PROJECT_IMAGE_SIZE,
    const Size & PROJECT_BOARD_SIZE,
    const Size & PROJECT_GridWidthANDHeigh,
    const Size & EdgePixel)
    {
    /---------------------------------标定程序-------------------------------------/

    ofstream fout("projectCaliberation_result.txt");
    int image_count = Projector_Object_points.size();
    Mat projector_IntMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 投影仪内参数矩阵 */
    Mat projector_distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)); /* 投影仪的5个畸变系数:k1,k2,p1,p2,k3 */
    vector<Mat> projector_rvecsMat;  /* 每幅图像的旋转向量 */
    vector<Mat> projector_tvecsMat; /* 每幅图像的平移向量 */
    /*初始化投影仪图片的二维坐标*/
    for (int i = 0; i < image_count; i++)
    {
    	vector<Point2f> tempImages;
    	for (int j = 0; j < PROJECT_BOARD_SIZE.height; j++)
    	{
    		for (int k = 0; k < PROJECT_BOARD_SIZE.width; k++)
    		{
    			Point2f tempPoints;
    			tempPoints.x = k * PROJECT_GridWidthANDHeigh.width + EdgePixel.width;
    			tempPoints.y = j * PROJECT_GridWidthANDHeigh.height + EdgePixel.height;
    			tempImages.push_back(tempPoints);
    		}
    	}
    	Projector_Image_points.push_back(tempImages);
    }
    
    /*开始标定*/
    cout << Projector_Object_points.size()<<"----"<< Projector_Object_points[0].size() << endl;
    cout << Projector_Image_points.size() << "----" << Projector_Image_points[0].size() <<endl;
    system("pause");
    
    calibrateCamera(Projector_Object_points,
    	Projector_Image_points,
    	PROJECT_IMAGE_SIZE,
    	projector_IntMatrix,
    	projector_distCoeffs,
    	projector_rvecsMat,
    	projector_tvecsMat, 0);
    /*标定完成*/
    Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */
    fout << "内参数矩阵:" << endl;
    fout << projector_IntMatrix << endl << endl;
    fout << "畸变系数:\n";
    fout << projector_distCoeffs << endl << endl << endl;
    for (int i = 0; i<image_count; i++)
    {
    	fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;
    	fout << projector_rvecsMat[i] << endl;
    	/* 将旋转向量转换为相对应的旋转矩阵 */
    	Rodrigues(projector_rvecsMat[i], rotation_matrix);
    	fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;
    	fout << rotation_matrix << endl;
    	fout << "第" << i + 1 << "幅图像的平移向量:" << endl;
    	fout << projector_tvecsMat[i] << endl << endl;
    }
    std::cout << "投影仪完成标定" << endl;
    /*---------------------------------------------------------------------------------*/
    

    }

    void on_MouseHandle(int event, int x, int y, int flags, void* param)
    {
    Mat& image = (Mat)param;//先从空指针转换为Mat指针再解引用
    switch (event)
    {
    case EVENT_MOUSEMOVE:
    {
    if (g_bDrawingBox)
    {
    g_rectangle.width = x - g_rectangle.x;
    g_rectangle.height = y - g_rectangle.y;
    }
    }
    break;

    case EVENT_LBUTTONDOWN:
    {
    	cvDestroyWindow("ROI");
    	g_bDrawingBox = true;
    	g_rectangle = Rect(x, y, 0, 0);//记录起始点
    }
    break;
    
    case EVENT_LBUTTONUP:
    {
    	g_bDrawingBox = false;
    	if (g_rectangle.width < 0)
    	{
    		g_rectangle.x += g_rectangle.width;
    		g_rectangle.width *= -1;
    	}
    	if (g_rectangle.height < 0)
    	{
    		g_rectangle.y += g_rectangle.height;
    		g_rectangle.height *= -1;
    	}
    	tempROI = image(Rect(g_rectangle.x, g_rectangle.y, g_rectangle.width, g_rectangle.height));
    	namedWindow("ROI");
    	imshow("ROI", tempROI);
    	//DrawRectangle(image, g_rectangle);//鼠标松开后可以在固定显示一个框
    }
    break;
    case EVENT_RBUTTONDOWN:
    {
    	stopDrawingFlag = true;/*停止取图*/
    }
    }
    

    }

    void DrawRectangle(Mat& img, Rect box)
    {

    rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255),
    	g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
    

    }

    #ifndef PROJECTCALIB_H_
    #define PROJECTCALIB_H_
    #include “opencv2/highgui/highgui.hpp”

    using namespace cv;
    using namespace std;

    void on_MouseHandle(int event, int x, int y, int flags, void* param);

    void DrawRectangle(Mat& img, Rect box);

    /--------------------------------------------------------
    projectorFindROICorners投影仪投影图片 ,选取ROI函数
    FILENAME:图片来源
    BOARDSIZE:投影仪投射棋盘的行数和列数
    vector<vector> & ROI2Image_points_seq 保存检测到的所有角点坐标(已转换到全局坐标)
    ----------------------------------------------------------
    /

    bool projectorFindROICorners(const string & FILENAME, Size &BOARDSIZE, vector<vector> & ROI2Image_points_seq);

    /--------------------------------------------------------
    projectCameraTOWorld 计算由二维图像坐标变为三维世界坐标[ u , v , 1 ]–>[ Xw , Yw , Zw , 1 ]的单应性矩阵,
    IMAGE_POINTS 打印棋盘格的图像坐标
    ROI2Image_points_seq:投影仪投射的棋盘的在摄像机图像中的坐标
    WORLD_POINTS 对应的世界坐标
    HOMOGRAPHY_ALLImage 图像坐标与世界坐标之间的单应性矩阵
    WORLD_POINTS_Homogeneous 投影仪投射的棋盘的真实世界坐标
    BOARD_SIZE 打印棋盘的行数和列数
    SQUARE_PRINT_SIZE 打印棋盘棋盘格的高度和宽度
    ----------------------------------------------------------
    /
    void projectCameraTOWorld(vector<vector> & IMAGE_POINTS,
    vector<vector> & ROI2Image_points_seq,
    vector<vector> & WORLD_POINTS,
    vector & HOMOGRAPHY_ALLImage,
    vector<vector> & WORLD_POINTS_Homogeneous, Size & BOARD_SIZE, Size & SQUARE_PRINT_SIZE);

    /--------------------------------------------------------
    ProjectorCalib 投影仪标定函数
    Projector_Object_points:投影仪投射的棋盘的真实世界坐标(输入不能为空)
    Projector_Image_points:投影仪的图像的角点(输入为空,函数内部计算)
    PROJECT_IMAGE_SIZE:投影仪的图像的尺寸(如:1024
    762)
    PROJECT_BOARD_SIZE:投影仪的图像的棋盘的行数列数;
    PROJECT_GridWidthANDHeigh:投影仪的图像的棋盘的高度和宽度
    EdgePixel:投影仪的图像的边缘多余的像素
    ----------------------------------------------------------*/
    void ProjectorCalib(vector<vector> & Projector_Object_points,
    vector<vector> & Projector_Image_points,
    const Size & PROJECT_IMAGE_SIZE,
    const Size & PROJECT_BOARD_SIZE,
    const Size & PROJECT_GridWidthANDHeigh,
    const Size & EdgePixel);

    #endif // !PROJECTCALIB_H_

    ————————————————
    版权声明:本文为CSDN博主「催人乳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/tama1204/article/details/88707482

    展开全文
  • 用固定的摄像采集若干幅标定板不同朝向的图像,对采集图像进行颜色通道过滤,得到投影仪标定所需的同心圆分量和棋盘格分量,结合摄像机投影仪图像之间的映射关系和同心圆的秩2约束来标定投影仪。此方法仅需用三幅...
  • 结构光之单目+投影仪标定流程详解

    千次阅读 热门讨论 2019-08-25 22:02:37
    ***作为一个小白,近期在使用MATLAB标定工具包对投影仪标定中,在各大网上,苦于没有一个详细的教程,遇到好多隐藏的坑,走了许多弯路。所以,写此博客,来对标定流程进行详细阐述以及相关可能遇到的问题。 因为...

    作为一个小白,近期在使用MATLAB标定工具包对投影仪的标定中,在各大网上,苦于没有一个详细的教程,遇到好多隐藏的坑,走了许多弯路。所以,写此博客,来对标定流程进行详细阐述以及相关可能遇到的问题。
    因为刚开始接触这个领域,有写的不足或欠缺的地方,还望各位大佬提出。

    对投影仪、相机的标定,通常是结构光主动式深度获取领域的重要步骤。通过标定,可以获取他们的内、外参数以及畸变参数等重要数据。而标定相机在最新的MATLAB版本中,已经嵌入了相关的APP,可以通过导入图片,从而软件自动对单目、双目相机完成标定流程,省时省力。
    针对单目+投影仪的标定,我们采用MATLAB的标定工具包中的cam_proj_gui这个程序来进行标定。
    运行该程序,出现如下界面:
    cam_proj_gui界面
    投影仪的标定基本流程就是:顺次点击完第一行的所有内容和第二行的标定投影仪方可。注意标定拍照过程中,投影仪投射的棋盘格需要和相机拍摄的实物棋盘格在同一场景中,并且尽可能保证棋盘格占据广泛视野;同时,标定图片尽可能保证有不同姿态,且大于15张为宜,以确保标定数据的准确性。
    接下来将针对一些细节问题,进行详细阐述。
    首先需要进行相机标定,即选中第一个框,这里的标定相机需要预先下载好camera_calib标定工具包,设置好路径。该工具包的使用网上还是比较多的,大家可以自己了解一下。
    随后,需要点击Load Camera Calibration,装载标定相机参数;
    当点击Set Projector’s calib.images时,出现下图:询问你是否使用标定相机时候用的图片来标定投影仪?
    在这里插入图片描述
    一般情况下,我们按回车,表示同意(此情况必须保证标定相机的图片存在且完整无误,标定过程中也没删减图片)
    若选择否,则出现让你重新标定相机的过程,如图。窗口大小一般为默认就好,X,Y方向上的大小为实际棋盘格的大小尺寸。紧接着就是顺次选择相机拍摄的实际的棋盘格的四个角点进行标定相机。
    导入标定图片
    当相机标定完成后,就可以点击第四个Ray plane intersection,进行对投影仪的标定。窗口大小依旧选择默认,为5*5
    若出现需要标定的图片没有正常显示(即为全白的情况),可以尝试将图片转换为灰度图。
    标定投影仪时,由于设置的窗口比较小,需要尽可能准确点中各个角点,以避免误差过大。标定过程中,还可以利用windows系统下,自带的放大镜进行更高倍数放大,避免点错。
    投影仪标定示意图
    若标定过程中,选定的角点出现了一些误差,不能自动识别各个角点的位置,则需要自己手动标定点框内的X、Y方向上的方格数量。我这里棋盘格X、Y方向数量设置为8。
    等待所有图片都标定完时,不要按回车过快,否则会前功尽弃。这时会要求你导入投射的棋盘格的模板图片(该图片应与程序在一个文件夹中),我这里模板图片名称为calib_solo_pro4500.bmp。然后选择窗口大小,再依次点击四个角点便可。
    导入投射棋盘格模板图片
    完成上述几步,便可以点击Calibrate the projector。注意:点击这步往往并不一定会成功。它经常会出现如下图所示的病态错误。
    病态错误
    解决办法:寻找工具包函数中所有check_cond = 1的地方将其更改为0,便可解决问题
    至此,所有的标定过程暂告一段落。系统会给你自动展示fc,cc,alpha_c,kc,Pixel error以及各个参数对应的误差范围。
    如果,你的误差值太大,则需要删减有些误差比较大的图片。
    Analyse error便可帮助你进行误差情况分析,出现如下图片。鼠标点击误差比较大的点,在命令行窗口便可出现该点所属的图片名称。
    分析误差分布
    Add/Suppress images可帮助你完成增/删图片的目的。先是0、1分别表示选择删除、增加图片操作;随后填写要增加或删除图片的名称。随之可重新进行标定操作。通过这种反复操作,便可达到降低误差的目的。
    最后save便可将标定得到的相关信息保存为Cam_Proj_calib.mat文件

    问题总结:

    • 若出现标定投影仪时,需要标定的图片没有正常显示(即为全白的情况),可以尝试将图片转换为灰度图。
    • 标定投影仪时候,可能会出现列表图片未被激活现象,建议提前寻找工具包函数中所有check_cond = 1的地方将其更改为0,便可解决问题
    展开全文
  • 结构光单目相机投影仪标定 1、准备工作 一块大的平板,贴上棋盘格,同时可以投影一幅棋盘格 2、投影采集 变换位姿,采集10幅图片 3、标定 使用相机标定工具箱和投影仪标定工具箱,求取相机和投影仪的内外参。 4、...
  • Matlab 结构光相机-投影仪标定代码
  • 投影仪标定过程总结

    千次阅读 2018-10-26 13:13:40
    投影仪标定步骤 已知多个角点齐次坐标 ( x p , y p , 1 ) (x_p,y_p,1) ( x p ​ , y p ​ , 1 ) ,求出对应的世界齐次坐标 ( X , Y , Z , 1 ) (X,Y,Z,1) ( X , Y , Z , 1 ) 步骤: (1)根据相机标定的角点齐次坐标...
  • (结构光代码篇)相机标定+投影仪标定

    千次阅读 热门讨论 2020-01-04 16:02:14
    相机标定 利用OpenCV(单目)相机标定函数calibrateCamera(),仅需要已知角点的世界坐标、角点的图片坐标、图片的尺寸,代入函数即可得到相机的内外各类参数。 世界坐标的获取 以棋盘格所在平面作为世界坐标系的...
  • 基于OPENCV的投影仪标定(源码)

    千次阅读 2019-05-10 10:09:48
    opencv3.0的源码,之前很苦恼投影仪标定,opencv提供了一个demo,上传源码: #include <opencv2/highgui.hpp> #include #include #include #include <opencv2/core.hpp> #include <opencv2/...
  • 同于相机标定的方法和步骤,投影仪的原理通常被看作是相机成像的逆过程,网上关于相机标定和校准的教程有很多,但投影仪标定的资料一方面另一方面介绍不够详细,对新手不太友好,所以这次分享的主要目的是做成全网...
  • 投影仪-相机标定

    2021-10-08 11:15:33
    1. 单目相机标定 引言 相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。...相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影
  • matlab投影仪标定

    千次阅读 2019-08-25 16:18:10
    matlab中的投影仪标定方法属于投射标定图案法,投射的图案只能是棋盘格,该方法将投影仪当作逆向的相机,它具有映射图像二维点到三维坐标的功能,因此可以使用张正友标定方法来对它进行标定投影仪标定图像的获取 ...
  • 标定前准备 标定投影仪之前需要已经将相机标定完成,获得了相机的内外参数。 一个白板,一部分有棋盘格一部分是空白的。...单目结构光投影仪标定是将投影仪看成一个“逆过来”的照相机,开始我不太明白逆着
  • 摄像机和投影机标定源代码

    热门讨论 2012-11-27 16:08:22
    基于张正友的二次平面摄像机标定算法,并通过摄像机的逆向光路计算投影机的内外参数,标定精度高,而满足一般的需求。代码依据网上高人的版本,进行相应的补充和修改,增加了投影机的标定,添加了更为详细的注释~...
  • 投影仪标定方法总结

    千次阅读 2019-10-30 16:13:23
    投影仪标定的核心:求投影仪投影格点的三维空间点坐标 方法一: 标定相机 求投影的投影的3D空间的角点坐标,通过Utilities::pixelToImageSpace()求相机坐标系的点坐标,设置缩放因子为1,z=1,然后转换到世界坐标...
  • 结构光系统之投影仪和系统标定

    千次阅读 热门讨论 2020-07-05 17:38:26
    基于棋盘格标定板的单相机单投影仪结构光系统的标定——相机标定
  • 这两种方法我都实现过,后者确实相对好点。 还有一种方法,八参数标定法,这个我没有做,但是看了一下他的原理。最近有时间会来写一下
  • 系统参数的标定是结构光三维测量系统工作的基础,且参数标定的精度直接影响测量的精度,其中投影仪目前还存在标定过程复杂、精度较低等问题。为解决该问题,通过投影一组圆阵图案到一块本身带有特征圆的平板上,并由...
  • 基于多项式失真表示的精确投影仪标定方法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,562
精华内容 2,624
关键字:

投影仪标定