由于几乎没有计算机视觉方面的经验/知识,我目前正在尝试分割和标记棋盘上的单独方块(即 a1 ... h8)。我的目标是利用这些信息,通过网络摄像头和机械臂与 AI 实际下棋。
我正在用 C#(使用 Emgu CV)编写视觉程序,以实现更简单的编程和 GUI 实现。作为我的第一步,我尝试按照本教程来检测正方形。

正如我们所看到的,并非所有的方块都被检测到,我相信有些方块被检测到不止一次(因为创建了 91 个框)。
问题
- 在确定 Canny 阈值和阈值链接的合适值时要考虑哪些因素?IE
gray.Canny(cannyThreshold, cannyThresholdLinking) - 原始图像中的正方形对我们来说是直线,但对计算机来说,它略微倾斜。这是什么原因?是因为边缘有锯齿吗?
- 为什么大部分方块都没有检测到?会不会是灯光?
- 我应该研究哪些适当的技术/方法来解决这个问题?我现在只熟悉关键字:Canny、Hough(我相信的圈子)和 Sobel。
代码
Image<Bgr, Byte> image = new Image<Bgr, Byte>(Emgu_CV.Properties.Resources.Chessboard).Resize(0.15, INTER.CV_INTER_LINEAR);
Image<Gray, Byte> gray = image.Convert<Gray, Byte>(); //.PyrDown().PyrUp() worsens detection
imageBox.Image = image;
double cannyThreshold = 180.0;
double cannyThresholdLinking = 150.0;
Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);
List<MCvBox2D> boxList = new List<MCvBox2D>();
using (MemStorage storage = new MemStorage())
for (Contour<Point> contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext)
{
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); // don't quite understand the purpose of *0.05
if (contours.Area > 250 && contours.Area < 10000)
{
if (currentContour.Total == 4)
{
bool isSquare = true;
Point[] pts = currentContour.ToArray();
LineSegment2D[] edges = PointCollection.PolyLine(pts, true);
for (int i = 0; i < edges.Length; i++)
{
double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
if (angle < 80 || angle > 95)
{
isSquare = false;
break;
}
if (isSquare) boxList.Add(currentContour.GetMinAreaRect());
}
}
}
}
Image<Bgr, Byte> squareImage = image.CopyBlank();
foreach (MCvBox2D box in boxList)
squareImage.Draw(box, new Bgr(Color.Yellow), 1);
outputBox.Image = squareImage;