Skip to content

Commit

Permalink
update tutorials and samples
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrPanov committed Apr 12, 2024
1 parent 7e1b089 commit 90485d4
Show file tree
Hide file tree
Showing 18 changed files with 414 additions and 1,266 deletions.
3 changes: 2 additions & 1 deletion modules/aruco/include/opencv2/aruco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ CV_EXPORTS_W void getBoardObjectAndImagePoints(const Ptr<Board> &board, InputArr
InputArray detectedIds, OutputArray objPoints, OutputArray imgPoints);


/** @deprecated Use cv::solvePnP
/** @deprecated Use Board::matchImagePoints and cv::solvePnP
*/
CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, const Ptr<Board> &board,
InputArray cameraMatrix, InputArray distCoeffs, InputOutputArray rvec,
Expand All @@ -75,6 +75,7 @@ CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, c
* This function estimates a Charuco board pose from some detected corners.
* The function checks if the input corners are enough and valid to perform pose estimation.
* If pose estimation is valid, returns true, else returns false.
* @deprecated Use CharucoBoard::matchImagePoints and cv::solvePnP
* @sa use cv::drawFrameAxes to get world coordinate system axis for object points
*/
CV_EXPORTS_W bool estimatePoseCharucoBoard(InputArray charucoCorners, InputArray charucoIds,
Expand Down
23 changes: 15 additions & 8 deletions modules/aruco/include/opencv2/aruco/aruco_calib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ namespace aruco {
* PatternPositionType defines center this system and axes direction.
* Axis X (red color) - first coordinate, axis Y (green color) - second coordinate,
* axis Z (blue color) - third coordinate.
* @sa estimatePoseSingleMarkers(), check tutorial_aruco_detection in aruco contrib
*
* @deprecated Use Board::matchImagePoints and cv::solvePnP
*
* @sa estimatePoseSingleMarkers()
*/
enum PatternPositionType {
/** @brief The marker coordinate system is centered on the middle of the marker.
*
* The coordinates of the four corners (CCW order) of the marker in its own coordinate system are:
* (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
* (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0).
*
* These pattern points define this coordinate system:
* ![Image with axes drawn](tutorials/images/singlemarkersaxes2.jpg)
*/
ARUCO_CCW_CENTER,
/** @brief The marker coordinate system is centered on the top-left corner of the marker.
Expand All @@ -35,9 +35,6 @@ enum PatternPositionType {
* (0, 0, 0), (markerLength, 0, 0),
* (markerLength, markerLength, 0), (0, markerLength, 0).
*
* These pattern points define this coordinate system:
* ![Image with axes drawn](tutorials/images/singlemarkersaxes.jpg)
*
* These pattern dots are convenient to use with a chessboard/ChArUco board.
*/
ARUCO_CW_TOP_LEFT_CORNER
Expand All @@ -50,7 +47,10 @@ enum PatternPositionType {
* rvec and tvec values as initial approximations of the rotation and translation vectors, respectively, and further
* optimizes them (default false).
* @param solvePnPMethod Method for solving a PnP problem: see @ref calib3d_solvePnP_flags (default SOLVEPNP_ITERATIVE).
* @sa PatternPositionType, solvePnP(), check tutorial_aruco_detection in aruco contrib
*
* @deprecated Use Board::matchImagePoints and cv::solvePnP
*
* @sa PatternPositionType, solvePnP()
*/
struct CV_EXPORTS_W_SIMPLE EstimateParameters {
CV_PROP_RW PatternPositionType pattern;
Expand Down Expand Up @@ -95,6 +95,8 @@ struct CV_EXPORTS_W_SIMPLE EstimateParameters {
* This function calibrates a camera using an Aruco Board. The function receives a list of
* detected markers from several views of the Board. The process is similar to the chessboard
* calibration in calibrateCamera(). The function returns the final re-projection error.
*
* @deprecated Use Board::matchImagePoints and cv::solvePnP
*/
CV_EXPORTS_AS(calibrateCameraArucoExtended)
double calibrateCameraAruco(InputArrayOfArrays corners, InputArray ids, InputArray counter, const Ptr<Board> &board,
Expand All @@ -105,6 +107,7 @@ double calibrateCameraAruco(InputArrayOfArrays corners, InputArray ids, InputArr

/** @overload
* @brief It's the same function as #calibrateCameraAruco but without calibration error estimation.
* @deprecated Use Board::matchImagePoints and cv::solvePnP
*/
CV_EXPORTS_W double calibrateCameraAruco(InputArrayOfArrays corners, InputArray ids, InputArray counter,
const Ptr<Board> &board, Size imageSize, InputOutputArray cameraMatrix,
Expand Down Expand Up @@ -147,6 +150,8 @@ CV_EXPORTS_W double calibrateCameraAruco(InputArrayOfArrays corners, InputArray
* This function calibrates a camera using a set of corners of a Charuco Board. The function
* receives a list of detected corners and its identifiers from several views of the Board.
* The function returns the final re-projection error.
*
* @deprecated Use CharucoBoard::matchImagePoints and cv::solvePnP
*/
CV_EXPORTS_AS(calibrateCameraCharucoExtended)
double calibrateCameraCharuco(InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds,
Expand All @@ -158,6 +163,8 @@ double calibrateCameraCharuco(InputArrayOfArrays charucoCorners, InputArrayOfArr

/**
* @brief It's the same function as #calibrateCameraCharuco but without calibration error estimation.
*
* @deprecated Use CharucoBoard::matchImagePoints and cv::solvePnP
*/
CV_EXPORTS_W double calibrateCameraCharuco(InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds,
const Ptr<CharucoBoard> &board, Size imageSize,
Expand Down
2 changes: 2 additions & 0 deletions modules/aruco/include/opencv2/aruco/charuco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ CV_EXPORTS_W void detectCharucoDiamond(InputArray image, InputArrayOfArrays mark
* @param borderBits width of the marker borders.
*
* This function return the image of a ChArUco marker, ready to be printed.
*
* @deprecated Use CharucoBoard::generateImage()
*/
CV_EXPORTS_W void drawCharucoDiamond(const Ptr<Dictionary> &dictionary, Vec4i ids, int squareLength,
int markerLength, OutputArray img, int marginSize = 0,
Expand Down
44 changes: 44 additions & 0 deletions modules/aruco/samples/aruco_samples_utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,48 @@ inline static bool saveCameraParams(const std::string &filename, cv::Size imageS
return true;
}


inline static cv::aruco::DetectorParameters readDetectorParamsFromCommandLine(cv::CommandLineParser &parser) {
cv::aruco::DetectorParameters detectorParams;
if (parser.has("dp")) {
cv::FileStorage fs(parser.get<std::string>("dp"), cv::FileStorage::READ);
bool readOk = detectorParams.readDetectorParameters(fs.root());
if(!readOk) {
throw std::runtime_error("Invalid detector parameters file\n");
}
}
return detectorParams;
}

inline static void readCameraParamsFromCommandLine(cv::CommandLineParser &parser, cv::Mat& camMatrix, cv::Mat& distCoeffs) {
//! [camDistCoeffs]
if(parser.has("c")) {
bool readOk = readCameraParameters(parser.get<std::string>("c"), camMatrix, distCoeffs);
if(!readOk) {
throw std::runtime_error("Invalid camera file\n");
}
}
//! [camDistCoeffs]
}

inline static cv::aruco::Dictionary readDictionatyFromCommandLine(cv::CommandLineParser &parser) {
cv::aruco::Dictionary dictionary;
if (parser.has("cd")) {
cv::FileStorage fs(parser.get<std::string>("cd"), cv::FileStorage::READ);
bool readOk = dictionary.readDictionary(fs.root());
if(!readOk) {
throw std::runtime_error("Invalid dictionary file\n");
}
}
else {
int dictionaryId = parser.has("d") ? parser.get<int>("d"): cv::aruco::DICT_4X4_50;
if (!parser.has("d")) {
std::cout << "The default DICT_4X4_50 dictionary has been selected, you could "
"select the specific dictionary using flags -d or -cd." << std::endl;
}
dictionary = cv::aruco::getPredefinedDictionary(dictionaryId);
}
return dictionary;
}

}
88 changes: 23 additions & 65 deletions modules/aruco/samples/calibrate_camera.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html

#include <ctime>
#include <iostream>
#include <vector>
#include <opencv2/calib3d.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/objdetect/aruco_detector.hpp>
#include "aruco_samples_utility.hpp"

using namespace std;
Expand All @@ -31,7 +27,7 @@ const char* keys =
"DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
"DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
"{cd | | Input file with custom dictionary }"
"{@outfile |<none> | Output file with calibrated camera parameters }"
"{@outfile |cam.yml| Output file with calibrated camera parameters }"
"{v | | Input from video file, if ommited, input comes from camera }"
"{ci | 0 | Camera id if input doesnt come from video (-v) }"
"{dp | | File of marker detector parameters }"
Expand All @@ -55,7 +51,7 @@ int main(int argc, char *argv[]) {
int markersY = parser.get<int>("h");
float markerLength = parser.get<float>("l");
float markerSeparation = parser.get<float>("s");
string outputFile = parser.get<String>(0);
string outputFile = parser.get<string>(0);

int calibrationFlags = 0;
float aspectRatio = 1;
Expand All @@ -66,15 +62,8 @@ int main(int argc, char *argv[]) {
if(parser.get<bool>("zt")) calibrationFlags |= CALIB_ZERO_TANGENT_DIST;
if(parser.get<bool>("pc")) calibrationFlags |= CALIB_FIX_PRINCIPAL_POINT;

aruco::DetectorParameters detectorParams;
if(parser.has("dp")) {
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
bool readOk = detectorParams.readDetectorParameters(fs.root());
if(!readOk) {
cerr << "Invalid detector parameters file" << endl;
return 0;
}
}
aruco::Dictionary dictionary = readDictionatyFromCommandLine(parser);
aruco::DetectorParameters detectorParams = readDetectorParamsFromCommandLine(parser);

bool refindStrategy = parser.get<bool>("rs");
int camId = parser.get<int>("ci");
Expand All @@ -99,36 +88,16 @@ int main(int argc, char *argv[]) {
waitTime = 10;
}

aruco::Dictionary dictionary = aruco::getPredefinedDictionary(0);
if (parser.has("d")) {
int dictionaryId = parser.get<int>("d");
dictionary = aruco::getPredefinedDictionary(
aruco::PredefinedDictionaryType(dictionaryId)
);
}
else if (parser.has("cd")) {
FileStorage fs(parser.get<std::string>("cd"), FileStorage::READ);
bool readOk = dictionary.aruco::Dictionary::readDictionary(fs.root());
if(!readOk) {
cerr << "Invalid dictionary file" << endl;
return 0;
}
}
else {
cerr << "Dictionary not specified" << endl;
return 0;
}

// Create board object
//! [CalibrationWithArucoBoard1]
// Create board object and ArucoDetector
aruco::GridBoard gridboard(Size(markersX, markersY), markerLength, markerSeparation, dictionary);
aruco::ArucoDetector detector(dictionary, detectorParams);

// Collected frames for calibration
vector<vector<vector<Point2f>>> allMarkerCorners;
vector<vector<int>> allMarkerIds;
Size imageSize;

aruco::ArucoDetector detector(dictionary, detectorParams);

while(inputVideo.grab()) {
Mat image, imageCopy;
inputVideo.retrieve(image);
Expand All @@ -141,10 +110,9 @@ int main(int argc, char *argv[]) {

// Refind strategy to detect more markers
if(refindStrategy) {
detector.refineDetectedMarkers(
image, gridboard, markerCorners, markerIds, rejectedMarkers
);
detector.refineDetectedMarkers(image, gridboard, markerCorners, markerIds, rejectedMarkers);
}
//! [CalibrationWithArucoBoard1]

// Draw results
image.copyTo(imageCopy);
Expand All @@ -153,10 +121,8 @@ int main(int argc, char *argv[]) {
aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds);
}

putText(
imageCopy, "Press 'c' to add current frame. 'ESC' to finish and calibrate",
Point(10, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 0), 2
);
putText(imageCopy, "Press 'c' to add current frame. 'ESC' to finish and calibrate",
Point(10, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 0), 2);
imshow("out", imageCopy);

// Wait for key pressed
Expand All @@ -166,19 +132,21 @@ int main(int argc, char *argv[]) {
break;
}

//! [CalibrationWithArucoBoard2]
if(key == 'c' && !markerIds.empty()) {
cout << "Frame captured" << endl;
allMarkerCorners.push_back(markerCorners);
allMarkerIds.push_back(markerIds);
imageSize = image.size();
}
}
//! [CalibrationWithArucoBoard2]

if(allMarkerIds.empty()) {
cerr << "Not enough captures for calibration" << endl;
return 0;
throw std::runtime_error("Not enough captures for calibration\n");
}

//! [CalibrationWithArucoBoard3]
Mat cameraMatrix, distCoeffs;

if(calibrationFlags & CALIB_FIX_ASPECT_RATIO) {
Expand All @@ -195,10 +163,7 @@ int main(int argc, char *argv[]) {
for(size_t frame = 0; frame < nFrames; frame++) {
Mat currentImgPoints, currentObjPoints;

gridboard.matchImagePoints(
allMarkerCorners[frame], allMarkerIds[frame],
currentObjPoints, currentImgPoints
);
gridboard.matchImagePoints(allMarkerCorners[frame], allMarkerIds[frame], currentObjPoints, currentImgPoints);

if(currentImgPoints.total() > 0 && currentObjPoints.total() > 0) {
processedImagePoints.push_back(currentImgPoints);
Expand All @@ -207,24 +172,17 @@ int main(int argc, char *argv[]) {
}

// Calibrate camera
double repError = calibrateCamera(
processedObjectPoints, processedImagePoints, imageSize,
cameraMatrix, distCoeffs, noArray(), noArray(), noArray(),
noArray(), noArray(), calibrationFlags
);

bool saveOk = saveCameraParams(
outputFile, imageSize, aspectRatio, calibrationFlags, cameraMatrix,
distCoeffs, repError
);
double repError = calibrateCamera(processedObjectPoints, processedImagePoints, imageSize, cameraMatrix, distCoeffs,
noArray(), noArray(), noArray(), noArray(), noArray(), calibrationFlags);
//! [CalibrationWithArucoBoard3]
bool saveOk = saveCameraParams(outputFile, imageSize, aspectRatio, calibrationFlags,
cameraMatrix, distCoeffs, repError);

if(!saveOk) {
cerr << "Cannot save output file" << endl;
return 0;
throw std::runtime_error("Cannot save output file\n");
}

cout << "Rep Error: " << repError << endl;
cout << "Calibration saved to " << outputFile << endl;

return 0;
}
Loading

0 comments on commit 90485d4

Please sign in to comment.