I am working on an Android application that recognizes the GO board and creates an SGF file .
I made a version that is able to detect the board and distort the perspective to make it square (the code and example image below), unfortunately, it becomes a little more complicated when adding stones. (image below)
Important things about the middle board for go:
- round black and white stones
- black lines on blackboard
- the color of the board varies from white to light brown, and sometimes with wood grains
- stones are located at the intersection of two lines
Correct me if I'm wrong, but I think my current approach is not good. Does anyone have a general idea of ββhow I can separate the stones and lines from the rest of the picture?
My code is:
Mat input = inputFrame.rgba();
Mat gray = new Mat();
Imgproc.cvtColor( input, gray, Imgproc.COLOR_RGB2GRAY);
equalizeHist(gray, gray);
Size s = new Size(5,5);
GaussianBlur(gray, gray, s, 0);
adaptiveThreshold( gray, gray, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY,11,2);
threshold(gray, gray, 0, 255, Imgproc.THRESH_BINARY + Imgproc.THRESH_OTSU);
Some images:

(source: eighttytwo.axc.nl )

(source: eighttytwo.axc.nl )
UPDATE: 05-03-2016
Hurrah! It was possible to correctly determine the lines of stones and colors. precondition: the image should only be on the board itself, without any other visible background.
I use houghLinesP (60 lines) and houghCircles (17 laps), the duration on my phone (1st generation Moto G) is about 5 seconds.
Detecting the circuit board and deformation is quite a challenge when it needs to work at different angles and in lightning conditions ... still working on it
- !!

(: eighttytwo.axc.nl)
: 15-03-2016
, , , , , (. )

(: eighttytwo.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;
int morph_size = 5;
int morph_operator = 0;
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);
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;
}
}
, , , . , , -, , =)

: 31-03-2016
, . .
- : GOSU Snap Alpha, !
: 16-10-2016
: , .
- Tensorflow, , .
, , .
, .