camera_calibration.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *  Software License Agreement (BSD License)
00003 *  Copyright (c) 2013, Intelligent Robotics Lab, DLUT.
00004 *  All rights reserved.
00005 *  Author:Zhao Cilang,Yan Fei,Zhuang Yan.
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Intelligent Robotics Lab nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 #include <ros/ros.h>
00034 #include <image_transport/image_transport.h>
00035 #include <opencv/cv.h>
00036 #include <opencv/highgui.h>
00037 #include <cxcore.h>
00038 #include <cv_bridge/CvBridge.h>
00039 
00040 int g_boards_n = 20;
00041 const int g_board_dt = 10;
00042 int g_board_w = 9;
00043 int g_board_h = 6;
00044 int g_board_n = g_board_w * g_board_h;
00045 CvSize g_board_sz = cvSize (g_board_w, g_board_h);
00046 
00047     //ALLOCATE STORAGE
00048 CvMat *g_image_points = cvCreateMat (g_boards_n * g_board_n, 2, CV_32FC1);
00049 CvMat *g_object_points = cvCreateMat (g_boards_n * g_board_n, 3, CV_32FC1);
00050 CvMat *g_point_counts = cvCreateMat (g_boards_n, 1, CV_32SC1);
00051 
00052 CvMat *g_intrinsic_matrix = cvCreateMat (3, 3, CV_32FC1);
00053 CvMat *g_distortion_coeffs = cvCreateMat (4, 1, CV_32FC1);
00054 
00055 CvPoint2D32f *g_corners = new CvPoint2D32f[g_board_n];
00056 int corner_count;
00057 int g_successes = 0;
00058 int g_step, g_frame = 0;
00059 
00060 sensor_msgs::CvBridge g_bridge;
00061 IplImage *g_image_raw = NULL;
00062 
00063 void imageCallback (const sensor_msgs::ImageConstPtr & msg)
00064 {
00065   try
00066   {
00067     g_image_raw = g_bridge.imgMsgToCv (msg, "bgr8");
00068   }
00069   catch (sensor_msgs::CvBridgeException & e)
00070   {
00071     ROS_ERROR ("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str ());
00072   }
00073 
00074   IplImage *gray_image = cvCreateImage (cvGetSize (g_image_raw), 8, 1);
00075   cvCvtColor (g_image_raw, gray_image, CV_BGR2GRAY);
00076 
00077   if (g_successes < g_boards_n)
00078   {
00079 
00080     if (g_frame++ % g_board_dt == 0)
00081     {
00082       //Find chessboard corners:
00083       int found = cvFindChessboardCorners (g_image_raw,
00084                                            g_board_sz,
00085                                            g_corners,
00086                                            &corner_count,
00087                                            CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
00088       //Get Subpixel accuracy on those corners
00089       cvFindCornerSubPix (gray_image, g_corners, corner_count,
00090                           cvSize (11, 11), cvSize (-1, -1), cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30,
00091                                                                             0.1));
00092 
00093       //Draw corners
00094       cvDrawChessboardCorners (g_image_raw, g_board_sz, g_corners, corner_count, found);
00095       cvShowImage ("calibration", g_image_raw);
00096 
00097       // If we got a good board, add it to our data
00098       if (found == 1)
00099       {
00100         g_step = g_successes * g_board_n;
00101         for (int i = g_step, j = 0; j < g_board_n; ++i, ++j)
00102         {
00103           CV_MAT_ELEM (*g_image_points, float, i, 0) = g_corners[j].x;
00104           CV_MAT_ELEM (*g_image_points, float, i, 1) = g_corners[j].y;
00105           CV_MAT_ELEM (*g_object_points, float, i, 0) = j / g_board_w;
00106           CV_MAT_ELEM (*g_object_points, float, i, 1) = j % g_board_w;
00107           CV_MAT_ELEM (*g_object_points, float, i, 2) = 0.0f;
00108 
00109         }
00110         CV_MAT_ELEM (*g_point_counts, int, g_successes, 0) = g_board_n;
00111         g_successes++;
00112       }
00113     }
00114 
00115     cvReleaseImage (&gray_image);
00116     //handle pause/unpause and ESC
00117     int c = cvWaitKey (15);
00118     if (c == 'p')
00119     {
00120       c = 0;
00121       while (c != 'p' && c != 27)
00122       {
00123         c = cvWaitKey (250);
00124       }
00125     }
00126     if (c == 27)
00127       return;
00128 
00129   }
00130   else
00131   {
00132     //ALLOCATE MATRICES ACCORDING TO HOW MANY IMAGES WE FOUND CHESSBOARDS ON
00133     CvMat *object_points2 = cvCreateMat (g_successes * g_board_n, 3, CV_32FC1);
00134     CvMat *image_points2 = cvCreateMat (g_successes * g_board_n, 2, CV_32FC1);
00135     CvMat *point_counts2 = cvCreateMat (g_successes, 1, CV_32SC1);
00136     //TRANSFER THE POINTS INTO THE CORRECT SIZE MATRICES
00137     for (int i = 0; i < g_successes * g_board_n; ++i)
00138     {
00139       CV_MAT_ELEM (*image_points2, float, i, 0) = CV_MAT_ELEM (*g_image_points, float, i, 0);
00140       CV_MAT_ELEM (*image_points2, float, i, 1) = CV_MAT_ELEM (*g_image_points, float, i, 1);
00141       CV_MAT_ELEM (*object_points2, float, i, 0) = CV_MAT_ELEM (*g_object_points, float, i, 0);
00142       CV_MAT_ELEM (*object_points2, float, i, 1) = CV_MAT_ELEM (*g_object_points, float, i, 1);
00143       CV_MAT_ELEM (*object_points2, float, i, 2) = CV_MAT_ELEM (*g_object_points, float, i, 2);
00144 
00145     }
00146     for (int i = 0; i < g_successes; ++i)
00147     {
00148       CV_MAT_ELEM (*point_counts2, int, i, 0) = CV_MAT_ELEM (*g_point_counts, int, i, 0);
00149     }
00150     cvReleaseMat (&g_object_points);
00151     cvReleaseMat (&g_image_points);
00152     cvReleaseMat (&g_point_counts);
00153 
00154     // At this point we have all of the chessboard corners we need.  
00155     // Initialize the intrinsic matrix such that the two focal
00156     // lengths have a ratio of 1.0
00157     CV_MAT_ELEM (*g_intrinsic_matrix, float, 0, 0) = 1.0f;
00158     CV_MAT_ELEM (*g_intrinsic_matrix, float, 1, 1) = 1.0f;
00159     
00160     //get the intrinsic parameters
00161     cvCalibrateCamera2 (object_points2,
00162                         image_points2,
00163                         point_counts2, cvGetSize (g_image_raw), g_intrinsic_matrix, g_distortion_coeffs, NULL, NULL, 0);
00164 
00165     cvSave ("Intrinsics.xml", g_intrinsic_matrix);
00166     cvSave ("Distortion.xml", g_distortion_coeffs);
00167     cvReleaseImage (&g_image_raw);
00168     cvReleaseMat (&g_intrinsic_matrix);
00169     cvReleaseMat (&g_distortion_coeffs);
00170     cvReleaseMat (&object_points2);
00171     cvReleaseMat (&image_points2);
00172     cvReleaseMat (&point_counts2);
00173 
00174     return;
00175   }
00176 }
00177 
00178 int main (int argc, char **argv)
00179 {
00180   ros::init (argc, argv, "camera_calibration");
00181   ros::NodeHandle nh;
00182   cvNamedWindow ("calibration");
00183   cvStartWindowThread ();
00184   image_transport::ImageTransport it (nh);
00185   image_transport::Subscriber sub = it.subscribe ("/pgr_camera/image", 1000, imageCallback);    //create a subscriber
00186   ros::spin ();
00187   cvDestroyWindow ("calibration");
00188 }


dlut_vision
Author(s): Zhao Cilang,Yan Fei,Zhuang Yan/zhuang@dlut.edu.cn
autogenerated on Sun Jan 5 2014 11:05:05