创建棋盘蒙版以检查棋盘上方块的状态

时间:2015-06-24 11:26:44

标签: opencv image-processing computer-vision emgucv

我想从棋盘中提取方块,并根据它们的坐标标记每个方块,即a1,a2,... h8。我的目标是创建一个“面具”来检查每个方块的存在。我目前正在编写一个使用Emgu CV在C#中执行此操作的程序。

可以找到用于测试的图像here

enter image description here

由于没有计算机视觉方面的经验,我只关注基本思想指导下的简单代码示例。我的第一个领导是tutorial,它告诉我如何制作一个简单的形状探测器。虽然测试图像比示例图像更复杂,但不是很准确。

不准确的方形检测(图像略有不同)

Example

结果存在两个问题:1)并非所有方块都被检测为正方形; 2)创建91个框(而不是64个)以显示检测到的正方形。

为了解决问题#1,我使用了具有扩张和中值平滑的二进制阈值来进一步“简化”图像,结果更好但不完整(由于噪声):

应用二进制阈值,扩张,中值平滑和侵蚀后

binary threshold

可视化和计算正方形

enter image description here

由于我不知道的原因,似乎多次检测到相同的方块(即问题#2),我不知道如何解决这个问题。我最初的想法是在检测到每个方块后立即给它一个标签,但现在看起来并不实用。

问题

  1. 我可以使用哪种方法去除方块b3和g6上的滤镜后噪音?
  2. 我可以使用哪些方法按行逐行对正方形进行正确计数和排序?
  3. 假设我设法标记每个方块,那么我如何“保存”方块的区域以重新用作新帧的掩码? 64个独特的面具在计算上是否昂贵?
  4. 如何最大化广场的检测率?

1 个答案:

答案 0 :(得分:1)

关于我在原始问题中的评论,我实施了一些可能作为固定网格构造的例子:

#define SQUARE_SIZE 131
#define OFFSET_X 75
#define OFFSET_Y 75
#define NUM_SQUARES_X 8
#define NUM_SQUARES_Y 8

using namespace std;
using namespace cv;

int main(){

    // Directory settings
    const string pathToData = "../data/";

    vector<string> filenames = std::vector<string>();

    // Load filenames
    glob(pathToData, filenames, false);

    if(filenames.size() <= 0){
        cout << "no images were found..." << endl;
        return -1;
    }


    Mat chessboard = imread(pathToData+"chessboard.jpg", IMREAD_UNCHANGED);

    for (int i=0;i<NUM_SQUARES_X;i++){
        for (int j=0;j<NUM_SQUARES_Y;j++){

            int startX = OFFSET_X + SQUARE_SIZE*i;
            int startY = OFFSET_Y + SQUARE_SIZE*j;
            int endX = startX + SQUARE_SIZE;
            int endY = startY + SQUARE_SIZE;

            rectangle(chessboard, Point(startX,startY), Point(endX,endY), Scalar(255,0,0), 3, 8, 0);
        }
    }

    namedWindow("chessboard", WINDOW_NORMAL);
    imshow("chessboard", chessboard);  

    cv::waitKey(0); 

    return 0;
}

上面代码的输出可以在下图中看到:

enter image description here

当然,你必须微调参数(偏移和方形尺寸),因为我没有花太多时间在它上面。