forked from opencv/opencv
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tutorial and codes for the homography tutorial.
- Loading branch information
Showing
22 changed files
with
1,196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
467 changes: 467 additions & 0 deletions
467
doc/tutorials/features2d/homography/homography.markdown
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file added
BIN
+44.9 KB
doc/tutorials/features2d/homography/images/homography_camera_displacement.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+80.5 KB
...torials/features2d/homography/images/homography_camera_displacement_compare.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+84.3 KB
...tutorials/features2d/homography/images/homography_camera_displacement_poses.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+33.3 KB
doc/tutorials/features2d/homography/images/homography_panorama_stitching.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+47.7 KB
doc/tutorials/features2d/homography/images/homography_perspective_correction.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+129 KB
...es2d/homography/images/homography_perspective_correction_chessboard_matches.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+81 KB
...tures2d/homography/images/homography_perspective_correction_chessboard_warp.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+63.7 KB
doc/tutorials/features2d/homography/images/homography_pose_chessboard_corners.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+30.6 KB
doc/tutorials/features2d/homography/images/homography_pose_estimation.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+75.7 KB
doc/tutorials/features2d/homography/images/homography_source_desired_images.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+9.84 KB
doc/tutorials/features2d/homography/images/homography_transformation_example1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+41.6 KB
doc/tutorials/features2d/homography/images/homography_transformation_example2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+30 KB
doc/tutorials/features2d/homography/images/homography_transformation_example3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
samples/cpp/tutorial_code/features2D/Homography/left_intrinsics.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
%YAML:1.0 | ||
--- | ||
image_width: 640 | ||
image_height: 480 | ||
board_width: 9 | ||
board_height: 6 | ||
square_size: 1. | ||
aspectRatio: 1. | ||
flags: 2 | ||
camera_matrix: !!opencv-matrix | ||
rows: 3 | ||
cols: 3 | ||
dt: d | ||
data: [ 5.3591575307485539e+02, 0., 3.4228314953752817e+02, 0., | ||
5.3591575307485539e+02, 2.3557082321320789e+02, 0., 0., 1. ] | ||
distortion_coefficients: !!opencv-matrix | ||
rows: 5 | ||
cols: 1 | ||
dt: d | ||
data: [ -2.6637290673868386e-01, -3.8586722644459073e-02, | ||
1.7831841406179300e-03, -2.8122035403651473e-04, | ||
2.3838760574917545e-01 ] | ||
avg_reprojection_error: 3.9259109564815858e-01 |
156 changes: 156 additions & 0 deletions
156
.../cpp/tutorial_code/features2D/Homography/tutorial_homography_ex1_pose_from_homography.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
#include <iostream> | ||
#include <opencv2/opencv_modules.hpp> | ||
#ifdef HAVE_OPENCV_ARUCO | ||
#include <opencv2/opencv.hpp> | ||
#include <opencv2/aruco.hpp> | ||
|
||
using namespace std; | ||
using namespace cv; | ||
|
||
namespace | ||
{ | ||
enum Pattern { CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID }; | ||
|
||
void calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners, Pattern patternType = CHESSBOARD) | ||
{ | ||
corners.resize(0); | ||
|
||
switch (patternType) | ||
{ | ||
case CHESSBOARD: | ||
case CIRCLES_GRID: | ||
//! [compute-chessboard-object-points] | ||
for( int i = 0; i < boardSize.height; i++ ) | ||
for( int j = 0; j < boardSize.width; j++ ) | ||
corners.push_back(Point3f(float(j*squareSize), | ||
float(i*squareSize), 0)); | ||
//! [compute-chessboard-object-points] | ||
break; | ||
|
||
case ASYMMETRIC_CIRCLES_GRID: | ||
for( int i = 0; i < boardSize.height; i++ ) | ||
for( int j = 0; j < boardSize.width; j++ ) | ||
corners.push_back(Point3f(float((2*j + i % 2)*squareSize), | ||
float(i*squareSize), 0)); | ||
break; | ||
|
||
default: | ||
CV_Error(Error::StsBadArg, "Unknown pattern type\n"); | ||
} | ||
} | ||
|
||
void poseEstimationFromCoplanarPoints(const string &imgPath, const string &intrinsicsPath, const Size &patternSize, | ||
const float squareSize) | ||
{ | ||
Mat img = imread(imgPath); | ||
Mat img_corners = img.clone(), img_pose = img.clone(); | ||
|
||
//! [find-chessboard-corners] | ||
vector<Point2f> corners; | ||
bool found = findChessboardCorners(img, patternSize, corners); | ||
//! [find-chessboard-corners] | ||
|
||
if (!found) | ||
{ | ||
cout << "Cannot find chessboard corners." << endl; | ||
return; | ||
} | ||
drawChessboardCorners(img_corners, patternSize, corners, found); | ||
imshow("Chessboard corners detection", img_corners); | ||
|
||
//! [compute-object-points] | ||
vector<Point3f> objectPoints; | ||
calcChessboardCorners(patternSize, squareSize, objectPoints); | ||
vector<Point2f> objectPointsPlanar; | ||
for (size_t i = 0; i < objectPoints.size(); i++) | ||
{ | ||
objectPointsPlanar.push_back(Point2f(objectPoints[i].x, objectPoints[i].y)); | ||
} | ||
//! [compute-object-points] | ||
|
||
//! [load-intrinsics] | ||
FileStorage fs(intrinsicsPath, FileStorage::READ); | ||
Mat cameraMatrix, distCoeffs; | ||
fs["camera_matrix"] >> cameraMatrix; | ||
fs["distortion_coefficients"] >> distCoeffs; | ||
//! [load-intrinsics] | ||
|
||
//! [compute-image-points] | ||
vector<Point2f> imagePoints; | ||
undistortPoints(corners, imagePoints, cameraMatrix, distCoeffs); | ||
//! [compute-image-points] | ||
|
||
//! [estimate-homography] | ||
Mat H = findHomography(objectPointsPlanar, imagePoints); | ||
cout << "H:\n" << H << endl; | ||
//! [estimate-homography] | ||
|
||
//! [pose-from-homography] | ||
// Normalization to ensure that ||c1|| = 1 | ||
double norm = sqrt(H.at<double>(0,0)*H.at<double>(0,0) + | ||
H.at<double>(1,0)*H.at<double>(1,0) + | ||
H.at<double>(2,0)*H.at<double>(2,0)); | ||
|
||
H /= norm; | ||
Mat c1 = H.col(0); | ||
Mat c2 = H.col(1); | ||
Mat c3 = c1.cross(c2); | ||
|
||
Mat tvec = H.col(2); | ||
Mat R(3, 3, CV_64F); | ||
|
||
for (int i = 0; i < 3; i++) | ||
{ | ||
R.at<double>(i,0) = c1.at<double>(i,0); | ||
R.at<double>(i,1) = c2.at<double>(i,0); | ||
R.at<double>(i,2) = c3.at<double>(i,0); | ||
} | ||
//! [pose-from-homography] | ||
|
||
//! [display-pose] | ||
Mat rvec; | ||
Rodrigues(R, rvec); | ||
aruco::drawAxis(img_pose, cameraMatrix, distCoeffs, rvec, tvec, 2*squareSize); | ||
imshow("Pose from coplanar points", img_pose); | ||
waitKey(); | ||
//! [display-pose] | ||
} | ||
|
||
const char* about = "Code for homography tutorial.\n" | ||
"Example 1: pose from homography with coplanar points.\n"; | ||
|
||
const char* params | ||
= "{ h help | false | print usage }" | ||
"{ image | | path to a chessboard image (left04.jpg) }" | ||
"{ intrinsics | | path to camera intrinsics (left_intrinsics.yml) }" | ||
"{ width w | 9 | chessboard width }" | ||
"{ height h | 6 | chessboard height }" | ||
"{ square_size | 0.025 | chessboard square size }"; | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
CommandLineParser parser(argc, argv, params); | ||
|
||
if (parser.get<bool>("help")) | ||
{ | ||
cout << about << endl; | ||
parser.printMessage(); | ||
return 0; | ||
} | ||
|
||
Size patternSize(parser.get<int>("width"), parser.get<int>("height")); | ||
float squareSize = (float) parser.get<double>("square_size"); | ||
poseEstimationFromCoplanarPoints(parser.get<string>("image"), | ||
parser.get<string>("intrinsics"), | ||
patternSize, squareSize); | ||
|
||
return 0; | ||
} | ||
#else | ||
int main() | ||
{ | ||
std::cerr << "FATAL ERROR: This sample requires opencv_aruco module (from opencv_contrib)" << std::endl; | ||
return 0; | ||
} | ||
#endif |
131 changes: 131 additions & 0 deletions
131
...pp/tutorial_code/features2D/Homography/tutorial_homography_ex2_perspective_correction.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <iostream> | ||
#include <opencv2/opencv_modules.hpp> | ||
#ifdef HAVE_OPENCV_ARUCO | ||
#include <opencv2/opencv.hpp> | ||
#include <opencv2/aruco.hpp> | ||
|
||
using namespace std; | ||
using namespace cv; | ||
|
||
namespace | ||
{ | ||
enum Pattern { CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID }; | ||
|
||
Scalar randomColor( RNG& rng ) | ||
{ | ||
int icolor = (unsigned int) rng; | ||
return Scalar( icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255 ); | ||
} | ||
|
||
void calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners, Pattern patternType = CHESSBOARD) | ||
{ | ||
corners.resize(0); | ||
|
||
switch (patternType) | ||
{ | ||
case CHESSBOARD: | ||
case CIRCLES_GRID: | ||
for( int i = 0; i < boardSize.height; i++ ) | ||
for( int j = 0; j < boardSize.width; j++ ) | ||
corners.push_back(Point3f(float(j*squareSize), | ||
float(i*squareSize), 0)); | ||
break; | ||
|
||
case ASYMMETRIC_CIRCLES_GRID: | ||
for( int i = 0; i < boardSize.height; i++ ) | ||
for( int j = 0; j < boardSize.width; j++ ) | ||
corners.push_back(Point3f(float((2*j + i % 2)*squareSize), | ||
float(i*squareSize), 0)); | ||
break; | ||
|
||
default: | ||
CV_Error(Error::StsBadArg, "Unknown pattern type\n"); | ||
} | ||
} | ||
|
||
void perspectiveCorrection(const string &img1Path, const string &img2Path, const Size &patternSize, RNG &rng) | ||
{ | ||
Mat img1 = imread(img1Path); | ||
Mat img2 = imread(img2Path); | ||
|
||
//! [find-corners] | ||
vector<Point2f> corners1, corners2; | ||
bool found1 = findChessboardCorners(img1, patternSize, corners1); | ||
bool found2 = findChessboardCorners(img2, patternSize, corners2); | ||
//! [find-corners] | ||
|
||
if (!found1 || !found2) | ||
{ | ||
cout << "Error, cannot find the chessboard corners in both images." << endl; | ||
return; | ||
} | ||
|
||
//! [estimate-homography] | ||
Mat H = findHomography(corners1, corners2); | ||
cout << "H:\n" << H << endl; | ||
//! [estimate-homography] | ||
|
||
//! [warp-chessboard] | ||
Mat img1_warp; | ||
warpPerspective(img1, img1_warp, H, img1.size()); | ||
//! [warp-chessboard] | ||
|
||
Mat img_draw_warp; | ||
hconcat(img2, img1_warp, img_draw_warp); | ||
imshow("Desired chessboard view / Warped source chessboard view", img_draw_warp); | ||
|
||
//! [compute-transformed-corners] | ||
Mat img_draw_matches; | ||
hconcat(img1, img2, img_draw_matches); | ||
for (size_t i = 0; i < corners1.size(); i++) | ||
{ | ||
Mat pt1 = (Mat_<double>(3,1) << corners1[i].x, corners1[i].y, 1); | ||
Mat pt2 = H * pt1; | ||
pt2 /= pt2.at<double>(2); | ||
|
||
Point end( (int) (img1.cols + pt2.at<double>(0)), (int) pt2.at<double>(1) ); | ||
line(img_draw_matches, corners1[i], end, randomColor(rng), 2); | ||
} | ||
|
||
imshow("Draw matches", img_draw_matches); | ||
waitKey(); | ||
//! [compute-transformed-corners] | ||
} | ||
|
||
const char* about = "Code for homography tutorial.\n" | ||
"Example 2: perspective correction.\n"; | ||
|
||
const char* params | ||
= "{ h help | false | print usage }" | ||
"{ image1 | | path to the source chessboard image (left02.jpg) }" | ||
"{ image2 | | path to the desired chessboard image (left01.jpg) }" | ||
"{ width w | 9 | chessboard width }" | ||
"{ height h | 6 | chessboard height }"; | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
cv::RNG rng( 0xFFFFFFFF ); | ||
CommandLineParser parser(argc, argv, params); | ||
|
||
if (parser.get<bool>("help")) | ||
{ | ||
cout << about << endl; | ||
parser.printMessage(); | ||
return 0; | ||
} | ||
|
||
Size patternSize(parser.get<int>("width"), parser.get<int>("height")); | ||
perspectiveCorrection(parser.get<string>("image1"), | ||
parser.get<string>("image2"), | ||
patternSize, rng); | ||
|
||
return 0; | ||
} | ||
#else | ||
int main() | ||
{ | ||
std::cerr << "FATAL ERROR: This sample requires opencv_aruco module (from opencv_contrib)" << std::endl; | ||
return 0; | ||
} | ||
#endif |
Oops, something went wrong.