Skip to content

Commit 4ae801d

Browse files
committed
example 19-2
1 parent d4a27fe commit 4ae801d

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ add_executable( example_17-01 example_17-01.cpp )
6565
add_executable( example_18-01 example_18-01.cpp )
6666
add_executable( example_18-01_from_disk example_18-01_from_disk.cpp )
6767
add_executable( example_19-01 example_19-01.cpp )
68+
add_executable( example_19-02 example_19-02.cpp )
6869
add_executable( example_20-01 example_20-01.cpp )
6970
add_executable( example_20-02 example_20-02.cpp )
7071
add_executable( example_21-01 example_21-01.cpp )
@@ -126,6 +127,7 @@ target_link_libraries( example_17-01 ${OpenCV_LIBS} )
126127
target_link_libraries( example_18-01 ${OpenCV_LIBS} )
127128
target_link_libraries( example_18-01_from_disk ${OpenCV_LIBS} )
128129
target_link_libraries( example_19-01 ${OpenCV_LIBS} )
130+
target_link_libraries( example_19-02 ${OpenCV_LIBS} )
129131
target_link_libraries( example_20-01 ${OpenCV_LIBS} )
130132
target_link_libraries( example_20-02 ${OpenCV_LIBS} )
131133
target_link_libraries( example_21-01 ${OpenCV_LIBS} )

example_19-02.cpp

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// Example 19-2. Computing the fundamental matrix using RANSAC
2+
#include <opencv2/opencv.hpp>
3+
#include <iostream>
4+
5+
using namespace std;
6+
void help(char *argv[]) {
7+
cout << "\nExample 19-2, Computing the fundamental matrix using RANSAC relating 2 images. Show the camera a checkerboard "
8+
<< "\nCall"
9+
<< "\n./example_19-2 <1:board_w> <2:board_h> <3:# of boards> <4:delay capture this many ms between frames> <5:scale the images 0-1>"
10+
<< "\n\nExample call:"
11+
<< "\n./example_19-2 12 12 20 500 0.5"
12+
<< "\n"
13+
<< endl;
14+
}
15+
16+
17+
// args: [board_w] [board_h] [number_of_boards] [delay]? [scale]?
18+
//
19+
int main(int argc, char *argv[]) {
20+
int n_boards = 0;
21+
float image_sf = 0.5f;
22+
float delay = 1.f;
23+
int board_w = 0;
24+
int board_h = 0;
25+
26+
// Will be set by input list
27+
if (argc < 4 || argc > 6) {
28+
cout << "\nERROR: Wrong number of input parameters, need 5, got " << argc - 1 << "\n";
29+
help(argv);
30+
return -1;
31+
}
32+
board_w = atoi(argv[1]);
33+
board_h = atoi(argv[2]);
34+
n_boards = atoi(argv[3]);
35+
delay = atof(argv[4]);
36+
image_sf = atof(argv[5]);
37+
int board_n = board_w * board_h;
38+
cv::Size board_sz = cv::Size(board_w, board_h);
39+
cv::VideoCapture capture(0);
40+
41+
if (!capture.isOpened()) {
42+
cout << "\nCouldn't open the camera\n";
43+
help(argv);
44+
return -1;
45+
}
46+
// Allocate Storage
47+
//
48+
vector<vector<cv::Point2f> > image_points;
49+
vector<vector<cv::Point3f> > object_points;
50+
// Capture corner views; loop until we've got n_boards number of
51+
// successful captures (meaning: all corners on each
52+
// board are found).
53+
//
54+
double last_captured_timestamp = 0;
55+
cv::Size image_size;
56+
while (image_points.size() < (size_t)n_boards) {
57+
cv::Mat image0, image;
58+
capture >> image0;
59+
image_size = image0.size();
60+
resize(image0, image, cv::Size(), image_sf, image_sf, cv::INTER_LINEAR);
61+
// Find the board
62+
//
63+
vector<cv::Point2f> corners;
64+
bool found = cv::findChessboardCorners(image, board_sz, corners);
65+
// Draw it
66+
//
67+
cv::drawChessboardCorners(image, board_sz, corners, found);
68+
// If we got a good board, add it to our data
69+
//
70+
double timestamp = (double)clock() / CLOCKS_PER_SEC;
71+
if (found && timestamp - last_captured_timestamp > 1) {
72+
last_captured_timestamp = timestamp;
73+
image ^= cv::Scalar::all(255);
74+
75+
cv::Mat mcorners(corners);
76+
// do not copy the data
77+
mcorners *= (1. / image_sf);
78+
// scale corner coordinates
79+
image_points.push_back(corners);
80+
object_points.push_back(vector<cv::Point3f>());
81+
vector<cv::Point3f> &opts = object_points.back();
82+
opts.resize(board_n);
83+
for (int j = 0; j < board_n; j++) {
84+
opts[j] = cv::Point3f((float)(j / board_w), (float)(j % board_w), 0.f);
85+
}
86+
cout << "Collected our " << (int)image_points.size() << " of " << n_boards
87+
<< " needed chessboard images\n" << endl;
88+
}
89+
// in color if we did collect the image
90+
//
91+
cv::imshow("Calibration", image);
92+
if ((cv::waitKey(30) & 255) == 27)
93+
return -1;
94+
}
95+
// end collection while() loop.
96+
cv::destroyWindow("Calibration");
97+
cout << "\n\n*** CALIBRATING THE CAMERA...\n" << endl;
98+
// Calibrate the camera!
99+
//
100+
cv::Mat intrinsic_matrix, distortion_coeffs;
101+
double err = cv::calibrateCamera(
102+
object_points, // Vector of vectors of points
103+
// from the calibration pattern
104+
image_points, // Vector of vectors of projected
105+
// locations (on images)
106+
image_size, // Size of images used
107+
intrinsic_matrix, // Output camera matrix
108+
distortion_coeffs, // Output distortion coefficients
109+
cv::noArray(), // We'll pass on the rotation vectors...
110+
cv::noArray(), // ...and the translation vectors
111+
cv::CALIB_ZERO_TANGENT_DIST | cv::CALIB_FIX_PRINCIPAL_POINT);
112+
113+
// Save the intrinsics and distortions
114+
cout << " *** DONE!\n\nReprojection error is " << err
115+
<< "\nStoring Intrinsics.xml and Distortions.xml files\n\n";
116+
cv::FileStorage fs("intrinsics.xml", cv::FileStorage::WRITE);
117+
fs << "image_width" << image_size.width << "image_height" << image_size.height
118+
<< "camera_matrix" << intrinsic_matrix << "distortion_coefficients"
119+
<< distortion_coeffs;
120+
fs.release();
121+
122+
// Example of loading these matrices back in:
123+
//
124+
fs.open("intrinsics.xml", cv::FileStorage::READ);
125+
cout << "\nimage width: " << (int)fs["image_width"];
126+
cout << "\nimage height: " << (int)fs["image_height"];
127+
cv::Mat intrinsic_matrix_loaded, distortion_coeffs_loaded;
128+
fs["camera_matrix"] >> intrinsic_matrix_loaded;
129+
fs["distortion_coefficients"] >> distortion_coeffs_loaded;
130+
cout << "\nintrinsic matrix:" << intrinsic_matrix_loaded;
131+
cout << "\ndistortion coefficients: " << distortion_coeffs_loaded << endl;
132+
133+
// Compute Fundamental Matrix Between the first
134+
// and the second frames:
135+
//
136+
cv::undistortPoints(
137+
image_points[0], // Observed point coordinates (from frame 0)
138+
image_points[0], // undistorted coordinates (in this case,
139+
// the same array as above)
140+
intrinsic_matrix, // Intrinsics, from cv::calibrateCamera()
141+
distortion_coeffs, // Distortion coefficients, also
142+
// from cv::calibrateCamera()
143+
cv::Mat(), // Rectification transformation (but
144+
// here, we don't need this)
145+
intrinsic_matrix // New camera matrix
146+
);
147+
148+
cv::undistortPoints(
149+
image_points[1], // Observed point coordinates (from frame 1)
150+
image_points[1], // undistorted coordinates (in this case,
151+
// the same array as above)
152+
intrinsic_matrix, // Intrinsics, from cv::calibrateCamera()
153+
distortion_coeffs, // Distortion coefficients, also
154+
// from cv::calibrateCamera()
155+
cv::Mat(), // Rectification transformation (but
156+
// here, we don't need this)
157+
intrinsic_matrix // New camera matrix
158+
);
159+
160+
// Since all the found chessboard corners are inliers, i.e., they
161+
// must satisfy epipolar constraints, here we are using the
162+
// fastest, and the most accurate (in this case) 8-point algorithm.
163+
//
164+
cv::Mat F = cv::findFundamentalMat( // Return computed matrix
165+
image_points[0], // Points from frame 0
166+
image_points[1], // Points from frame 1
167+
cv::FM_8POINT // Use the 8-point algorithm
168+
);
169+
cout << "Fundamental matrix: " << F << endl;
170+
171+
// Build the undistort map which we will use for all
172+
// subsequent frames.
173+
//
174+
cv::Mat map1, map2;
175+
cv::initUndistortRectifyMap(
176+
intrinsic_matrix_loaded, // Our camera matrix
177+
distortion_coeffs_loaded, // Our distortion coefficients
178+
cv::Mat(), // (Optional) Rectification, don't
179+
// need.
180+
intrinsic_matrix_loaded, // "New" matrix, here it's the same
181+
// as the first argument.
182+
image_size, // Size of undistorted image we want
183+
CV_16SC2, // Specifies the format of map to use
184+
map1, // Integerized coordinates
185+
map2 // Fixed-point offsets for
186+
// elements of map1
187+
);
188+
189+
// Just run the camera to the screen, now showing the raw and
190+
// the undistorted image.
191+
//
192+
for (;;) {
193+
cv::Mat image, image0;
194+
capture >> image0;
195+
if (image0.empty())
196+
break;
197+
cv::remap(image0, // Input image
198+
image, // Output image
199+
map1, // Integer part of map
200+
map2, // Fixed point part of map
201+
cv::INTER_LINEAR, cv::BORDER_CONSTANT,
202+
cv::Scalar() // Set border values to black
203+
);
204+
cv::imshow("Undistorted", image);
205+
if ((cv::waitKey(30) & 255) == 27)
206+
break;
207+
}
208+
return 1;
209+
}

0 commit comments

Comments
 (0)