Cv2 findChessboardCorners fails to find corners

Viewed 5496

I am using cv2 findChessBoardCorners for camera calibration in a vision application. My call to the function looks like this:

def auto_detect_checkerboard(self, image):
    retval, corners = cv2.findChessboardCorners(image, (7, 7), flags=cv2.CALIB_CB_ADAPTIVE_THRESH
                                                + cv2.CALIB_CB_EXHAUSTIVE)
    if(retval):
        return corners[0][0], corners[0][1]
    else:
        print("No Checkerboard Found")
        assert False

But it seems to fail to find any corners on all images I have tried with it so far. The most trivial example I have used is960 x 1280 photograph of a checkerboard on a wooden table

Is there an issue with my use of the the function? Or is there an issue with the image that I need to deal with in preprocessing?

So far I have tried converting to grayscale, and applying a Gaussian filter, neither of which seem to have made a difference.

1 Answers

My approach for the problem is to perform color-segmentation to get a binary mask. Next, using binary mask to remove the background to make the board visible, removed from artifacts. Finally output the chess border features in an accurate way.

    1. Performing color-segmentation: We convert the loaded image to the HSV format define lower/upper ranges and perform color segmentation using cv2.inRange to obtain a binary mask.
    1. Extracting chess-board: After obtaining binary mask we will use it to remove the background and separate chess part from the rest of the image using cv2.bitwise_and. Arithmetic operation and is highly useful for defining roi in hsv colored images.
    1. Displaying chess-board features. After extracting the chessboard from the image, we will set the patternSizeto (7, 7) and flags to adaptive_thresh + fast_check + normalize image inspired from the source.

Steps:

  • Color-segmentation to get the binary mask.

    • enter image description here

    • lwr = np.array([0, 0, 143])
      upr = np.array([179, 61, 252])
      hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
      msk = cv2.inRange(hsv, lwr, upr)
      
  • Removing background using mask

    • enter image description here

    • krn = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 30))
      dlt = cv2.dilate(msk, krn, iterations=5)
      res = 255 - cv2.bitwise_and(dlt, msk)
      
  • Displaying Chess-board features

    • enter image description here

    • res = np.uint8(res)
      ret, corners = cv2.findChessboardCorners(res, (7, 7),
                                               flags=cv2.CALIB_CB_ADAPTIVE_THRESH +
                                                     cv2.CALIB_CB_FAST_CHECK +
                                                     cv2.CALIB_CB_NORMALIZE_IMAGE)
      if ret:
          print(corners)
          fnl = cv2.drawChessboardCorners(img, (7, 7), corners, ret)
          cv2.imshow("fnl", fnl)
          cv2.waitKey(0)
      else:
          print("No Checkerboard Found")
      

Code:


import cv2
import numpy as np

# Load the image
img = cv2.imread("kFM1C.jpg")

# Color-segmentation to get binary mask
lwr = np.array([0, 0, 143])
upr = np.array([179, 61, 252])
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
msk = cv2.inRange(hsv, lwr, upr)

# Extract chess-board
krn = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 30))
dlt = cv2.dilate(msk, krn, iterations=5)
res = 255 - cv2.bitwise_and(dlt, msk)

# Displaying chess-board features
res = np.uint8(res)
ret, corners = cv2.findChessboardCorners(res, (7, 7),
                                         flags=cv2.CALIB_CB_ADAPTIVE_THRESH +
                                               cv2.CALIB_CB_FAST_CHECK +
                                               cv2.CALIB_CB_NORMALIZE_IMAGE)
if ret:
    print(corners)
    fnl = cv2.drawChessboardCorners(img, (7, 7), corners, ret)
    cv2.imshow("fnl", fnl)
    cv2.waitKey(0)
else:
    print("No Checkerboard Found")

To find lower and upper boundaries of the mask, you may find useful: HSV-Threshold-script

Related