从源码看kalibr 角点提取原理
因为目前涉及kalibr角点提取的代码改写,还想改成用任意标定板都可以提取角点的代码,所以想仔细想仔细研究一下他的提取原理,看看为什么标定板的行列非得大于3.
编译这套docker代码,需要在工作空间的根目录下运行:
catkin build -DCMAKE_BUILD_TYPE=Release -j4
********************************let’s start *****************************************
阅读源码可以发现,核心代码在这里:
\catkin_ws\src\kalibr\aslam_cv\aslam_cameras\src\GridDetector.cpp
bool GridDetector::findTargetNoTransformation(const cv::Mat & image, const aslam::Time & stamp,
GridCalibrationTargetObservation & outObservation) const {
bool success = false;
// Extract the calibration target corner points
Eigen::MatrixXd cornerPoints;
std::vector<bool> validCorners;
success = _target->computeObservation(image, cornerPoints, validCorners);
// Set the image, target, and timestamp regardless of success.
outObservation.setTarget(_target);
outObservation.setImage(image);
outObservation.setTime(stamp);
// Set the observed corners in the observation
for (int i = 0; i < cornerPoints.rows(); i++) {
if (validCorners[i])
outObservation.updateImagePoint(i, cornerPoints.row(i).transpose());
}
return success;
}
分析可知,_target应该包括提取的角点。找到其对应头文件,看他的私有成员可以知道_target是是GridCalibrationTargetBase::Ptr类型。
private:
/// the camera geometry
boost::shared_ptr<CameraGeometryBase> _geometry;
/// \brief the calibration target
GridCalibrationTargetBase::Ptr _target;
/// \brief detector options
GridDetectorOptions _options;
前面提到,提取关键角点的代码为:
success = _target->computeObservation(image, cornerPoints, validCorners);
找到computeObservation这个函数,位于\catkin_ws\src\kalibr\aslam_cv\aslam_cameras\include\aslam\cameras\GridCalibrationTargetBase.hpp,发现是一个虚函数:
virtual bool computeObservation(const cv::Mat & /*image*/,
Eigen::MatrixXd & /*outImagePoints*/,
std::vector<bool> & /*outCornerObserved*/) const
{
SM_ASSERT_TRUE(Exception, true, "you need to implement this method for each target!");
return false;
};
这说明,应该是每一个不同的板子用不同的计算角点的方法。对于April tag,找到他的computeObservation的路径为:\catkin_ws\src\kalibr\aslam_cv\aslam_cameras_april\include\aslam\cameras\GridCalibrationTargetAprilgrid.hpp
/// \brief extract the calibration target points from an image and write to an observation
bool computeObservation(const cv::Mat & image,
Eigen::MatrixXd & outImagePoints,
std::vector<bool> &outCornerObserved) const;
让我们看看cpp的具体实现它干了什么:
/// \brief extract the calibration target points from an image and write to an observation
bool GridCalibrationTargetAprilgrid::computeObservation(
const cv::Mat & image, Eigen::MatrixXd & outImagePoints,
std::vector<bool> &outCornerObserved) const {
bool success = true;
// detect the tags
std::vector<AprilTags::TagDetection> detections = _tagDetector->extractTags(image);
/* handle the case in which a tag is identified but not all tag
* corners are in the image (all data bits in image but border
* outside). tagCorners should still be okay as apriltag-lib
* extrapolates them, only the subpix refinement will fail
*/
//min. distance [px] of tag corners from image border (tag is not used if violated)
std::vector<AprilTags::TagDetection>::iterator iter = detections.begin();
for (iter = detections.begin(); iter != detections.end();) {
// check all four corners for violation
bool remove = false;
for (int j = 0; j < 4; j++) {
remove |= iter->p[j].first < _options.minBorderDistance;
remove |= iter->p[j].first > (float) (image.cols) - _options.minBorderDistance; //width
remove |= iter->p[j].second < _options.minBorderDistance;
remove |= iter->p[j].second > (float) (image.rows) - _options.minBorde

本文揭秘kalibr中AprilTag角点提取算法,包括目标检测策略和边缘处理规则。
最低0.47元/天 解锁文章
1927





