2017-10-04 9 views
1

이렇게 상자에 쓰여진 손으로 쓴 문자를 추출하고 싶습니다. Form field문서에서 가져온 이미지에서 테두리를 제거하는 방법 (MNIST 필기체 문자와 같은)?

저는 29 픽셀의 너비의 사각형을 추출하고 있습니다.이 사각형은 나에게 이런 이미지를줍니다.

Extracted images 1Extracted Images 2Extracted Images 3

올바르게 문자를 인식하기 위해, 각각의 캐릭터 이미지는 매우 깨끗합니다. 이와 같이, 나는이 일을하고 무엇

Clean chars 1Clean chars 2

,

  1. 계산 수평 및 수직 투사 모든 이미지의 .
  2. 두 배열의 각 요소를 반복합니다. 투영 값이 특정 임계 값보다 큰 경우 경계를 만났음을 의미합니다. 테두리 주위의 공백을 제거합니다.

  3. 그런 다음 이미지에서 윤곽을 찾습니다.

  4. 등고선 영역이 특정 임계 값보다 큰 경우. 경계의 구형을 취득 해 절단합니다.

하지만 문제는 정확하지 않습니다. 경우에 따라 정상적으로 작동하지만 대부분의 경우 비참하게 실패합니다. 이 enter image description here

enter image description here

또한 투영 값이 이미지 (또는이 이미지에 가까운 화상)에 매우 특정 같이 이미지를 생성한다. 그것은 잘 일반화되지 않습니다.

이 상황에서 잘 작동하는 다른 방법이 있습니까?

코드,

char = cv2.imread(image) 
char_gray = cv2.cvtColor(char, cv2.COLOR_BGR2GRAY) 
char_bw = cv2.adaptiveThreshold(char_gray, 255, 
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 9) 

(rows, cols) = char_gray.shape 

bit_not = cv2.bitwise_not(char_bw) 
proj_h = cv2.reduce(bit_nv2.REDUCE_AVG) 

proj_v = cv2.reduce(bit_not, 0, cv2.REDUCE_AVG) 

thresh_h = 200 
thresh_v = 100 

start_x, start_y, end_x, end_y = 0, 0, cols - 1, rows - 1 
#proj_h = proj_h[0] 
proj_v = proj_v[0] 

num_iter_h = cols // 8 
num_iter_v = rows // 8 

for _ in range(num_iter_h): 
    if proj_h[start_y][0] > 35: 
     start_y += 1 

for _ in range(num_iter_h): 
    if proj_h[end_y][0] > 160: 
     end_y -= 1 

for _ in range(num_iter_v): 
    if proj_v[start_x] > 15: #25: 
     start_x += 1 

for _ in range(num_iter_v): 
    if proj_v[end_x] > 125: 
     end_x -= 1 

print('processing.. %s.png' % idx) 
output_char = char[start_y:end_y, start_x:end_x] 
output_char = get_cropped_char(output_char) 
return output_char 


def get_cropped_char(img): 
    """ 
    Returns Grayscale cropped image 
    """ 

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

blur = cv2.GaussianBlur(img, (3,3), 0) 

thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 75, 10) 
im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 

contour = None 
for c in cnts: 
    area = cv2.contourArea(c) 
    if area > 100: 
     contour = c 
if contour is None: return None 
(x, y, w, h) = cv2.boundingRect(contour) 
img = img[y:y+h, x:x+w] 
return img 

답변

1

는 내가 직접 임계 후 이미지를 문자를자를 수있는 좋은 방법이라고 생각하지 않습니다. 나는 morphy-op가 장면을 만들 수 있다고 믿습니다.

블록 요소가 잘 정렬되므로 블록을 분리하거나 블록 경계를 제거하기 위해 morphy-erode-op를 시도하십시오. clean 문자 이미지를 얻으면 문자 이미지를 쉽게자를 수 있습니다.

...

불쌍한 영어, 哈哈哈


이것은 내가 얻을 결과입니다.

자른 이미지.

enter image description here

단계 :

enter image description here

+0

침식 수술에 대해 이야기하고 있습니까? – Arka

+0

예, 알았습니다. – Silencer

+0

와우. 그것은 정확하게하고 싶습니다. 그러나 침식 후에. 상자는 어떻게 분리합니까? – Arka

1

내가 OpenCV의 새로운 오전 (내가 비슷한 프로젝트 ... 작업입니다)하지만, 여기에 내가 경험에서 말할 수있는 것입니다. 적어도 마지막 두 부분은 깨끗한 문자를 추출 할 수 있습니다. 첫 번째 것은 숫자를 가로 지르는 선 때문에 조금 더 어려워집니다.

이미지의 회색 버전을 만들고 임계 값을 입력하고 opening/closing operations을 시도해야합니다. 그 후 각 사각형의 수평/수직선을 제거하려면 morphological transformation을 수행해야합니다. 프로그램의 버전을 시험해 보았는데 40 %의 효과가있었습니다. 나는 그것을 향상시켜야합니다 ...

그 결과, 각 번호의 경계 상자를 추출해야합니다. 그것은 어렵지 않습니다. 일부 숫자는 실패하지만 대부분 숫자가 추출됩니다. "매우 깨끗합니다"는이 단계에서 매우 어렵습니다.

더 많은 연구를 수행하십시오. 대부분의 작업을 수행하는 방법에 대한 많은 예제가 있습니다.

EDIT : 내 이미지와 비슷한 이미지가 있어야합니다. 각각 하나의 숫자 주위, 내부 사각형 보면이 같은 뭔가 작업

example

이 나는 ​​광산에서 얻을 것입니다 .. 더 쉽습니다. 다음 처리를 위해 쉽게 추출하고 저장할 수 있습니다.

example2

+0

나는 또한 OpenCV에 상당히 익숙하다. 나는 지난 몇 주 동안이 문제들과 싸우고있다. 결과가 일관성이 없기 때문에 모든 단일 단계에 적어도 5 가지 방법이 있습니다. 처음/가로선을 사용하여 가로/세로 선을 제거한 다음 윤곽선을 감지 한 다음 감지 된 윤곽선의 경계 영역을 제거합니까? – Arka

+0

글쎄, 지난 3 개월 동안 OpenCV와 Python을 사용하고 있습니다 ... 내가 사용하는 프로세스는 설명 된 것과 거의 비슷합니다. – Link

+0

이미지의 경계를 얼마나 정확하게 제거 할 수 있었습니까? – Arka