0

I've been trying to create a chessboard reader, nothing fancy so far, just want to be able to read the squares presented. The problem seems to be that while some squares are detectable others are being disregarded by the system. Currently i've read and attempted all solutions from these similar questions:

Python OpenCV: Rubik's cube solver color extraction

How to get the cells of a sudoku grid with OpenCV?

Square detection in image

The image i am currently working with:

enter image description here

I've taken the image and applied a list of processes: B2G -> Thresh -> Blur -> CannyLineDet -> Inverted -> FindCountours

The output prior to ROI chopping is:

enter image description here

The output ROIs are currently as follows: enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

This is the code, but its in Java, if the posted solution is in python that is fine as it is fairly easy to convert between.

            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        boolean writeFile =true;
        // Mat src =
        // Imgcodecs.imread("C:\\Users\\thorf\\Documents\\JavaWS\\openCVtest\\src\\openCVtest\\linesinput.png");
        Mat src = Imgcodecs.imread("C:\\Users\\thorf\\Documents\\JavaWS\\openCVtest\\src\\openCVtest\\chessboard.png");
        Mat grey = new Mat();
        Size size = new Size(3, 3);
        double[][] sharpenKernel = { { -1, -1, -1 }, { -1, 9, -1 }, { -1, -1, -1 } };

        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, size);

        Imgproc.cvtColor(src, grey, Imgproc.COLOR_BGR2GRAY);


        Mat threshed = new Mat();
        Imgproc.threshold(grey, threshed, 200, 255, Imgproc.THRESH_OTSU);
        Imgcodecs.imwrite("threshed.png", threshed);
        showWaitDestroy("threshed", threshed);

        
        Mat blur = new Mat();
        Imgproc.medianBlur(threshed, blur, 5);
        Imgcodecs.imwrite("blur.png", blur);
        showWaitDestroy("blur", blur);
        
        Mat edges = new Mat();
        Imgproc.Canny(blur, edges, 50, 400);
        Imgcodecs.imwrite("edges.png", edges);
        showWaitDestroy("edges", edges);
        

        Mat inv = new Mat();
        Core.bitwise_not(edges, inv);
        Imgcodecs.imwrite("inv.png", inv);
        showWaitDestroy("inv", inv);
        
        processROIs(inv, src);

As can be seen only certain squares are being detected, often those that are white and have pieces in them, however this is not always the case. My question is whether there is a better way to do this, or whether i am missing something in this implimentation? First time using CV so any help is appreciated. EDIT1: I cant divide the image into sections as the input will not always be this image. It may be in another border etc which prevents me from finding the outter bounds.

  • 1
    Observation: only black squares with white pieces and white squares with black pieces are detected. The black on black and white on white cases might offer too low contrast to be detected. – Adriaan Koster Jul 15 '21 at 14:38
  • 2
    Why not just get the outside rectangle and just divide it into 8x8 equal parts? – fmw42 Jul 15 '21 at 15:13
  • The contrast thing is indeed a factor but something i had not put to words quite yet, and i cannot divide the original image as the image will change a lot so sometimes the outer bound rectangle will not be the board but a different website element. – Sulkyoptimism Jul 15 '21 at 15:33
  • since you are already getting many squares out correctly, and you know there are 8 x 8 squares nicely lined out, it is easy to find out the big square inclosing all the 64 squares, then just divide this big sqaure evenly into 8 x 8 squares. You can even double check your result by comparing them with these detected squares. – Guang Jul 15 '21 at 23:22
  • Okay im not sure if the intended application will function with this but i will try this as the answer. The problem then becomes detecting the external boundary from other boundaries. Thank you! – Sulkyoptimism Jul 16 '21 at 01:03

1 Answers1

1

OpenCV has an out-of-the-box method to find chessboard corners: https://docs.opencv.org/4.5.1/d9/d0c/group__calib3d.html#ga93efa9b0aa890de240ca32b11253dd4a

In java it would look something like:

//for a standard 8x8 chessboard, the method needs the inner corners
int nrows = 7; 
int ncols = 7;
MatOfPoint2f corners = new MatOfPoint2f();
Calib3d.findChessboardCorners(myImg, corners, new Size(nrows, ncols));
Nicolas Busca
  • 1,100
  • 7
  • 14