5

我正在开发一个可以识别GO 板并为其创建SGF 文件的 Android 应用程序。

我制作了一个能够检测板并扭曲透视以使其方形的版本(下面的代码和示例图像)不幸的是,添加石头时它会变得有点困难。(下图)

关于普通围棋板的重要事项:

  • 圆形黑白石头
  • 黑板上的黑线
  • 板材颜色从白色到浅棕色,有时带有木纹
  • 石头放在两条线的交点上

如果我错了,请纠正我,但我认为我目前的方法不是一个好方法。有人对我如何将石头和线条与图片的其余部分分开有一个大致的想法吗?

我的代码:

    Mat input = inputFrame.rgba(); //original image
    Mat gray = new Mat();          //grayscale image

    //convert image to grayscale
    Imgproc.cvtColor( input, gray, Imgproc.COLOR_RGB2GRAY);

    //try to improve histogram (more contrast)
    equalizeHist(gray, gray);

    //blur image
    Size s = new Size(5,5);
    GaussianBlur(gray, gray, s, 0);

    //apply adaptive treshold 
    adaptiveThreshold( gray, gray, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY,11,2);

    //adding secondary treshold, removes a lot of noise
    threshold(gray, gray, 0, 255, Imgproc.THRESH_BINARY + Imgproc.THRESH_OTSU);

一些图片:

空板
(来源:八十二.axc.nl

填充板
(来源:八十二.axc.nl

编辑: 05-03-2016

耶!设法正确检测线石头和颜色。前提条件图片必须只是板本身,没有任何其他可见的背景。
我使用 houghLinesP (60lines) 和 houghCircles (17circles),在我的手机(第 1 代 Moto G)上的持续时间约为 5 秒。
当它必须在不同的角度和闪电条件下工作时,检测板和翘曲是一个相当大的挑战......仍在努力

仍然欢迎提出不同方法的建议!!

填充板
(来源:八十二.axc.nl

编辑: 2016 年 3 月 15 日

我找到了一个很好的方法来让线与交叉类型的形态变换相交,当图片直接在板上方拍摄时效果惊人,不幸的是不是在一个角度(见下文) (来源:八十二.axc.nl变形

在我的最后一次更新中,我展示了线和石头检测以及从正上方拍摄的照片,从那时起我一直致力于检测电路板并以一种我的线和石头检测变得有用的方式扭曲它。

哈里斯角检测
我努力获得正确的参数设置,但我仍然不确定它们是否是最佳的,在使用哈里斯角之前找不到太多关于如何优化图像的信息。现在它检测到许多角落都是有用的。虽然感觉它可以工作。(上面有图片的例子)

    Mat corners = new Mat();
    Imgproc.cornerHarris(image, corners, 5, 3, 0.03);

    Mat mask = new Mat(corners.size(), CvType.CV_8U, new Scalar(1));
    Core.MinMaxLocResult maxVal = Core.minMaxLoc(corners);

    Core.inRange(corners, new Scalar(maxVal.maxVal * 0.01), new Scalar(maxVal.maxVal), mask);

当直接从上方拍摄图片,从某个角度使用或与旋转板一起使用时,交叉型形态变换
效果很好(示例中的图片中线)

    Imgproc.GaussianBlur(image, image, new Size(5, 5), 0);
    Imgproc.adaptiveThreshold(image, image, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 11, 2);

    int morph_elem = 1;     //0: Rect - 1: Cross - 2: Ellipse
    int morph_size = 5;

    int morph_operator = 0; //0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat
    Mat element = getStructuringElement( morph_elem, new Size(2 * morph_size + 1, 2 * morph_size + 1), new Point( morph_size, morph_size ));
    morphologyEx(image, image, morph_operator + 2, element);

如果外板线上没有石头并且光线条件不苛刻,则轮廓和轮廓线
效果很好。轮廓通常只是电路板的一部分(示例中带有图片的下一行)

    Imgproc.GaussianBlur(image, image, new Size(5, 5), 0);
    Imgproc.adaptiveThreshold(image, image, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 11, 2);

    Mat hierarchy = new Mat();
    MatOfPoint biggest     = null;
    int contourId          = 0;
    double biggestArea     = 0;

    double minSize = 2000;
    List<MatOfPoint> contours = new ArrayList<>();

    findContours(InvertedImage, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    //find biggest
    for( int x = 0; x < contours.size() ; x++ ){

        double area = Imgproc.contourArea(contours.get(x));

        if( area > minSize && area > biggestArea ){

            biggestArea = area;
            biggest     = contours.get(x);
            contourId   = x;
        }
    }

提供正确的图片所有三种方法都有效,但不足以可靠。欢迎任何关于参数、图像预处理、不同方法或任何可能改进检测的想法=)

图片链接

比较

编辑: 2016 年 3 月 31 日

检测线和石头几乎解决了,所以我将关闭这个问题。创建了一个新的的精确检测和变形的方法。

任何对我的进展感兴趣的人:这是我的 GOSU Snap Alpha 频道,现在不要期待太多!

编辑: 2016 年 16 月 10 日

更新:我看到有些人仍在关注这个问题。我测试了更多东西并开始使用 Tensorflow,我的神经网络看起来很有前途,你可以在这里看看。 还有很多工作要做,我当前的图像数据集很糟糕,现在我正在努力获取一个大数据集。

该应用程序最好使用带有粗线条和良好闪电的方板。

4

2 回答 2

3

假设您不想“强迫”最终用户拍摄最干净的照片(例如使用某些 QR 码扫描仪之类的叠加层)

也许您可以使用一些具有不同内核的形态转换:

  • 使用矩形内核打开和关闭线条
  • 使用椭圆内核打开和关闭以获取石头(应该可以在某些时候反转图像以恢复白色或黑色)

看看http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html(对不起,这个是在C++中,但我认为这在Java中几乎相同)

我尝试了这些操作来从数独中删除网格以避免单元格提取中的噪音,它就像一个魅力。

让我知道这些信息对您有用(这肯定是一个非常有趣的案例)

于 2016-02-15T19:03:38.173 回答
0

我正在开发相同的程序。我完全避免找线。首先使用透视变换将板子变成正方形。找到 19x19 网格的边缘。然后假设板是 19x19,你可以计算线条的位置。这对我很有效。然后计算最接近石头中心的交点,以确定石头在哪一行和哪一行。对我来说效果很好。唯一可能是针对不同照明条件和不同颜色的宝石和板材的校准程序。

于 2016-12-06T18:23:31.350 回答