使用Emgu CV检测棋盘格角点遇异常,求两种方法的正确实现
Emgu CV棋盘格角点检测两种方法实现指导
一、Harris角点检测(修复报错+完整实现)
你遇到的“OpenCV: !image.empty()”异常,核心原因是图像加载失败,比如路径错误、文件不存在或格式不支持。先确保pth指向有效棋盘格图像路径,再参考以下完整实现:
var pth = paths[index]; // 加载灰度图像,先验证图像是否加载成功 var image = new Image<Gray, byte>(pth); if (image.IsEmpty) { Console.WriteLine("图像加载失败,请检查路径"); return; } // 创建与输入图像同尺寸的32位浮点Mat,用于存储Harris角点响应 var cornerResponse = new Mat(image.Size, DepthType.Cv32F, 1); // 执行Harris角点检测 CvInvoke.CornerHarris(image, cornerResponse, blockSize: 3, apertureSize: 3, k: 0.04); // 对响应图进行阈值处理,筛选出强角点 Mat thresholded = new Mat(); double threshold = 0.01 * CvInvoke.MinMaxLoc(cornerResponse)[1]; // 取最大响应的1%作为阈值 CvInvoke.Threshold(cornerResponse, thresholded, threshold, 255, ThresholdType.ToZero); // 复制原始图像用于绘制角点(转彩色方便观察) var cornerImage = image.Convert<Bgr, byte>(); // 遍历图像,找到阈值后的角点并绘制圆形 for (int y = 0; y < thresholded.Rows; y++) { for (int x = 0; x < thresholded.Cols; x++) { float response = thresholded.GetValue<float>(y, x); if (response > threshold) { // 绘制红色圆形标记,半径3,厚度2 CvInvoke.Circle(cornerImage, new Point(x, y), 3, new Bgr(Color.Red).MCvScalar, 2); } } } // 保存绘制后的图像 cornerImage.Save("harris_corners.png");
关键说明:
- 必须验证图像加载状态,避免空图像传入引发异常
- Harris输出的是32位浮点响应图,不能直接保存,需阈值筛选后在原始图像上绘制角点
- 调整
k值(建议0.04-0.06)和阈值比例,可优化角点检测效果
二、FindCornerSubPixel(棋盘格专用角点细化)
这种方法是棋盘格角点检测的标准流程,先通过FindChessboardCorners找到初始角点,再用FindCornerSubPixel细化坐标:
var pth = paths[index]; var image = new Image<Gray, byte>(pth); if (image.IsEmpty) { Console.WriteLine("图像加载失败,请检查路径"); return; } // 定义棋盘格内角点尺寸(比如8x6的棋盘格,内角点为7x5) Size chessboardSize = new Size(7, 5); VectorOfPointF corners = new VectorOfPointF(); // 检测初始棋盘格角点 bool found = CvInvoke.FindChessboardCorners(image, chessboardSize, corners, ChessboardDetectionType.AdaptiveThresh | ChessboardDetectionType.NormalizeImage); if (found) { // 细化角点坐标,达到亚像素精度 CvInvoke.FindCornerSubPixel(image, corners, new Size(11, 11), new Size(-1, -1), new MCvTermCriteria(30, 0.001)); // 复制图像为彩色,绘制角点 var cornerImage = image.Convert<Bgr, byte>(); foreach (PointF corner in corners.ToArray()) { CvInvoke.Circle(cornerImage, Point.Round(corner), 3, new Bgr(Color.Green).MCvScalar, 2); } cornerImage.Save("subpixel_corners.png"); } else { Console.WriteLine("未检测到棋盘格角点,请检查棋盘格尺寸或图像清晰度"); }
关键说明:
chessboardSize必须设置为棋盘格的内角点数量(比如M行N列方块的棋盘格,内角点为(M-1)x(N-1))FindCornerSubPixel的搜索窗口尺寸(Size(11,11))和终止条件(迭代次数30,精度0.001)可根据需求调整- 这种方法专门针对棋盘格,检测精度和稳定性比通用Harris方法更高
内容的提问来源于stack exchange,提问作者user16612111
相关产品推荐
相关产品推荐

