00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
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
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
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
00094 cvDrawChessboardCorners (g_image_raw, g_board_sz, g_corners, corner_count, found);
00095 cvShowImage ("calibration", g_image_raw);
00096
00097
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
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
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
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
00155
00156
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
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);
00186 ros::spin ();
00187 cvDestroyWindow ("calibration");
00188 }