Reputation: 40
I'm trying to determine the boundaries of the chessboard (they are bounded by a black bar)
I do the following
img = cv2.imread(filename)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imwrite("gray.jpg", gray)
thresh = cv2.inRange(gray, hsv_min, hsv_max)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
thresh = cv2.dilate(thresh, kernel, iterations = 1)
thresh = cv2.erode(thresh, None, iterations = 4)
and there's no way I can get a better result, after
contours0, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours0:
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], -1, (255, 0, 0), 0)
cv2.imshow('contours', img)
Upvotes: 1
Views: 1656
Reputation: 53119
Here is one way to do that in Python OpenCV. Basically, threshold the image. Apply some morphology. Get the external contours. Then draw the largest ones above some threshold in perimeter on a black background. The important aspect is that you get the 4 corners included. Then get the convex hull and draw that as the boundary.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('chess.jpg')
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold to binary
thresh = cv2.threshold(gray, 25, 255, cv2.THRESH_BINARY)[1]
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,1))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# invert morph
morph = 255 - morph
# get external contours
cnts = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# draw white contour on black background
cntr_img = np.zeros_like(morph)
for c in cnts:
perimeter = cv2.arcLength(c, True)
if perimeter > 200:
cv2.drawContours(cntr_img, [c], 0, 255, 1)
# get all non-zero points
points = np.column_stack(np.where(cntr_img.transpose() > 0))
hull = cv2.convexHull(points)
# draw convex hull vertices on input image
result = img.copy()
cv2.polylines(result, [hull], True, (0,0,255), 2)
# save results
cv2.imwrite('chess_threshold.jpg', thresh)
cv2.imwrite('chess_morph.jpg', morph)
cv2.imwrite('chess_contour.jpg', cntr_img)
cv2.imwrite('chess_convexhull.jpg', result)
# show results
cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('cntr_img', cntr_img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image:
Morphology Image:
Contour Image:
Resulting Convex Hull on copy of Input:
Upvotes: 5