Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move contrib charuco to main objdetect #22986

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
99d3bc7
move charuco, add new CharucoDetector API
AleksandrPanov Dec 20, 2022
319d71f
fix interactive-calibration tool
AleksandrPanov Dec 20, 2022
5be4c66
add matchImagePoints() for Charuco
AleksandrPanov Dec 20, 2022
0b8e274
fix interactive-calibration tool
AleksandrPanov Dec 20, 2022
20f2f7e
create charuco_detector.cpp/hpp
AleksandrPanov Dec 20, 2022
56d17ff
fixes
AleksandrPanov Dec 20, 2022
0e56eee
add detectDiamonds
AleksandrPanov Dec 20, 2022
f4041a2
move aruco tests to objdetect
AleksandrPanov Dec 21, 2022
dcd11e4
fix solvePnP
AleksandrPanov Dec 21, 2022
100cc55
move aruco perf tests to objdetect
AleksandrPanov Dec 21, 2022
2a024f5
swap detectBoard params
AleksandrPanov Dec 21, 2022
3698915
move py test_read_write_dict, add CharucoDetector py test
AleksandrPanov Dec 21, 2022
8ed708e
add testCharucoDetector
AleksandrPanov Dec 21, 2022
f0284f0
fix noArray case
AleksandrPanov Dec 21, 2022
f59e284
move drawDetectedDiamonds
AleksandrPanov Dec 22, 2022
d5c9f8d
fixes
AleksandrPanov Dec 22, 2022
7d34efa
add one API in checkLastFrame() and w, h
AleksandrPanov Dec 22, 2022
12e279c
fix deleteLastFrame
AleksandrPanov Dec 22, 2022
dcee0a0
fix deleteLastFrame
AleksandrPanov Dec 22, 2022
8db0926
fix checkLastFrame
AleksandrPanov Dec 22, 2022
06ae747
fix np.float32
AleksandrPanov Dec 22, 2022
50e0fb4
fix docs
AleksandrPanov Dec 22, 2022
ffe588f
try fix doc
AleksandrPanov Dec 22, 2022
1f214f2
remove public GridImpl, CharucoImpl
AleksandrPanov Dec 22, 2022
cb3aa2f
fix docs
AleksandrPanov Dec 23, 2022
0ed1de9
change Ptr<> to reference
AleksandrPanov Dec 23, 2022
24bc756
return np.float32
AleksandrPanov Dec 23, 2022
c82d524
fix docs
AleksandrPanov Dec 23, 2022
88e10ee
remove public virtual API for Board classes
AleksandrPanov Dec 23, 2022
db2e081
Got rid of ::create for aruco boards.
asmorkalov Dec 27, 2022
68b6ec2
Bindings fix for Aruco boards.
asmorkalov Dec 27, 2022
8cd2949
Code review fixes.
asmorkalov Dec 27, 2022
3f0a507
Code review fixes.
asmorkalov Dec 28, 2022
2fce006
Cleanup
asmorkalov Dec 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 1 addition & 4 deletions apps/interactive-calibration/CMakeLists.txt
@@ -1,6 +1,3 @@
set(DEPS opencv_core opencv_imgproc opencv_features2d opencv_highgui opencv_calib3d opencv_videoio)
if(${BUILD_opencv_aruco})
list(APPEND DEPS opencv_aruco)
endif()
set(DEPS opencv_core opencv_imgproc opencv_features2d opencv_highgui opencv_calib3d opencv_videoio opencv_objdetect)
file(GLOB SRCS *.cpp)
ocv_add_application(opencv_interactive-calibration MODULES ${DEPS} SRCS ${SRCS})
8 changes: 4 additions & 4 deletions apps/interactive-calibration/calibController.cpp
Expand Up @@ -219,10 +219,10 @@ void calib::calibDataController::filterFrames()
if(mCalibData->imagePoints.size()) {
mCalibData->imagePoints.erase(mCalibData->imagePoints.begin() + worstElemIndex);
mCalibData->objectPoints.erase(mCalibData->objectPoints.begin() + worstElemIndex);
}
else {
mCalibData->allCharucoCorners.erase(mCalibData->allCharucoCorners.begin() + worstElemIndex);
mCalibData->allCharucoIds.erase(mCalibData->allCharucoIds.begin() + worstElemIndex);
if (mCalibData->allCharucoCorners.size()) {
mCalibData->allCharucoCorners.erase(mCalibData->allCharucoCorners.begin() + worstElemIndex);
mCalibData->allCharucoIds.erase(mCalibData->allCharucoIds.begin() + worstElemIndex);
}
}

cv::Mat newErrorsVec = cv::Mat((int)numberOfFrames - 1, 1, CV_64F);
Expand Down
62 changes: 20 additions & 42 deletions apps/interactive-calibration/frameProcessor.cpp
Expand Up @@ -11,7 +11,6 @@

#include <vector>
#include <string>
#include <algorithm>
#include <limits>

using namespace calib;
Expand Down Expand Up @@ -74,17 +73,12 @@ bool CalibProcessor::detectAndParseChessboard(const cv::Mat &frame)

bool CalibProcessor::detectAndParseChAruco(const cv::Mat &frame)
{
#ifdef HAVE_OPENCV_ARUCO
cv::Ptr<cv::aruco::Board> board = mCharucoBoard.staticCast<cv::aruco::Board>();

std::vector<std::vector<cv::Point2f> > corners, rejected;
std::vector<int> ids;
cv::aruco::detectMarkers(frame, cv::makePtr<cv::aruco::Dictionary>(mArucoDictionary), corners, ids, cv::makePtr<cv::aruco::DetectorParameters>(), rejected);
cv::aruco::refineDetectedMarkers(frame, board, corners, ids, rejected);
cv::Mat currentCharucoCorners, currentCharucoIds;
if(ids.size() > 0)
cv::aruco::interpolateCornersCharuco(corners, ids, frame, mCharucoBoard, currentCharucoCorners,
currentCharucoIds);
detector->detectBoard(frame, currentCharucoCorners, currentCharucoIds, corners, ids);
if(ids.size() > 0) cv::aruco::drawDetectedMarkers(frame, corners);

if(currentCharucoCorners.total() > 3) {
Expand All @@ -102,9 +96,6 @@ bool CalibProcessor::detectAndParseChAruco(const cv::Mat &frame)
mCurrentCharucoIds = currentCharucoIds;
return true;
}
#else
CV_UNUSED(frame);
#endif
return false;
}

Expand Down Expand Up @@ -155,6 +146,7 @@ bool CalibProcessor::detectAndParseDualACircles(const cv::Mat &frame)
void CalibProcessor::saveFrameData()
{
std::vector<cv::Point3f> objectPoints;
std::vector<cv::Point2f> imagePoints;
asmorkalov marked this conversation as resolved.
Show resolved Hide resolved

switch(mBoardType)
{
Expand All @@ -169,6 +161,11 @@ void CalibProcessor::saveFrameData()
case chAruco:
mCalibData->allCharucoCorners.push_back(mCurrentCharucoCorners);
mCalibData->allCharucoIds.push_back(mCurrentCharucoIds);

mCharucoBoard->matchImagePoints(mCurrentCharucoCorners, mCurrentCharucoIds, objectPoints, imagePoints);
CV_Assert(mCurrentCharucoIds.total() == imagePoints.size());
mCalibData->imagePoints.push_back(imagePoints);
mCalibData->objectPoints.push_back(objectPoints);
break;
case CirclesGrid:
objectPoints.reserve(mBoardSize.height*mBoardSize.width);
Expand Down Expand Up @@ -248,37 +245,17 @@ bool CalibProcessor::checkLastFrame()
else
mCalibData->cameraMatrix.copyTo(tmpCamMatrix);

if(mBoardType != chAruco) {
cv::Mat r, t, angles;
cv::solvePnP(mCalibData->objectPoints.back(), mCurrentImagePoints, tmpCamMatrix, mCalibData->distCoeffs, r, t);
RodriguesToEuler(r, angles, CALIB_DEGREES);

if(fabs(angles.at<double>(0)) > badAngleThresh || fabs(angles.at<double>(1)) > badAngleThresh) {
mCalibData->objectPoints.pop_back();
mCalibData->imagePoints.pop_back();
isFrameBad = true;
}
}
else {
#ifdef HAVE_OPENCV_ARUCO
cv::Mat r, t, angles;
std::vector<cv::Point3f> allObjPoints;
allObjPoints.reserve(mCurrentCharucoIds.total());
for(size_t i = 0; i < mCurrentCharucoIds.total(); i++) {
int pointID = mCurrentCharucoIds.at<int>((int)i);
CV_Assert(pointID >= 0 && pointID < (int)mCharucoBoard->getChessboardCorners().size());
allObjPoints.push_back(mCharucoBoard->getChessboardCorners()[pointID]);
}

cv::solvePnP(allObjPoints, mCurrentCharucoCorners, tmpCamMatrix, mCalibData->distCoeffs, r, t);
RodriguesToEuler(r, angles, CALIB_DEGREES);

if(180.0 - fabs(angles.at<double>(0)) > badAngleThresh || fabs(angles.at<double>(1)) > badAngleThresh) {
isFrameBad = true;
cv::Mat r, t, angles;
cv::solvePnP(mCalibData->objectPoints.back(), mCalibData->imagePoints.back(), tmpCamMatrix, mCalibData->distCoeffs, r, t);
RodriguesToEuler(r, angles, CALIB_DEGREES);
if(fabs(angles.at<double>(0)) > badAngleThresh || fabs(angles.at<double>(1)) > badAngleThresh) {
mCalibData->objectPoints.pop_back();
mCalibData->imagePoints.pop_back();
if (mCalibData->allCharucoCorners.size()) {
mCalibData->allCharucoCorners.pop_back();
mCalibData->allCharucoIds.pop_back();
}
#endif
isFrameBad = true;
}
return isFrameBad;
}
Expand All @@ -295,15 +272,16 @@ CalibProcessor::CalibProcessor(cv::Ptr<calibrationData> data, captureParameters
mTemplDist = capParams.templDst;
mSaveFrames = capParams.saveFrames;
mZoom = capParams.zoom;
cv::aruco::CharucoParameters charucoParameters;
charucoParameters.tryRefineMarkers = true;

switch(mBoardType)
{
case chAruco:
#ifdef HAVE_OPENCV_ARUCO
mArucoDictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(capParams.charucoDictName));
mCharucoBoard = cv::aruco::CharucoBoard::create(mBoardSize.width, mBoardSize.height, capParams.charucoSquareLength,
capParams.charucoMarkerSize, mArucoDictionary);
#endif
mCharucoBoard = cv::makePtr<cv::aruco::CharucoBoard>(cv::Size(mBoardSize.width + 1, mBoardSize.height + 1), capParams.charucoSquareLength,
capParams.charucoMarkerSize, mArucoDictionary);
detector = cv::makePtr<cv::aruco::CharucoDetector>(cv::aruco::CharucoDetector(*mCharucoBoard, charucoParameters));
break;
case CirclesGrid:
case AcirclesGrid:
Expand Down
7 changes: 2 additions & 5 deletions apps/interactive-calibration/frameProcessor.hpp
Expand Up @@ -7,9 +7,7 @@

#include <opencv2/core.hpp>
#include <opencv2/calib3d.hpp>
#ifdef HAVE_OPENCV_ARUCO
#include <opencv2/aruco/charuco.hpp>
#endif
#include <opencv2/objdetect.hpp>

#include "calibCommon.hpp"
#include "calibController.hpp"
Expand Down Expand Up @@ -39,10 +37,9 @@ class CalibProcessor : public FrameProcessor
cv::Mat mCurrentCharucoIds;

cv::Ptr<cv::SimpleBlobDetector> mBlobDetectorPtr;
#ifdef HAVE_OPENCV_ARUCO
cv::aruco::Dictionary mArucoDictionary;
cv::Ptr<cv::aruco::CharucoBoard> mCharucoBoard;
#endif
cv::Ptr<cv::aruco::CharucoDetector> detector;

int mNeededFramesNum;
unsigned mDelayBetweenCaptures;
Expand Down
37 changes: 6 additions & 31 deletions apps/interactive-calibration/main.cpp
Expand Up @@ -7,9 +7,6 @@
#include <opencv2/cvconfig.h>
#include <opencv2/highgui.hpp>

#ifdef HAVE_OPENCV_ARUCO
#include <opencv2/aruco/charuco.hpp>
#endif

#include <string>
#include <vector>
Expand Down Expand Up @@ -105,11 +102,6 @@ int main(int argc, char** argv)

captureParameters capParams = paramsController.getCaptureParameters();
internalParameters intParams = paramsController.getInternalParameters();
#ifndef HAVE_OPENCV_ARUCO
if(capParams.board == chAruco)
CV_Error(cv::Error::StsNotImplemented, "Aruco module is disabled in current build configuration."
" Consider usage of another calibration pattern\n");
#endif

cv::TermCriteria solverTermCrit = cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS,
intParams.solverMaxIters, intParams.solverEps);
Expand Down Expand Up @@ -170,29 +162,12 @@ int main(int argc, char** argv)
globalData->imageSize = pipeline->getImageSize();
calibrationFlags = controller->getNewFlags();

if(capParams.board != chAruco) {
globalData->totalAvgErr =
cv::calibrateCamera(globalData->objectPoints, globalData->imagePoints,
globalData->imageSize, globalData->cameraMatrix,
globalData->distCoeffs, cv::noArray(), cv::noArray(),
globalData->stdDeviations, cv::noArray(), globalData->perViewErrors,
calibrationFlags, solverTermCrit);
}
else {
#ifdef HAVE_OPENCV_ARUCO
cv::aruco::Dictionary dictionary =
cv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(capParams.charucoDictName));
cv::Ptr<cv::aruco::CharucoBoard> charucoboard =
cv::aruco::CharucoBoard::create(capParams.boardSize.width, capParams.boardSize.height,
capParams.charucoSquareLength, capParams.charucoMarkerSize, dictionary);
globalData->totalAvgErr =
cv::aruco::calibrateCameraCharuco(globalData->allCharucoCorners, globalData->allCharucoIds,
charucoboard, globalData->imageSize,
globalData->cameraMatrix, globalData->distCoeffs,
cv::noArray(), cv::noArray(), globalData->stdDeviations, cv::noArray(),
globalData->perViewErrors, calibrationFlags, solverTermCrit);
#endif
}
globalData->totalAvgErr =
cv::calibrateCamera(globalData->objectPoints, globalData->imagePoints,
globalData->imageSize, globalData->cameraMatrix,
globalData->distCoeffs, cv::noArray(), cv::noArray(),
globalData->stdDeviations, cv::noArray(), globalData->perViewErrors,
calibrationFlags, solverTermCrit);
dataController->updateUndistortMap();
dataController->printParametersToConsole(std::cout);
controller->updateState();
Expand Down
3 changes: 2 additions & 1 deletion apps/interactive-calibration/parametersController.cpp
Expand Up @@ -109,6 +109,7 @@ bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser)

std::string templateType = parser.get<std::string>("t");


if(templateType.find("symcircles", 0) == 0) {
mCapParams.board = CirclesGrid;
mCapParams.boardSize = cv::Size(4, 11);
Expand All @@ -127,7 +128,7 @@ bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser)
}
else if(templateType.find("charuco", 0) == 0) {
mCapParams.board = chAruco;
mCapParams.boardSize = cv::Size(6, 8);
mCapParams.boardSize = cv::Size(5, 7);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to touch it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After fix the vars h/w is setting num corners for CharucoBard (like in chessboard)
After fix CharucoBoard create looks like this:
cv::aruco::CharucoBoard::create(mBoardSize.width + 1, mBoardSize.height + 1, capParams.charucoSquareLength,
capParams.charucoMarkerSize, mArucoDictionary);

mCapParams.boardSize = cv::Size(5, 7); was fixed to support compatibility with old default parameters

mCapParams.charucoDictName = 0;
mCapParams.charucoSquareLength = 200;
mCapParams.charucoMarkerSize = 100;
Expand Down
21 changes: 21 additions & 0 deletions modules/objdetect/include/opencv2/objdetect.hpp
Expand Up @@ -105,6 +105,26 @@ using a Boosted Cascade of Simple Features. IEEE CVPR, 2001. The paper is availa
@defgroup objdetect_dnn_face DNN-based face detection and recognition
Check @ref tutorial_dnn_face "the corresponding tutorial" for more details.
@defgroup objdetect_common Common functions and classes
@defgroup objdetect_aruco ArUco markers and boards detection for robust camera pose estimation
@{
ArUco Marker Detection
Square fiducial markers (also known as Augmented Reality Markers) are useful for easy,
fast and robust camera pose estimation.

The main functionality of ArucoDetector class is detection of markers in an image. If the markers are grouped
as a board, then you can try to recover the missing markers with ArucoDetector::refineDetectedMarkers().
ArUco markers can also be used for advanced chessboard corner finding. To do this, group the markers in the
CharucoBoard and find the corners of the chessboard with the CharucoDetector::detectBoard().

The implementation is based on the ArUco Library by R. Muñoz-Salinas and S. Garrido-Jurado @cite Aruco2014.

Markers can also be detected based on the AprilTag 2 @cite wang2016iros fiducial detection method.

@sa @cite Aruco2014
This code has been originally developed by Sergio Garrido-Jurado as a project
for Google Summer of Code 2015 (GSoC 15).
@}

@}
*/

Expand Down Expand Up @@ -852,5 +872,6 @@ class CV_EXPORTS_W QRCodeDetector
#include "opencv2/objdetect/detection_based_tracker.hpp"
#include "opencv2/objdetect/face.hpp"
#include "opencv2/objdetect/aruco_detector.hpp"
#include "opencv2/objdetect/charuco_detector.hpp"

#endif