2016-02-15 26 views
4

我正在开发一个Android应用程序,它将识别GO board并创建一个SGF fileOpenCV检测棋盘上的不同方法

我犯了一个版本,其能够检测板和翘曲的角度,使其平方(下面代码和示例图像)不幸的是它加入石子时变得有点困难。(下图)

重要的事情关于平均棋盘:

  • 圆形黑色和白色石
  • 黑线在板
  • 板的颜色范围从白色至浅棕色,有时带有木纹
  • 石头被放置在交叉的两条线

纠正我,如果我错了,但我认为我目前的做法是不是一个好。 有人有关我如何从图片的其余部分分离石头和线的一般想法?

我的代码:

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

编辑: 2016年5月3日

耶!设法正确地检测线条石块和颜色。先决条件是图片必须只是板子本身,没有任何其他背景可见。
我使用houghLinesP(60lines)和houghCircles(17圈),持续时间在我的手机上(第1代摩托G)约5秒钟。
探测板和扭曲事实证明是相当大的挑战,当它以不同的角度和闪电条件是工作..仍在努力对

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

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

编辑:当图片被直接采取上述板不幸 15-03-2016

我发现了一个很好的方式来获得符合十字型形态的转换交叉,令人惊叹的作品而不是在一个角度(见下文) morph http://roelept82.eightytwo.axc.nl/pic/morph.png

在我上次更新我显示线和石头检测与直接从上面拍摄的照片自那时起我一直以来通过检测电路板并翘曲,以便我的线条和石材检测变得有用。

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

交叉型形态学变换
当图像直接取自上面,从一个角度或与旋转板使用不起作用(与图片中间线工作很大例如)

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
如果有在外boardline没石子和光照条件不苛刻的它工作得很好。轮廓仅是主板的一部分,经常(与示例图片下行)

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. 还有很多工作要做,我当前的图像数据集非常糟糕,现在我正在努力获得一个大数据集。

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

回答

2

假设你不希望“强制”最终用户采取干净的照片(如使用覆盖像一些QR码扫描仪例如)

也许你可以使用一些形态转换型动物的内核:

  • 开口与矩形内核关闭的线路
  • 开幕式,并与椭圆的内核,以获得宝石关闭(它应该有可能在某个时候将图像反拿回白或黑色)

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

我曾尝试这些操作,从一个数独中删除网格,以避免细胞提取噪音它像一个魅力一样工作。

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

+0

谢谢!我明白这个主意。必须进行测试,并将结果返回给您。 – MaMiFreak

+0

我对这个建议感到非常满意,不幸的是,对于与此不同的项目更是如此。我设法删除线(见链接),但我不能删除的石头,而不删除线。 https://www.dropbox.com/s/hdvtshj1e481u4c/lineremoval.png?dl=0 旁边,它不是一个非常快速的转换,最后我希望能够处理至少2张图片a秒(而不是当前的每3秒1次)以获得正在进行的游戏的连续注册 – MaMiFreak

+0

根据您的编辑,我发现您可以检测到您想要的内容。对于处理时间,我能想到的最简单的事情就是在处理之前减少图像分辨率。尝试将分辨率除以1.5,2,2.5,3等,观察结果和处理时间。这些转换必须检查每个像素,将初始分辨率除以2会将处理时间减少近4秒。 – RossierFl

0

我工作的程序相同。我完全避免找到线条。 首先使用透视变换将棋盘变成方块,就像你所做的一样。找到19x19网格的边缘。然后假设电路板是19x19,您可以计算线的位置。这对我很好。然后计算石材中心的最接近的交点,以确定石材所在的行和列线。对我来说工作得很好。只可能是针对不同的照明条件和不同颜色的石块和木板校准程序。

+0

如何定位板以便执行正确的透视变换? – MaMiFreak

+0

基本上打电话找轮廓,以获得所有的板的轮廓。 – sammy

+0

然后找到最大面积轮廓,然后找到该轮廓的凸包。这通常起作用。 – sammy