Удаление сетки в отсканированных / сфотографированных медицинских документах - PullRequest
2 голосов
/ 09 июля 2019

Я студент-стоматолог, и в настоящее время пытаюсь написать скрипт для анализа и извлечения рукописных цифр из стоматологических записей. У меня уже есть черновая версия сценария, но уровень распознавания у меня довольно низкий. Большая проблема с анализом данных - это сетка, которую трудно удалить.

Сканированная форма, которую я хочу проанализировать (белые поля для анонимности):

Пустая форма:

Я пробовал разные решения для этой проблемы (эрозия / дилатация, HoughLineTransform и смазывание линий). Использование совмещения элементов и вычитания с пустым шаблоном в настоящее время дает мне лучшие результаты.

Результаты:

Эрозия и расширение этого изображения дают еще лучшие результаты

Результаты:
! [] [4]

Но это требует новой калибровки почти каждый раз, когда я пытаюсь это сделать. Знаете ли вы о более элегантном решении моей проблемы. Может ли соответствие SURF дать лучшие результаты? Большое спасибо!

Вот мой код:

GOOD_MATCH_PERCENT = 0.15

def match_img_to_template(input_img, template_img, MAX_FEATURES, GOOD_MATCH_PERCENT):

    # blurring of the input image
    template_img = cv2.GaussianBlur(template_img, (3, 3), cv2.BORDER_DEFAULT)

    # equalizing the histogramm of the input image
    img_preprocessed = cv2.equalizeHist(input_img)

    # ORB Detector
    orb = cv2.ORB_create(MAX_FEATURES)
    kp1, des1 = orb.detectAndCompute(img_preprocessed, None)
    kp2, des2 = orb.detectAndCompute(template_img, None)

    # Brute Force Matching
    matcher= cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
    matches = matcher.match(des1, des2, None)

    matches.sort(key=lambda x:x.distance, reverse=False)

    numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
    matches = matches[:numGoodMatches]

    # Remove not so good matches
    numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
    matches = matches[:numGoodMatches]

    # Extract location of good matches
    points1 = np.zeros((len(matches), 2), dtype=np.float32)
    points2 = np.zeros((len(matches), 2), dtype=np.float32)

    for i, match in enumerate(matches):
        points1[i, :] = kp1[match.queryIdx].pt
        points2[i, :] = kp2[match.trainIdx].pt

    # Find homography
    h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)

    # Use homography
    height, width = template_img.shape
    input_warped = cv2.warpPerspective(input_img, h, (width, height))

    ret1, input_warped_thresh = cv2.threshold(input_warped,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

    diff = cv2.absdiff(template_img, input_warped_thresh)

    ret, diff = cv2.threshold(diff, 20, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C + cv2.THRESH_BINARY)

    diff = cv2.equalizeHist(diff)

    # Create kernels
    kernel1 = np.ones((3,3),np.uint8)
    kernel2 = np.ones((6,6), np.uint8)
    # erode dilate to remove the grid
    diff_erode = cv2.erode(diff,kernel1)
    diff_dilated = cv2.dilate(diff_erode,kernel2)
    # invert diff_dilate
    diff_dilated_inv = cv2.bitwise_not(diff_dilated)

    return diff_dilated_inv
...