我想从棋盘中提取方块,并根据它们的坐标标记每个方块,即a1,a2,... h8。我的目标是创建一个“面具”来检查每个方块的存在。我目前正在编写一个使用Emgu CV在C#中执行此操作的程序。
可以找到用于测试的图像here。
由于没有计算机视觉方面的经验,我只关注基本思想指导下的简单代码示例。我的第一个领导是tutorial,它告诉我如何制作一个简单的形状探测器。虽然测试图像比示例图像更复杂,但不是很准确。
不准确的方形检测(图像略有不同)
结果存在两个问题:1)并非所有方块都被检测为正方形; 2)创建91个框(而不是64个)以显示检测到的正方形。
为了解决问题#1,我使用了具有扩张和中值平滑的二进制阈值来进一步“简化”图像,结果更好但不完整(由于噪声):
应用二进制阈值,扩张,中值平滑和侵蚀后
可视化和计算正方形
由于我不知道的原因,似乎多次检测到相同的方块(即问题#2),我不知道如何解决这个问题。我最初的想法是在检测到每个方块后立即给它一个标签,但现在看起来并不实用。
答案 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;
}
上面代码的输出可以在下图中看到:
当然,你必须微调参数(偏移和方形尺寸),因为我没有花太多时间在它上面。