zoukankan      html  css  js  c++  java
  • OpenCV使用标定图

    本文由 @lonelyrains 出品,转载请注明出处。 
    文章链接: http://blog.csdn.net/lonelyrains/article/details/46915705


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

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


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


    生成OpenCV识别的标定图列表的project:opencv248sourcessamplescppimagelist_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:opencv248sourcessamplescppcalibration.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自带的图片opencv248sourcessamplescppleftXX.jpg,转成png,成功运行。

    在识别到的棋盘中描出了角点。

    3、为了减小问题出现的因素。尽量控制单一变量。使用行列同leftXX.jpg同样的标定板图片:宽9个小方格、高6个小方格。仍然不能识别。

    4、怀疑是摄像头的畸变太严重,导致图片识别不了,就用手机摄像头试了一下。由于手机摄像头的畸变很小,基本能够忽略。结果尽管也不能识别。

    可是将手机对着显示器拍照拍得的原始图片对着leftXX.jpg使用灰色边框,结果能够识别了!

    5、再用摄像头拍的图片,使用灰色边框,发现仍然识别不了。假设摄像头畸变太严重导致识别不了,貌似也不太合情理,由于都是数字游戏呀。

    方格应该能够比較好识别吧。畸变看起来也不是比leftXX.jpg大太多。剩下的仅仅能怀疑是打印纸的黑方格的黑色不明显。用毛笔涂黑(也是醉了)。

    6、最后最终能够识别一部分图片了!也算大功告成吧。顺便歧视一把国内打印店的打印机质量,黑方格颜色太浅,咋leftXX.jpg外国打印机就打得那么神颜色。


    原始畸变图片、校准工具描了角点的畸变图片和校正图片,取了同一张。分别例如以下:





    添加了命令行的批处理文件,标定校准工具、图片打包下载链接:http://download.csdn.net/detail/lonelyrains/8906705


  • 相关阅读:
    凤凰网面试经历——钢管舞也算精英文化吗
    立此为证:豆瓣要做电影数字发行了(2010818)
    Officially GoldenGate was purchased by oracle in October 1, 2009
    11gR2新特性:Heavy swapping observed on system in last 5 mins.
    Oracle BMW Racing sailing vessel帆船图
    Know more about CBO Index Cost
    Samsung Epic 4G 图文介绍
    Oracle Exalogic X22 HalfRack DiagramExaloic半配图
    Java 编程下线程的生命周期
    Android 编程组件Fragments 的生命周期与 Activity 的生命周期之间的关系
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6743276.html
Copyright © 2011-2022 走看看