Fix bugs in calibrate.cc

This commit is contained in:
Razvan Mihalyi 2012-09-18 23:16:39 +02:00
commit 285c65b6fb
2 changed files with 147 additions and 120 deletions

View file

@ -10,7 +10,7 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
enum {INTERACTIVE_MODE, PRESPECIFIED_MODE}; enum { INTERACTIVE_MODE, PRESPECIFIED_MODE };
#define KEY_ESCAPE 1048603 #define KEY_ESCAPE 1048603
#define KEY_SPACE 1048608 #define KEY_SPACE 1048608
@ -19,124 +19,144 @@ enum {INTERACTIVE_MODE, PRESPECIFIED_MODE};
#define COUNT_SQUARES_X 4 #define COUNT_SQUARES_X 4
#define COUNT_SQUARES_Y 6 #define COUNT_SQUARES_Y 6
int main(int argc, char** argv) int detect_pattern(Mat frame, vector< vector<Point3f> >& object_points, vector<vector<Point2f> >& image_points)
{ {
int user_mode; // interior number of corners
int specified_boards; Size pattern_size(COUNT_SQUARES_X, COUNT_SQUARES_Y);
if (argc > 2) // will be filled by the detected corners
cerr << "Usage: ./calibrate [number of frames]\n"; vector<Point2f> corners;
else if (argc == 1)
{
user_mode = INTERACTIVE_MODE;
cout << "Camera calibration using interactive behavior. Press SPACE to grab frame, ESC to quit.\n";
}
else
{
user_mode = PRESPECIFIED_MODE;
stringstream ss; ss << argv[1];
ss >> specified_boards;
cout << "Camera calibration using " << specified_boards << " frames.\n";
}
VideoCapture capture(0); // open the default camera bool pattern_found = findChessboardCorners(
if (!capture.isOpened()) // check if opening camera stream succeeded frame, pattern_size, corners,
{ CALIB_CB_ADAPTIVE_THRESH +
cerr << "Camera could not be found. Exiting.\n"; CALIB_CB_NORMALIZE_IMAGE +
return -1; CALIB_CB_FAST_CHECK);
}
// set frame width and height by hand, defaults to 160x120
capture.set (CV_CAP_PROP_FRAME_WIDTH, 640);
capture.set (CV_CAP_PROP_FRAME_HEIGHT, 480);
// show camera image in a separate window if (!pattern_found)
namedWindow("Camera Image", CV_WINDOW_KEEPRATIO); return -1;
// store object points (world coords) and image points (image coords) for use in calibrateCamera
vector< vector <Point3f> > object_points;
vector< vector <Point2f> > image_points;
/// current frame, its grayscale counterpart and storage for the first frame // to tweak params: http://bit.ly/QyoU3k
Mat frame, gray_frame, first_frame; cornerSubPix(frame, corners, Size(11, 11), Size(-1, -1),
// flag for determining whether pattern was detected in at least one of the camera grabs TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 100,
bool acquired_samples = false; 0.1));
drawChessboardCorners(frame, pattern_size, Mat(corners),
pattern_found);
vector<Point3f> obj;
for (int j = 0; j < COUNT_SQUARES_X * COUNT_SQUARES_Y; ++j)
obj.push_back(Point3f(j / COUNT_SQUARES_X, j % COUNT_SQUARES_X, 0.0f));
// loop indefinitely and keep frame counter object_points.push_back(obj);
for(int count_frames = 0; ; ++count_frames) image_points.push_back(corners);
{ return 0;
capture >> frame; // get a new frame from camera }
cvtColor(frame, gray_frame, CV_BGR2GRAY); // convert current frame to grayscale
imshow("Camera Image", frame); // update camera image int run_interactive()
{
int key_pressed = waitKey(0); // get user key press namedWindow("Camera Image", CV_WINDOW_KEEPRATIO);
if (key_pressed == KEY_CLOSE_WINDOW || key_pressed == KEY_ESCAPE) break;
int count = 0;
if (user_mode == INTERACTIVE_MODE && key_pressed == KEY_SPACE) Mat frame;
{ vector<vector<Point3f> > object_points;
Size pattern_size(COUNT_SQUARES_X, COUNT_SQUARES_Y); // number of squares in the pattern, a.k.a, interior number of corners vector<vector<Point2f> > image_points;
vector <Point2f> corners; // storage for the detected corners in findChessboardConrners Mat intrinsic = Mat(3, 3, CV_32FC1);
bool pattern_found = findChessboardCorners( gray_frame, pattern_size, corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK); Mat distCoeffs;
vector<Mat> rvecs, tvecs;
if (pattern_found)
{ // open the default camera
if (count_frames == 0) first_frame = frame; VideoCapture capture(-1);
// if corners are detected, they are further refined by calculating subpixel corners from the grayscale image
// this iterative process terminates after the given number of iterations and error epsilon // check if opening camera stream succeeded
cornerSubPix(gray_frame, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 100, 0.1)); if (!capture.isOpened()) {
// draw the detected corners for debugging purposes cerr << "Camera could not be found. Exiting.\n";
drawChessboardCorners(frame, pattern_size, Mat(corners), pattern_found); return -1;
// show detected corners in a different window }
imshow("Detected pattern", frame);
for (;;) {
// build a grid of 3D points (z component is 0 because the pattern is in one plane) to fit the square pattern area (COUNT_SQUARES_X * COUNT_SQUARES_Y) cout << "Frame: " << count << endl;
vector< Point3f > pattern_points; Mat gray_frame;
for(int j = 0; j < COUNT_SQUARES_X * COUNT_SQUARES_Y; ++j) capture >> frame; // get a new frame from camera
pattern_points.push_back(Point3f(j/COUNT_SQUARES_X, j%COUNT_SQUARES_X, 0.0f)); cvtColor(frame, gray_frame, CV_BGR2GRAY);
imshow("Camera Image", frame);
// populate image points with corners and object points with grid points
image_points.push_back(corners); int key_pressed = waitKey(0);
object_points.push_back(pattern_points); if (key_pressed == KEY_CLOSE_WINDOW || key_pressed == KEY_ESCAPE)
cout << "Frame " << count_frames << " grabbed.\n"; break;
acquired_samples = true;
} if (key_pressed == KEY_SPACE) {
} if (detect_pattern(gray_frame, object_points, image_points) == 0) {
cout << "Frame " << count << " grabbed." << endl;
} } else {
cout << "pattern not found" << endl;
// if at least one video capture contains the pattern, perform calibration }
if (acquired_samples) }
{ }
Mat intrinsic = Mat(3, 3, CV_32FC1);
Mat distCoeffs; calibrateCamera(object_points, image_points, frame.size(), intrinsic,
vector<Mat> rvecs; distCoeffs, rvecs, tvecs);
vector<Mat> tvecs;
for (;;) {
// perform calibration, obtain instrinsic parameters and distortion coefficients capture >> frame;
cout << "\nCalibrating...\n"; Mat imageUndistorted;
calibrateCamera(object_points, image_points, frame.size(), intrinsic, distCoeffs, rvecs, tvecs); undistort(frame, imageUndistorted, intrinsic, distCoeffs);
imshow("win1", frame);
/* imshow("win2", imageUndistorted);
Mat grab2 = imread("./data/grab2.jpg"), grab2_undistorted; waitKey(1);
Mat grab4 = imread("./data/grab4.jpg"), grab4_undistorted; }
undistort(grab2, grab2_undistorted, intrinsic, distCoeffs);
undistort(grab4, grab4_undistorted, intrinsic, distCoeffs); capture.release();
}
imwrite("./data/grab2_undistorted.jpg", grab2_undistorted);
imwrite("./data/grab4_undistorted.jpg", grab4_undistorted); int run_prespecified(int argc, char **argv)
*/ {
int count = 0;
Mat undistorted_frame; Mat frame;
// apply the calibration transformation to the first frame and store image on disk vector<vector<Point3f> > object_points;
undistort(first_frame, undistorted_frame, intrinsic, distCoeffs); vector<vector<Point2f> > image_points;
imwrite("capture.jpg", first_frame); Mat intrinsic = Mat(3, 3, CV_32FC1);
imwrite("undistorted_frame.jpg", undistorted_frame); Mat distCoeffs;
cout << "Saved first frame to undistorted_frame.jpg\n"; vector<Mat> rvecs, tvecs;
cout << "Intrinsic parameters: \n" << intrinsic << "\n";
cout << "Distortion coefficients: \n" << distCoeffs << "\n"; for (int i = 0; i < argc; i++) {
} Mat gray_frame;
else cerr << endl << argv[i] << endl;
{ frame = imread(argv[i], CV_LOAD_IMAGE_COLOR);
cerr << "No frames grabbed!\n"; cvtColor(frame, gray_frame, CV_BGR2GRAY);
} imshow("Camera Image", frame);
if (detect_pattern(gray_frame, object_points, image_points) == 0) {
// the camera will be deinitialized automatically in VideoCapture destructor cout << "Frame " << i << " grabbed." << endl;
return 0; } else {
cout << "Pattern not found in frame " << i << endl;
}
}
cout << "Calibrating..." << endl;
calibrateCamera(object_points, image_points, frame.size(), intrinsic,
distCoeffs, rvecs, tvecs);
for (int i = 0; i < argc; i++) {
frame = imread(argv[i], CV_LOAD_IMAGE_COLOR);
Mat imageUndistorted;
undistort(frame, imageUndistorted, intrinsic, distCoeffs);
imshow("win1", frame);
imshow("win2", imageUndistorted);
waitKey(0);
}
return 0;
}
int main(int argc, char **argv)
{
int user_mode;
int specified_boards;
/* no arguments means interactive mode
* one or more arguments are image filenames */
if (argc == 1) {
run_interactive();
} else {
run_prespecified(argc-1, ++argv);
}
return 0;
} }

View file

@ -8,6 +8,7 @@ if __name__ == "__main__":
im = cv.LoadImage(filename, cv.CV_LOAD_IMAGE_GRAYSCALE) im = cv.LoadImage(filename, cv.CV_LOAD_IMAGE_GRAYSCALE)
im3 = cv.LoadImage(filename, cv.CV_LOAD_IMAGE_COLOR) im3 = cv.LoadImage(filename, cv.CV_LOAD_IMAGE_COLOR)
board_width, board_height = (4, 6) board_width, board_height = (4, 6)
square_size = 4
corner_count = board_width * board_height corner_count = board_width * board_height
found_all, corners = cv.FindChessboardCorners( im, (board_width, board_height)) found_all, corners = cv.FindChessboardCorners( im, (board_width, board_height))
@ -24,19 +25,25 @@ if __name__ == "__main__":
image_points = cv.CreateMat(corner_count, 2, cv.CV_32FC1) image_points = cv.CreateMat(corner_count, 2, cv.CV_32FC1)
point_counts = cv.CreateMat(1, 1, cv.CV_32SC1) point_counts = cv.CreateMat(1, 1, cv.CV_32SC1)
for jj in range(corner_count): for jj in range(corner_count):
cv.Set2D(object_points, jj, 0, float(jj/board_width)) #cv.Set2D(object_points, jj, 0, float(jj/board_width))
cv.Set2D(object_points, jj, 1, float(jj%board_width)) #cv.Set2D(object_points, jj, 1, float(jj%board_width))
cv.Set2D(object_points, jj, 2, float(0.0)) #cv.Set2D(object_points, jj, 2, float(0.0))
cv.Set2D(image_points, jj, 0, corners[jj][0]) cv.Set2D(image_points, jj, 0, corners[jj][0])
cv.Set2D(image_points, jj, 1, corners[jj][1]) cv.Set2D(image_points, jj, 1, corners[jj][1])
for i in range(board_height):
for j in range(board_width):
cv.Set2D(object_points, i*board_width+j, 0, float(i*square_size))
cv.Set2D(object_points, i*board_width+j, 1, float(j*square_size))
cv.Set2D(object_points, i*board_width+j, 2, float(0.0))
print i*board_width+j, i*square_size, j*square_size
cv.Set1D(point_counts, 0, corner_count) cv.Set1D(point_counts, 0, corner_count)
cv.CalibrateCamera2(object_points, image_points, point_counts, cv.GetSize(im3), camera_intrinsic_mat, distortion_mat, rotation_vecs, translation_vecs) cv.CalibrateCamera2(object_points, image_points, point_counts, cv.GetSize(im3), camera_intrinsic_mat, distortion_mat, rotation_vecs, translation_vecs)
undistorted = cv.CloneImage(im3); undistorted = cv.CloneImage(im3);
cv.Undistort2(im3, undistorted, camera_intrinsic_mat, distortion_mat) cv.Undistort2(im3, undistorted, camera_intrinsic_mat, distortion_mat)
cv.ShowImage("win", undistorted); cv.ShowImage("win", undistorted);
#cv.ShowImage("win", im3);
cv.WaitKey() cv.WaitKey()
else: else:
print "not found" print "not found"