android – OpenCV检测go板的不同方法

我正在开发一款能够识别
GO board并创建
SGF file的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);

一些图片:

empty board http://roelept82.eightytwo.axc.nl/pic/device-2016-02-15-130011.png
filledboard http://roelept82.eightytwo.axc.nl/pic/device-2016-02-15-131431.png

编辑:05-03-2016

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

对于不同方法的建议仍然欢迎!!

filledboard http://roelept82.eightytwo.axc.nl/pic/detect.png

编辑:15-03-2016

我找到了一种很好的方法来获得与十字型形态变换的线相交,当图片直接在板上方拍摄时,效果惊人,不幸的是在一定角度时(见下文)
morph http://roelept82.eightytwo.axc.nl/pic/morph.png

在我的最后一次更新中,我展示了线条和石头检测,上面直接拍摄了一张照片,从那时起我就一直在检测电路板并以一种我的线和石头检测变得有用的方式对其进行翘曲.

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

    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);

轮廓和houghlines
如果外板上没有石头,而且光线条件不刺耳则效果很好.轮廓通常只是板的一部分(示例中带有图片的下线)

    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;
        }
    }

提供正确的图片所有三种方法都有效,但不够好,不够可靠.任何关于参数,图像预处理,不同方法或任何可能改善检测的想法都是受欢迎的=)

link to picture

comparison http://roelept82.eightytwo.axc.nl/pic/comparison.png

编辑:31-03-2016

检测线和石头几乎已经解决了所以我将关闭这个问题. created a new one用于准确检测和翘曲.

任何对我的进步感兴趣的人:this is my GOSU Snap Alpha channel现在不要期待太多!

编辑:16-10-2016

更新:我看到有些人仍在关注这个问题.
我测试了一些更多的东西并开始使用Tensorflow,我的神经网络看起来很有前途, you can have a look at it here.
还有很多工作要做,我当前的图像数据集非常糟糕,现在我正在努力获取一个大数据集.

该应用程序最好使用方形板与粗线和体面的闪电.

最佳答案 假设您不想“强迫”您的最终用户拍摄最干净的照片(例如使用像某些QR码扫描仪那样的叠加)

也许你可以使用不同的内核进行一些形态转换:

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

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

我尝试过这些操作从数独中移除网格以避免细胞提取中的噪音,它就像一个魅力.

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

点赞