I want to detect corners from a image with boxes, although i created the chessboard edge lines with the EDlines algorithm. Now, I have some problems to join them to create perfect boxes. Could you help me maybe?
ed_anti=cvX.createEdgeDrawing()ed_anti.detectEdges(binarized)edges_anti=ed_anti.getEdgeImage(None)segments_anti=ed_anti.getSegments()#gets the segments of the edgesgradiant_anti=ed_anti.getGradientImage(None)#detects the gradient of the edgesed_lines_anti=ed_anti.detectLines(None)#detects the linesif ed_lines_anti is not None: lines_anti = np.uint16(np.around(ed_lines_anti))for i in range(len(ed_lines_anti)):cv.line(anti_black_image, (lines_anti[i][0][0], lines_anti[i][0][1]), (lines_anti[i][0][2], lines_anti[i][0][3]), (250, 0, 250), 1, cv.LINE_AA)
Here is one approach in Python/OpenCV to get your boxes.
- Read the image- Convert to grayscale- Threshold and invert (to find the original black boxes)- Pad with white all around- Floodfill with black to turn the white corners to black.- Crop the padding away- Apply close morphology to fill in black specks- Apply erode morphology to separate the cells- Get external contours for the cells- Draw red contours on a black image- Draw red contours on a copy of the input- Save the results
Input:
import cv2
import numpy as np# read the input
img = cv2.imread('checkerboard.png')# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# threshold and invert
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]# add white border and floodfill the border to black
pad = cv2.copyMakeBorder(thresh, 10,10,10,10, cv2.BORDER_CONSTANT, value=(255))
hh, ww = pad.shape
mask = np.zeros([hh + 2, ww + 2], np.uint8)
floodfill = cv2.floodFill(pad, mask, (0,0), (0), (0), (0), flags=4)[1]
hh, ww = floodfill.shape# crop padding
crop = floodfill[10:hh-10, 10:ww-10]# apply morphology to remove small spots and then disconnect cells
kernel = np.ones((3,3), np.uint8)
clean = cv2.morphologyEx(crop, cv2.MORPH_CLOSE, kernel)
kernel = np.ones((9,9), np.uint8)
clean = cv2.morphologyEx(clean, cv2.MORPH_ERODE, kernel)# get contours
cntr_img = np.zeros_like(clean)
cntr_img = cv2.merge([cntr_img,cntr_img,cntr_img])
cntr_img2 = img.copy()
contours = cv2.findContours(clean, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:area = cv2.contourArea(cntr)if area > 10:cv2.drawContours(cntr_img, [cntr], -1, (0,0,255), 1)cv2.drawContours(cntr_img2, [cntr], -1, (0,0,255), 1)# save results
cv2.imwrite('checkerboard_thresh.jpg', thresh)
cv2.imwrite('checkerboard_floodfill.jpg', floodfill)
cv2.imwrite('checkerboard_crop.jpg', crop)
cv2.imwrite('checkerboard_contours.jpg', cntr_img)
cv2.imwrite('checkerboard_contours2.jpg', cntr_img2)# show the results
cv2.imshow('threshold', thresh)
cv2.imshow('floodfill', floodfill)
cv2.imshow('crop', crop)
cv2.imshow('clean', clean)
cv2.imshow('cntr_img', cntr_img)
cv2.imshow('cntr_img2', cntr_img2)
cv2.waitKey(0)
Threshold and inverted image:
Floodfilled image:
Cropped image (crop to remove added padding):
Contours on black background:
Contours on copy of input: