OCR 청소 이미지


9

OCR의 이미지를 지우려고했습니다. (라인)

여기에 이미지 설명을 입력하십시오

때로는 이미지를 추가로 처리하기 위해이 선을 제거해야하며 꽤 가까워 지지만 임계 값이 텍스트에서 너무 많이 걸리는 시간이 많습니다.

    copy = img.copy()
    blur = cv2.GaussianBlur(copy, (9,9), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,30)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    dilate = cv2.dilate(thresh, kernel, iterations=2)

    cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    for c in cnts:
        area = cv2.contourArea(c)
        if area > 300:
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(copy, (x, y), (x + w, y + h), (36,255,12), 3)

편집 : 또한 글꼴이 변경되는 경우 상수를 사용하면 작동하지 않습니다. 이것을하는 일반적인 방법이 있습니까?


2
이 줄 중 일부 또는 그 일부는 합법적 인 텍스트와 동일한 특성을 가지므로 유효한 텍스트를 손상시키지 않으면 서 제거하기가 어렵습니다. 이 경우 문자보다 길고 다소 고립되어 있다는 사실에 초점을 맞출 수 있습니다. 따라서 첫 번째 단계는 문자의 크기와 친밀도를 추정하는 것입니다.
Yves Daoust

@YvesDaoust 캐릭터의 친밀감을 찾는 방법은 무엇입니까? (크기에 순수하게 필터링하기 때문에 문자로 많은 시간을 혼합 위로를 얻을 수)
K41F4r

1
모든 얼룩에 대해 가장 가까운 이웃까지의 거리를 찾을 수 있습니다. 그런 다음 거리에 대한 히스토그램 분석을 통해 "close"와 "apart"(분산 모드와 같은 것) 또는 "surrounded"와 "isolated"사이의 임계 값을 찾을 수 있습니다.
이브 다우 스트

서로 가까이있는 여러 개의 작은 선이있는 경우 가장 가까운 이웃이 다른 작은 선이 아닐까요? 다른 모든 얼룩까지의 평균 거리를 계산하는 데 너무 많은 비용이 듭니까?
K41F4r

"가장 가까운 이웃이 다른 작은 선이되지 않겠습니까?": 좋은 반대, 재판장 님. 실제로는 거의 짧은 배열이 합법적 인 텍스트와 다르지 않지만 완전히 정렬되지는 않습니다. 끊어진 선 조각을 다시 그룹화해야 할 수도 있습니다. 나는 모든 사람들과의 평균 거리가 당신을 구출 할 것이라고 확신하지 않습니다.
이브 다우 스트

답변:


14

여기 아이디어가 있습니다. 이 문제를 여러 단계로 나눕니다.

  1. 평균 직사각형 윤곽 영역을 결정합니다. 그런 다음 임계 값을 지정하고 윤곽의 경계 사각형 영역 을 사용하여 필터링 합니다. 우리가하는 이유는 일반적인 문자가 너무 크지 만 큰 노이즈는 더 큰 직사각형 영역에 걸쳐있을 것이라는 관찰 때문입니다. 그런 다음 평균 면적을 결정합니다.

  2. 큰 특이 치 윤곽을 제거합니다. 윤곽을 다시 반복하고 윤곽 5x을 채워 평균 윤곽 영역보다 큰 경우 큰 윤곽을 제거합니다 . 고정 임계 값 영역을 사용하는 대신이 동적 임계 값을 사용하여 더욱 견고합니다.

  3. 수직 커널로 확장하여 문자를 연결하십시오 . 아이디어는 문자가 열로 정렬되어 있다는 관찰을 이용합니다. 수직 커널로 확장하여 텍스트를 서로 연결하므로 노이즈가이 결합 된 윤곽에 포함되지 않습니다.

  4. 작은 소음을 제거하십시오 . 유지할 텍스트가 연결되었으므로 윤곽을 찾아 4x평균 윤곽 영역 보다 작은 윤곽을 제거합니다 .

  5. 이미지를 비트 단위로 재구성합니다 . 마스크에 유지할 윤곽선 만 있기 때문에 비트 단위로 텍스트를 보존하고 결과를 얻습니다.


프로세스의 시각화는 다음과 같습니다.

우리는 오츠의 임계 값을 바이너리 이미지를 얻기 위해 다음 윤곽 찾을 평균 형상이 직사각형 영역을 결정합니다. 여기에서 등고선채워 녹색으로 강조 표시된 큰 이상치 등고선을 제거합니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

우리가 건설 다음 수직 커널팽창 문자를 연결할 수 있습니다. 이 단계는 원하는 모든 텍스트를 연결하여 노이즈를 개별 블롭으로 유지하고 격리합니다.

여기에 이미지 설명을 입력하십시오

이제 작은 노이즈를 제거하기 위해 윤곽 영역 을 사용하여 윤곽을 찾고 필터링 합니다.

여기에 이미지 설명을 입력하십시오

제거 된 노이즈 입자가 모두 녹색으로 강조 표시되어 있습니다.

여기에 이미지 설명을 입력하십시오

결과

여기에 이미지 설명을 입력하십시오

암호

import cv2

# Load image, grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Determine average contour area
average_area = [] 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    average_area.append(area)

average = sum(average_area) / len(average_area)

# Remove large lines if contour area is 5x bigger then average contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    if area > average * 5:  
        cv2.drawContours(thresh, [c], -1, (0,0,0), -1)

# Dilate with vertical kernel to connect characters
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,5))
dilate = cv2.dilate(thresh, kernel, iterations=3)

# Remove small noise if contour area is smaller than 4x average
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < average * 4:
        cv2.drawContours(dilate, [c], -1, (0,0,0), -1)

# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = (255,255,255)

cv2.imshow('result', result)
cv2.imshow('dilate', dilate)
cv2.imshow('thresh', thresh)
cv2.waitKey()

참고 : 기존 이미지 처리는 임계 값 지정, 형태 학적 작업 및 윤곽선 필터링 (윤곽선 근사, 면적, 종횡비 또는 얼룩 감지)으로 제한됩니다. 입력 이미지는 문자 텍스트 크기에 따라 달라질 수 있으므로 단일 솔루션을 찾는 것은 매우 어렵습니다. 동적 솔루션을위한 머신 / 딥 러닝으로 자신 만의 분류기를 훈련시키는 것이 좋습니다.


1
더 큰 글꼴의 경우 텍스트도 삭제되지 않습니까?
K41F4r

예, 임계 값 영역 값을 조정해야합니다. 보다 동적 인 접근 방식에 대한 아이디어는 사용하는 평균 문자 영역을 결정하는 것입니다 임계 값으로
nathancy

평균 영역을 사용하면 텍스트가 여전히 많이 삭제되어 OCR 결과가 더
나빠질 수 있습니다.

게시물에 추가 할 수있는 다른 입력 이미지 예가 있습니까?
nathancy 2014

1
전통적인 이미지 처리 기술을 사용하여 모든 상황에서 작동하는 솔루션을 찾는 것은 매우 어렵습니다. 딥 러닝을 사용하여 자신의 분류자를 훈련시키는 것이 좋습니다. 행운을 빕니다!
nathancy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.