C++ OpenCV findChessboardCorners()耗时很长

2023-11-04


问题概览

近期新买的棋盘格标定板到了,开始尝试用之前写的标定程序对相机进行标定,程序中使用的棋盘格角点提取的函数为OpenCV库函数findChessboardCorners(),但在运行过程中发现其中几张拍摄的图片会出现耗时很长的问题,好的图片一两秒算完,异常图片可能就是几百秒开外,典型图片如下图所示,大家有兴趣可以直接搭例子进行测试

在这里插入图片描述

函数定义


bool cv::findChessboardCorners	(	InputArray 	image,
									Size 	patternSize,
									OutputArray 	corners,
									int 	flags = CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE 
								)	
  • image:输入图像(格式:cv::Mat)
  • patternSize:特征点的横纵向数量(格式:cv::Size)
  • corners:输出提取到的特征点像素坐标集合(格式:vector< vector< cv::Point2f > >)
  • flags :(默认缺省)标识符,用于附加一些滤波步骤,以帮助找到棋盘上的角点,缺省量为CALIB_CB_ADAPTIVE_THRESH(自适应阈值法)CALIB_CB_NORMALIZE_IMAGE(图像归一化)

问题排查

从图片上看,这张图像标定区域清晰,且角点并不存在遮挡问题,理论上不应该会出现提取不到特征点的问题出现,其次及时我把标识符中所有提升算法鲁棒性和快速性的标志加上,也没有产生很大的作用。直到我开始仔细查阅OpenCV的Manuel的时候,发现其有关标定特征点提取的函数下面都有这么一段话:

The function requires white space (like a square-thick border, the wider the better) around the board to make the detection more robust in various environments.

翻译一下就是说,这几个特征点提取的函数希望被摄的标定图案周围能有较多的白色空白,这样才能保证特征提取函数的鲁棒性。而回看刚刚的图片其实就存在着问题,首先标定板制作本身比较紧凑,图案周边的空白较少;其次该图片图案的左下角贴近图像边缘位置。而这两个因素很大程度上造成了findChessboardCorners()无法从图像上识别到正确的标定图案位置。

对于findChessboardCorners()的这种鲁棒性较差问题,stackoverflow上的大佬做过一个解释,这里我直接搬运了原文,这种空白较少实际上就是造成了第一步出现了很大的计算耗时导致。网上还有一种说法是,findChessboardCorners()中有关特征点搜索的Blob算法比较旧,鲁棒性不是很好,不像findCirclesGrid()圆点特征点提取函数那样有很好的鲁棒性。

Can findChessboardCorners be speeded up?
OpenCV findChessboardCorners very slow

Most of the time is spent in checkerboard extraction, which consists (roughly speaking) of three steps: detecting checkerboard corners in the images, refining them to subpixel resolution, and matching them to the nominal checkerboard.
Of the three, the first step is the most expensive, because it involves processing the entire image. So you can gain some time by detecting corners and matching checkerboard at lower resolution (using cv2.findChessboardCorners). You can then rescale their coordinates to full resolution and subpixel-refine them (cv2.find4QuadCornersSubpix) for greater accuracy. The refinement routine works on small regions around the detected corners, so it needs much less memory - which is helpful when working on CPU’s with limited cache size.

解决方案

由于findChessboardCorners()是封装好的函数,我没办法对其进行超时跳出的设计(除非放线程运算,然后对线程做超时处理),因此考虑方案有以下两个:

1.人为添加空白或者将背景变为与图案背景一致

我在实践中采用的人为添加空白这种方式,当然选择删掉跑的慢的标定图片是更好的选择啦。最后实测ok,修改后的标定板长这样
在这里插入图片描述

2.使用OpenCV4中的findChessboardCornersSB() 函数

这个函数只在OpenCV 4以后的版本出现,对于这个函数的介绍,建议大家阅读这位前辈的opencv4 findChessboardCornersSB 棋盘格角点提取。从Manuel上来看,这个函数在一篇"Accurate Detection and Localization of Checkerboard Corners for Calibration" 的论文基础上,提高了标定算法鲁棒性以及精度,并且直接集成了亚像素提取的步骤(不再需要单独再加一个cornerSubPix()了)

其函数定义如下:

bool cv::findChessboardCornersSB	(	InputArray 		image,
										Size 			patternSize,
										OutputArray 	corners,
										int 			flags,
										OutputArray 	meta 
									)	

我实测这个函数确实可以解决刚刚的问题,但这个函数会占用很多算力资源,同时耗时也不算短,利用VS监控运行这个函数期间的内存占用非常惊人,所以还是建议视情况而定。
在这里插入图片描述

参考引用

OpenCV Manuel:Camera Calibration and 3D Reconstruction

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ OpenCV findChessboardCorners()耗时很长 的相关文章

随机推荐

  • canvas 动态背景粒子特效 直接拿走

  • 五子棋c++代码_C++大作业赏析

    清小C C 大作业赏析 如何完成一篇优秀的C 大作业 苦恼C 大作业的同学快点进来看看 小声 五子棋设计 五子棋是大家最为熟悉双人对弈的棋类游戏之一 只要任意行 列 斜线连成五子即可获胜 上个学期中 陈昊柯同学的大作业实现了五子棋 不但能够
  • 循环进度可视化tqdm

    Python的tqdm库是循环进度条可视化 可以在 Python 循环中添加一个进度提示信息 用户只需要封装任意的迭代器 tqdm iterator 这里我们分3个部分展示 介绍 使用 实例 安装用pip即可 1 介绍 首先先来看一下如何创
  • express中间件详解

    Express中间件是一个函数 它可以访问请求对象 req 响应对象 res 和next函数 中间件的主要作用是在处理请求之前或之后执行一些操作 例如验证用户身份 记录日志 解析请求体等 使用Express中间件有两种方式 应用级别和路由级
  • STM32CUBEMX_日志系统_RTT和串口(重映射浮点数打印)

    STM32CUBEMX 日志系统 RTT和串口 重映射浮点数打印 前言 嵌入式系统开发过程中日志的打印至关重要 他在系统架构搭建和开发过程中包括后期调试定位问题都非常重要 所以在此记录两种日志打印的方式 第一种是移植J link中自带的RT
  • 生成数字与字母组合随机的字符串

    package kmt test cn import java util Random public class StringRandom 生成随机数字和字母 public String getStringRandom int length
  • Springboot中Eureka的使用方法

    在微服务架构中 注册中心是核心的基础服务 它主要记录各个微服务和微服务地址的映射关系 各个微服务都将自己注册到这个注册中心上面 当微服务之间需要互相调用时 就可以从注册中心上面去发现微服务和进行调用 Spring Cloud是一个开箱即用的
  • Linux基础及Linux环境搭建(保姆级别)

    详细 第一章 Linux基础及Linux环境搭建 保姆级别 Kali BugChen的博客 CSDN博客 第一章 Linux基础及Linux环境的搭建 保姆级别 一 Linux简介 1 什么是Linux 一款免费开源流行的操作系统 2 Li
  • 被车撞了!

    买了新车之后 因为是新手司机上路 开了不到4个月 车身已经被划伤好多处了 有的是我自己不小心划的 有的是车在停车场 不知道被谁划伤的 找不到肇事者了 不过好在都是小小的划伤 不影响车的颜值 也不影响驾驶体验 一开始我还很心疼 后来也释然了
  • 【Linux】进程间通信1-匿名管道1

    文章目录 管道符 创建匿名管道的pipe函数 从内核角度深入理解管道 代码验证pipe函数 管道和子进程的先后创建顺序 代码实现父子进程的通信 管道的特性 前言 为什么需要进程间通信呢 每一个进程的数据都是存储在物理内存当中的 进程通过各自
  • 【JMeter】beanshell 获取/修改请求头信息

    在使用jmeter做接口测试的时候 相信大家一定遇到过以下场景 使用HTTP信息头管理器设置全局请求头信息 如 content type application json 但并非所有的接口的content type都是application
  • osal_start_timerEx 函数分析

    经常用到osal start timerEx函数来周期性产生某一事件 本文就来分析一下该函数 fn osal start timerEx brief This function is called to start a timer to e
  • 同一台电脑安装多个版本的idea

    同一台电脑安装多个版本的idea 需求 当前 电脑上已经安装了idea2019 3 exe版本 发现此版本太旧了 无法体验新版idea2023 1的很多功能及优化 新出的好多idea插件都不支持idea2019 3版本了 比如 支持Chat
  • C/C++浮点数的存储方式 IEEE-754标准,以及实现一个ftoa函数将浮点数转换为字符串

    浮点数的存储格式 转载自 http www cnblogs com dolphin0520 archive 2011 10 02 2198280 html C C 浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的 例如一个
  • 遍历Map的四种方法

    遍历map的4种方式的比较 public static void main String args Map
  • 机器学习(第一章)—— 特征工程

    目录 一 特征归一化 二 类别型特征 三 高维组合特征的处理 四 组合特征 五 文本表示模型 六 Word2Vec 七 图像数据不足时的处理方法 为什么需要对数值类型的特征做归一化 怎样处理类别型特征 什么是组合特征 如何处理高维组合特征
  • SpringRetry重试机制(3秒上手)

    目录 前言 一 SpringRetry的使用 1 1 引入依赖 1 2 开启重新机制 1 3 3 在方法上添加 Retryable 1 3 4 编写重试失败后的执行的方法 测试 前言 SpringRetry重试机制在实际工作中的场景 比如
  • PTA输出指定范围内的完数

    1 include
  • 【渲染管线-1】坐标变换的理解

    渲染管线 1 坐标变换的理解 1 对坐标变换的形象理解 2 整个过程在计算机内的逻辑 本文将尽可能细致的对坐标变换的过程 用意和一些细节进行剖析 目的是方便自己在遗忘时进行复习 因此可能会有些繁琐 文章将分成两部分 第一部分包含大量例子 主
  • C++ OpenCV findChessboardCorners()耗时很长

    目录 问题概览 函数定义 问题排查 解决方案 1 人为添加空白或者将背景变为与图案背景一致 2 使用OpenCV4中的findChessboardCornersSB 函数 参考引用 问题概览 近期新买的棋盘格标定板到了 开始尝试用之前写的标