在OpenCV中,棋盘格角点检测与绘制是一个常见的任务,通常用于相机标定。
棋盘格自定义可参考: OpenCV: Create calibration pattern
opencv官网" />
目录
- 1. 棋盘格角点检测 findChessboardCorners()
- 2. 棋盘格角点绘制 drawChessboardCorners()
- 3. 代码示例
- C++版本
- python版本
1. 棋盘格角点检测 findChessboardCorners()
函数原型是
//C++使用时,包含头文件
#include <opencv2/calib3d.hpp>bool cv::findChessboardCorners (InputArray image,
Size patternSize,
OutputArray corners,
int flags = CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE)
Python://opencv4.8.0
cv.findChessboardCorners( image, patternSize[, corners[, flags]] ) -> retval, corners
这里引用官方的文档内容–参数介绍
opencv官方文档" />
参数成员
image 来源棋盘视图。它必须是8位灰度或彩色图像。
这里如果输入是彩色图像,最好先使用 cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 转换为灰度图像。
patternSize 棋盘格的内部角点数量,格式为 (columns, rows)。必须是棋盘格内部的角点数量,而不是棋盘格的方块数量。例如,一个 10x7 的棋盘格方块,其内部角点数量是 9x6。
注意:这里的角点是指棋盘格内部的交叉点,而不是棋盘格的方块数量。
corners 检测到的角点的输出数组。
如果找到角点,corners 将是一个包含所有角点坐标的数组,形状为 (N, 1, 2),其中 N 是角点的数量。
flags 各种操作标志,可以为零或以下值的组合:
*CALIB_CB_ADAPTIVE_THRESH 使用自适应阈值将图像转换为黑白,而不是固定的阈值水平(根据平均图像亮度计算)。
*CALIB_CB_NORMALIZE_IMAGE 在应用固定或自适应阈值之前,用均衡器归一化图像灰度系数。
*CALIB_CB_FILTER_QUADS 使用附加标准(如轮廓面积、周长、类似正方形的形状)过滤掉在轮廓检索阶段提取的错误四边形。
*CALIB_CB_FAST_CHECK 在图像上运行快速检查,寻找棋盘角,如果没有找到,则快捷调用。当没有观察到棋盘时,这可以显著地加速退化条件下的调用。
返回值
ret
布尔值,表示是否成功找到棋盘格角点。如果找到角点,返回 True;否则返回 False。
corners
检测到的角点坐标,是一个形状为 (N, 1, 2) 的 NumPy 数组,其中 N 是角点的数量。每个角点的坐标是 (x, y),表示其在图像中的像素位置。
该函数试图确定输入图像是否是棋盘图案的视图,并定位棋盘的内部角。如果找到了所有的角,并按一定的顺序(逐行,每行从左到右)放置,则该函数返回一个非零值。否则,如果函数未能找到所有的角或对它们重新排序,它将返回0。例如,一个规则的棋盘有8×8个正方形和7×7个内角,即黑色正方形相互接触的点。检测到的坐标是近似的,为了更精确地确定它们的位置,该函数调用cornerSubPix。如果返回的坐标不够精确,也可以使用带有不同参数的cornerSubPix函数。
2. 棋盘格角点绘制 drawChessboardCorners()
函数原型是
//头文件包含
#include <opencv2/calib3d.hpp>void cv::drawChessboardCorners(InputOutputArray image,
Size patternSize,
InputArray corners,
bool patternWasFound )
Python://opencv4.8.0
cv.drawChessboardCorners(image, patternSize, corners, patternWasFound)->image
参数介绍,引用于官方文档
opencv官网" />
image ; 目标图像。它必须是8位彩色图像。
patternSize 棋盘行和列的内角数量(patternSize = cv::Size(points _ per _ row,points_per_column))。必须是棋盘格内部的角点数量,而不是棋盘格的方块数量。例如,一个 10x7 的棋盘格方块,其内部角点数量是 9x6。
corners: 检测到的角的数组,findChessboardCorners的输出。
patternWasFound: 这个参数表明是否找到了完整棋盘。此处应导入使用findChessboardCorners 函数时所获取到的返回值。
这个函数用于绘制单个棋盘角,如果没有找到棋盘,则显示为红色圆圈;如果找到了棋盘,则显示为用线条连接的彩色角。
3. 代码示例
以下是一个简单的步骤和代码示例,展示如何使用OpenCV检测棋盘格的角点并绘制它们。
C++版本
#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 读取图像cv::Mat image = cv::imread("chessboard.png");if (image.empty()) {std::cerr << "无法加载图像!" << std::endl;return -1;}// 转换为灰度图像cv::Mat gray;cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);// 定义棋盘格的内部角点数量cv::Size patternSize(9, 6); // 例如,9x6 的棋盘格// 存储角点的容器std::vector<cv::Point2f> corners;// 查找棋盘格角点bool found = cv::findChessboardCorners(gray, patternSize, corners);if (found) {std::cout << "找到 " << corners.size() << " 个角点" << std::endl;// 优化角点位置cv::TermCriteria criteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 30, 0.001);cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1), criteria);// 绘制角点cv::drawChessboardCorners(image, patternSize, cv::Mat(corners), found);// 显示结果cv::imshow("Chessboard Corners", image);cv::waitKey(0);} else {std::cout << "未找到棋盘格角点" << std::endl;}cv::destroyAllWindows();return 0;
}
代码说明
1. 图像读取与灰度转换
使用 cv::imread 读取图像,并检查是否成功加载。
使用 cv::cvtColor 将彩色图像转换为灰度图像。
2. 定义棋盘格尺寸
使用 cv::Size 定义棋盘格的内部角点数量(例如 9x6)。
3. 查找角点
使用 cv::findChessboardCorners 查找棋盘格角点。如果找到角点,返回 true,并将角点坐标存储在 corners 中。
4. 优化角点位置
使用 cv::cornerSubPix 对角点位置进行亚像素优化,以提高精度。
5. 绘制角点
使用 cv::drawChessboardCorners 在图像上绘制检测到的角点。
6. 显示结果
使用 cv::imshow 显示带有角点的图像,并等待用户按键退出。
python_126">python版本
步骤:
- 导入必要的库:导入OpenCV和NumPy库。
- 读取图像:读取包含棋盘格的图像。
- 查找角点:使用
cv2.findChessboardCorners
函数查找棋盘格的角点。 - 优化角点位置:使用
cv2.cornerSubPix
函数优化角点位置。 - 绘制角点:使用
cv2.drawChessboardCorners
函数绘制检测到的角点。 - 显示结果:显示带有角点的图像。
代码示例:
python">import cv2
import numpy as np# 读取图像
image = cv2.imread('chessboard.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 定义棋盘格的尺寸(内部角点的数量)
pattern_size = (9, 6) # 例如,9x6的棋盘格# 查找棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)if ret:print(f"找到 {len(corners)} 个角点")# 优化角点位置criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)# 绘制角点cv2.drawChessboardCorners(image, pattern_size, corners, ret)# 显示结果cv2.imshow('Chessboard Corners', image)cv2.waitKey(0)cv2.destroyAllWindows()
else:print("未找到棋盘格角点")
代码说明:
cv2.findChessboardCorners
:这个函数用于查找棋盘格的角点。它需要输入灰度图像、棋盘格的尺寸(内部角点的数量),以及一些可选参数。如果找到角点,返回True
和角点的坐标。cv2.cornerSubPix
:这个函数用于优化角点的位置,使其更加精确。cv2.drawChessboardCorners
:这个函数用于在图像上绘制检测到的角点。
注意事项:
- 棋盘格的尺寸(内部角点的数量)需要根据实际的棋盘格进行调整。
- 如果图像中没有找到棋盘格角点,
ret
将为False
,此时需要检查图像和棋盘格尺寸是否正确。