3

I have the following images of a chessboard taken from a camera:

left_image

Here is my minimal working example code:

import cv2
print(cv2.__version__)
left_gray = cv2.imread('left_raw.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
print(left_gray.shape)
ret, left_corners  = cv2.findChessboardCorners(left_gray, (6,5))
print(left_corners)

And here is the output, indicating that no corners were found:

2.4.13.1
(1080, 1920)
None

I read several other StackOverflow questions:

  1. This question is about opencv2 failing in a "seemingly simple scenario" but I believe that the images I have are much more simple because this one had a completely cropped out chessboard version. In my case I have a chessboard which I put on top of some white printer paper.
  2. This question is about a failure on high-resolution images. I'm not sure if the camera I'm using is high-res but my image is different from that question since the chessboard here is (roughly) centered and isn't completely skewed.
  3. This question is about a failure on a "perfect" chessboard. However, that one was symmetric, whereas my image is not symmetric (it has 6 rows and 7 columns) and I'm using the input of (5,6) for my chessboard. I also tried (6,5) in case I got it backward but no luck.
  4. This question was about someone getting the dimensions wrong. The user claims that if we have a (10,7) board, the input to the function should be (9,7) where 10=number of columns, 7=number of rows in original board. However, I think we have to subtract one from both dimensions. In any case, I tried using (7,5) and a few other variants for my image but none of the cases work.
  5. This question is about MATLAB but the code shouldn't be too different from Python, and that user saw some success in detecting images even for a much more complicated scenario than what I have.

I'm a little lost at this point about how to find the corners. Does anyone have some advice they would like to share? The image and code are right here in case you wish to test them out. I should also point out that I tried increasing the brightness of the original camera when taking the image but no luck.

Community
  • 1
  • 1
ComputerScientist
  • 936
  • 4
  • 12
  • 20
  • How about trying `cv2.goodFeaturesToTrack()`? – Jeru Luke Feb 08 '17 at 17:38
  • This is the best result (https://imgur.com/a/y2FyF) I can get using a `5x5` grid and by reducing the image size by two. If you can take new images, I would suggest you to use the official OpenCV chessboard (https://raw.githubusercontent.com/opencv/opencv/master/doc/pattern.png) as yours seems slightly different for me. Also remember that to get a good calibration, the calibration pattern must be the most possible flat (the calibration method relies on flat calibration pattern). – Catree Feb 08 '17 at 19:05

2 Answers2

8

I was able to obtain a satisfactory result using cv2.goodFeaturesToTrack().

CODE:

corners = cv2.goodFeaturesToTrack(gray_img,25,0.01,10)
corners = np.int0(corners)

for i in corners:
    x,y = i.ravel()
    cv2.circle(img,(x,y),3,(0,0,255),-1)

cv2.imshow('Corners',img)

enter image description here

I know it is not accurate, but with some pre-processing you should be able to obtain a better result.

:D

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
  • Yeah, maybe I should go ahead and use this... The only reason for doing this is that I need points in a camera calibration and I need matching points across a left and a right image. So if it's only a subset of the corners that's fine, but I will have to manually check that the cameras detect the same corners in the left/right images. – ComputerScientist Feb 08 '17 at 17:53
  • Well said. Just ensure that your images/video feed is proper to accurately mark the corners – Jeru Luke Feb 08 '17 at 18:29
  • Do have a look at [THIS PAGE](http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html) as well :D – Jeru Luke Feb 08 '17 at 18:39
  • Thanks for the links, @Jeru Luke. However I think I may have figured out the issue, maybe the chessboard is too large? I tried again with a newly printed chessboard (and it also doesn't have that ugly border I have above because now the background and the chessboard are on the same piece of paper). This chessboard was much smaller, and the corners now seem to be detected. I'll experiment with this a bit further and report back hopefully. – ComputerScientist Feb 08 '17 at 18:55
  • 1
    I think the issue was more with the overall quality of that original chessboard, which looked like someone sat on it and then scrubbed it against a wall for a while. A bunch of the corners had white spots in them, etc. From what I recall, you want the chessboard to be good quality and absolutely flat. | Maybe also ditch JPEGs (lossy compression, adds artefacts). | There seems to be some serious vignetting in that image... – Dan Mašek Feb 08 '17 at 19:01
  • @JeruLuke Out of topic comment: you should avoid to link to obsolete OpenCV documentation like the `3.0-beta` as some changes can occur (this is not the case here). You can access to all the OpenCV documentation version here: http://docs.opencv.org/ – Catree Feb 08 '17 at 19:14
  • 1
    Good points. I think the quality may have been an issue. In any case I have now resolved it with this new chessboard, so I don't need the `goodFeatures` part but thanks for letting me know about it. – ComputerScientist Feb 08 '17 at 20:43
3

This is the best result I can get with the following environment:

  • OpenCV 3.2
  • chessboard size: 5x5
  • image reduced by two in each dimension
  • image preprocessed with CLAHE algorithm

Chessboard corners detection

C++ code:

cv::Mat img = cv::imread("klpVW.jpg", cv::IMREAD_GRAYSCALE);
cv::resize(img, img, cv::Size(), 0.5, 0.5);
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
clahe->apply(img, img);

std::vector<cv::Point2f> corners;
cv::Size boardSize(5, 5);
bool found = cv::findChessboardCorners(img, boardSize, corners);
std::cout << "found=" << found << std::endl;
cv::Mat display(img.size(), CV_8UC3);
cv::cvtColor(img, display, cv::COLOR_GRAY2BGR);
cv::drawChessboardCorners(display, boardSize, cv::Mat(corners), found);

cv::imshow("Chessboard corners", display);
cv::imwrite("test_chessboard_corners.png", display);
cv::waitKey(0);

As your OpenCV version is different, you may not get the same result. Anyway, you should use instead this OpenCV pattern (yours seems slightly different for me) and remember that the calibration pattern must be as flat as possible to get good calibration results.

Catree
  • 2,477
  • 1
  • 17
  • 24
  • Thanks for the answer. I agree that I should update and get a better image. (The problem is that I am doing it on a shared computer that I don't own, but I'll bring this up with the maintainers.) – ComputerScientist Feb 08 '17 at 20:44