如何使用OpenCV检测多个外部边界中的数独确切边界?
我在用OpenCV提取数独网格的时候,想找到面积最大的方形轮廓。但是有些数独的外边界不止一个,所以程序只检测到了最外面的边界。这影响了后面的程序,因为数独是按行和列分成9个部分的,目的是从每个单元格中提取数字。
我该怎么修改main_outline()函数,才能检测到数独的实际边界,而不是那些额外的外边界呢?
def main_outline(contour):
biggest = np.array([])
max_area = 0
for i in contour:
area = cv2.contourArea(i)
if area >50:
peri = cv2.arcLength(i, True)
approx = cv2.approxPolyDP(i , 0.02* peri, True)
if area > max_area and len(approx) ==4:
biggest = approx
max_area = area
return biggest ,max_area
su_contour_1= su_puzzle.copy()
su_contour_2= su_puzzle.copy()
su_contour, hierarchy = cv2.findContours(preprocess(su_puzzle),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(su_contour_1, su_contour,-1,(0,255,0),3)
black_img = np.zeros((450,450,3), np.uint8)
su_biggest, su_maxArea = main_outline(su_contour)
这个问题可以通过以下图片来解释:
输入图片:
当前程序提取的图片:
期望提取的图片:
我尝试使用递归函数来检测内部边界,但失败了,因为在检测到确切边界后,它会继续寻找轮廓,这样就会被识别为单独的数独网格,导致结果错误。我找不到一个好的停止条件。
1 个回答
1
如果边界总是蓝色的话,这样做可能会效果很好:
im = cv2.imread("sudoku.png") # read im
b,g,r = cv2.split(im) # split to bgr
bThresh = cv2.threshold(b, 0, 1, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1] # get the threshold
cnts, _ = cv2.findContours(bThresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # find the contours
largestCnt = max(cnts, key = cv2.contourArea) # find the largest contour
x, y, w, h = cv2.boundingRect(largestCnt) # get bounding rect
croppedIm = im[y:y+h, x:x+w] # crop
cv2.imwrite("Cropped.png", croppedIm) # save
下面的代码可视化效果:
imContoured = cv2.drawContours(cv2.merge((r,g,b)).copy(), largestCnt, -1, (255,0,0), 5) # draw largest contour with thick line, red
plt.figure()
plt.imshow(imContoured)
plt.axis("off")
得到的结果是:
最终保存的图片是: