OpenCV检测围棋板的不同方法

MaM*_*eak 5 android opencv image-recognition baduk

我正在开发一款Android应用,它将识别GO板并为其创建SGF文件

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

关于普通棋盘游戏的重要事项:

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

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

我的代码:

    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);
Run Code Online (Sandbox Code Playgroud)

一些图像:

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

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

编辑: 05-03-2016

好极了!设法检测线条结石和颜色正确。前提条件是图片只能是木板本身,看不到其他任何背景。
我使用houghLinesP(60行)和houghCircles(17周),在我的手机(第1代Moto G)上的持续时间约为5秒。
当必须在不同的角度和雷电条件下工作时,检测电路板并使其翘曲是一个很大的挑战。

仍然欢迎使用其他方法的建议!!

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

编辑: 15-03-2016

我找到了一种使线与交叉类型的形态学变换相交的好方法,不幸的是,当照片直接在木板上方拍摄时,效果很好,而并非在一定角度下(见下文) 变形
(来源:八十二.axc.nl

在上一次更新中,我从上面直接拍摄的照片显示了线条和石头的检测,从那时起,我一直在致力于检测木板并对其变形以使线条和石头的检测变得有用。

harris拐角检测
我一直在努力获取正确的参数设置,但我仍然不确定它们是否是最佳设置,在使用harris拐角之前无法找到有关如何优化图像的大量信息。现在,它检测到许多有用的地方。尽管感觉可行。(示例中带有图片的上一行)

    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);
Run Code Online (Sandbox Code Playgroud)


当直接从上方直接拍摄图片,从某个角度使用或与旋转的木板一起使用时,十字型形态转换效果很好(例如,带有图片的中间线)

    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);
Run Code Online (Sandbox Code Playgroud)


如果外部木板上没有石头,并且光线条件不苛刻,则轮廓线和粗糙度线效果很好。轮廓经常只是板子的一部分(例如,下排带有图片)

    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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

提供正确的图片,这三种方法都可以工作,但不够可靠。欢迎对参数,图像预处理,不同方法或任何可能改善检测的任何想法=)

链接到图片

比较

编辑: 31-03-2016

检测线条和石头几乎可以解决,所以我将结束这个问题。创建了一个用于准确检测和变形的新工具

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

编辑: 16-10-2016

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

该应用程序最好使用带有粗线和体面闪电的方形板。

小智 3

假设您不想“强迫”最终用户拍摄最干净的照片(例如使用像某些二维码扫描仪那样的覆盖层)

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

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

看看http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_looking_hats/opening_looking_hats.html(抱歉,这是用C++写的,但我认为这在Java中几乎是一样的)

我尝试过这些操作来从数独中删除网格,以避免单元格提取中的噪音,它的效果非常好。

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