赞
踩
findChessboardCornersSB是OpenCV4新引入的棋盘格角点检测函数,可以直接获得亚像素角点坐标,对噪声的鲁棒性和对大尺寸图像的检测速度相比之前的findChessboardCorners有很大提升。本文介绍findChessboardCornersSB函数的算法原理,并给出函数使用示例。
findChessboardCornersSB的实现主要参考论文Accurate Detection and Localization of Checkerboard Corners for Calibration(2018)。
如上图所示,棋盘格角点检测算法的模型可以分为两类,一种是中心线模型,一种是边缘交叉模型。边缘交叉模型的缺点是易受噪声影响,论文中提出的是一种基于中心线模型的检测算法。
检测算法基于Radon变换的思想,对于任意一个像素,可以选择以其为中心的圆形区域,对像素灰度沿不同角度进行积分。可以画出积分结果随角度的变化曲线,当这一像素是角点时,如下图所示,曲线接近三角函数曲线,且曲线有较大的变化幅度。可以根据这一特性判断像素是否为角点。
使用Radon变换的问题是不同角度的积分计算较为耗时。为了加速这一过程,论文中只计算0、45、90、135这四个方向。0、90度的积分结果分别由对图像进行横竖两个方向的Box滤波获得,为得到45、135度的积分结果,先将图像旋转45°,对旋转的图像进行横竖两个方向的Box滤波,最后再反向旋转图像。取四个滤波结果中最大值与最小值差值的平方作为角点响应值。对响应图进行滤波,找到局部极大值,并进行亚像素插值获得亚像素角点坐标,最后再使用阈值和非最大值抑制来滤除响应弱的角点。原文算法流程如下图。
下图是论文中展示的对实际图片进行角点检测的效果
论文使用仿真数据和实际数据对提出的算法和OpenCV原始的角点检测算法效果进行了对比。仿真数据中,提出的算法在不同角点角度、低运动模糊、不同噪声水平、不同透视角度下都优于OpenCV原始方法。实际数据中,提出的算法检测成功率更高,同时重投影误差也更小。
#include<opencv2/opencv.hpp> int main() { std::string pattern = "./data/*.png"; std::vector<std::string> files; cv::glob(pattern, files); int width = 11; int height = 8; cv::Size patternSize(width, height); // flag参数 // cv::CALIB_CB_NORMALIZE_IMAGE 调用cv::equalizeHist对图片进行直方图均衡化 // cv::CALIB_CB_EXHAUSTIVE 保留更多的角点用于棋盘格筛选,同时尝试更多次数的棋盘格筛选 // cv::CALIB_CB_ACCURACY 对图像进行x2放大,提高角点检查准确度 // cv::CALIB_CB_LARGER 是否允许检测出的标定板角点数量大于标定板patternSize // cv::CALIB_CB_MARKER 标定板是否有标记点 int flag = cv::CALIB_CB_EXHAUSTIVE | cv::CALIB_CB_ACCURACY; std::string windowsName = "Chessboard Corners"; for (auto f : files) { cv::Mat image = cv::imread(f, cv::IMREAD_UNCHANGED); std::vector<cv::Point2f> corners; // 检测棋盘格 bool found = cv::findChessboardCornersSB(image, patternSize, corners, flag); if (found) { // 绘制显示结果 cv::drawChessboardCorners(image, patternSize, corners, found); cv::namedWindow(windowsName); cv::imshow(windowsName, image); cv::waitKey(0); cv::destroyWindow(windowsName); } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。