Вам, вероятно, нужно просмотреть контуры и найти самый большой 4-сторонний, чтобы захватить внешнюю часть вашей сетки.
Вы бы использовали что-то вроде этой вспомогательной функции (обработано мое предварительно обработанное изображение):
def largest_4_sided_contour(processed, show_contours=False):
_, contours, _ = cv2.findContours(
processed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Сортировка контуров по области
contours = sorted(contours, key=cv2.contourArea, reverse=True)
посмотрите на самые большие 5(если их больше 5, в противном случае просто посмотрите на все из них)
for cnt in contours[:min(5, len(contours))]:
Если число сторон равно 4, то это та, которую мы ищем, поэтому мы можем перестать искать и вернуть эту.
if len(approx(cnt)) == 4:
return cnt
return None
В вашей сетке есть некоторые неровности, поэтому вам, возможно, придется выполнить некоторую предварительную обработку или искать диапазон количества сторон, но обычно, просматривая область контура и сужая ее наколичество сторон, вы должны быть в состоянии что-то выяснить.
Вы упомянули получение углов, так что этот шаг:
def get_rectangle_corners(cnt):
''' gets corners from a contour '''
pts = cnt.reshape(cnt.shape[0], 2)
rect = np.zeros((4, 2), dtype="float32")
# the top-left point has the smallest sum whereas the
# bottom-right has the largest sum
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
# compute the difference between the points -- the top-right
# will have the minumum difference and the bottom-left will
# have the maximum difference
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect