python 에서 opencv 문자 분할 실천

11890 단어 opencv문자 분할
그림 과 문 자 를 분할 할 때 자주 사용 하 는 방법 은 두 가지 가 있다.하 나 는 투영 법 으로 조판 이 정연 하고 글자 간격 이 비교적 넓 은 이미지 에 적용 된다.또 하 나 는 OpenCV 의 윤곽 검 측 으로 문자 가 불규칙 하 게 배 열 된 이미지 에 적용 된다.
투영 법
텍스트 그림 을 가로 와 세로 로 투영 하 는 것 은 각 줄 의 픽 셀 갯 수 를 통계 하고 각 열 의 픽 셀 갯 수 를 통 해 문 자 를 분할 하 는 것 이다.
각각 수평 과 수직 방향 에서 예비 처리(이치 화)이미지 의 특정한 픽 셀 을 통계 하고 이치 화 이미지 가 검 지 않 으 면 흰색 이 며 우 리 는 그 중의 흰 점 이나 검 은 점 을 통계 함으로써 통계 결과 에 따라 각 줄 의 상하 경계 와 각 열의 좌우 경 계 를 판단 하여 분할 의 목적 을 실현 할 수 있다.
알고리즘 단계:
4.567917.수평 투영 과 수직 투영 방식 으로 이미지 분할 을 하고 투영 구역 의 크기 에 따라 줄 과 각 구역 을 나 누 어 원시 이미지 에 대해 이치 화 처 리 를 한다4.567917.투영 하기 전에 이미지 그 레이스 케 일 을 조정 하여 팽창 조작 을 한다4.567917.수평 투영 과 수직 투영 을 실시한다4.567917.투영 의 길이 와 높이 에 따라 전체 줄 과 블록 정 보 를 구한다가로 판 문자-소표 문자 분할

#      
import cv2
import numpy as np

img = cv2.imread(r"C:\Users\An\Pictures\1.jpg")
cv2.imshow("Orig Image", img)
#            
sp = img.shape
print("    :", sp)
sz1 = sp[0]  # height(rows) of image
sz2 = sp[1]  # width(columns) of image
sz3 = sp[2]  # the pixels value is made up of three primary colors
print('width: %d 
height: %d
number: %d' % (sz2, sz1, sz3)) gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) retval, threshold_img = cv2.threshold(gray_img, 120, 255, cv2.THRESH_BINARY_INV) cv2.imshow("threshold_img", threshold_img) # gray_value_x = [] for i in range(sz1): white_value = 0 for j in range(sz2): if threshold_img[i, j] == 255: white_value += 1 gray_value_x.append(white_value) print("", gray_value_x) # hori_projection_img = np.zeros((sp[0], sp[1], 1), np.uint8) for i in range(sz1): for j in range(gray_value_x[i]): hori_projection_img[i, j] = 255 cv2.imshow("hori_projection_img", hori_projection_img) text_rect = [] # inline_x = 0 start_x = 0 text_rect_x = [] for i in range(len(gray_value_x)): if inline_x == 0 and gray_value_x[i] > 10: inline_x = 1 start_x = i elif inline_x == 1 and gray_value_x[i] < 10 and (i - start_x) > 5: inline_x = 0 if i - start_x > 10: rect = [start_x - 1, i + 1] text_rect_x.append(rect) print(" , Y:", text_rect_x) # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 3)) dilate_img = cv2.dilate(threshold_img, kernel) cv2.imshow("dilate_img", dilate_img) for rect in text_rect_x: cropImg = dilate_img[rect[0]:rect[1],0:sp[1]] # y-start:y-end,x-start:x-end sp_y = cropImg.shape # gray_value_y = [] for i in range(sp_y[1]): white_value = 0 for j in range(sp_y[0]): if cropImg[j, i] == 255: white_value += 1 gray_value_y.append(white_value) # veri_projection_img = np.zeros((sp_y[0], sp_y[1], 1), np.uint8) for i in range(sp_y[1]): for j in range(gray_value_y[i]): veri_projection_img[j, i] = 255 cv2.imshow("veri_projection_img", veri_projection_img) # inline_y = 0 start_y = 0 text_rect_y = [] for i in range(len(gray_value_y)): if inline_y == 0 and gray_value_y[i] > 2: inline_y = 1 start_y = i elif inline_y == 1 and gray_value_y[i] < 2 and (i - start_y) > 5: inline_y = 0 if i - start_y > 10: rect_y = [start_y - 1, i + 1] text_rect_y.append(rect_y) text_rect.append([rect[0], rect[1], start_y - 1, i + 1]) cropImg_rect = threshold_img[rect[0]:rect[1], start_y - 1:i + 1] # cv2.imshow("cropImg_rect", cropImg_rect) # cv2.imwrite("C:/Users/ThinkPad/Desktop/cropImg_rect.jpg",cropImg_rect) # break # break # print(" (y-start:y-end,x-start:x-end):", text_rect) rectangle_img = cv2.rectangle(img, (text_rect[0][2], text_rect[0][0]), (text_rect[0][3], text_rect[0][1]), (255, 0, 0), thickness=1) for rect_roi in text_rect: rectangle_img = cv2.rectangle(img, (rect_roi[2], rect_roi[0]), (rect_roi[3], rect_roi[1]), (255, 0, 0), thickness=1) cv2.imshow("Rectangle Image", rectangle_img) key = cv2.waitKey(0) if key == 27: print(key) cv2.destroyAllWindows()
소표 이미지 이치 화 결 과 는 다음 과 같다.
在这里插入图片描述
소표 그림 결 과 는 다음 과 같 습 니 다.
在这里插入图片描述
세로 판-고문 문자 분할
고서 에 있어 고서 문 자 는 습관 적 으로 위 에서 아래로 쓰 이기 때문에 스 캔 할 때 열 을 스 캔 하여 투영 하고 스 캔 줄 에 투영 해 야 한다.
1.원본 그림 의 이치 화
수평 투영 과 수직 투영 방식 으로 이미지 분할 을 하고 투영 구역 의 크기 와 크기 에 따라 각 줄 과 각 조각의 구역 을 분할 하여 원시 이미 지 를 이치 화 처리한다.
원본 그림:
在这里插入图片描述
2 값 화 된 그림:
在这里插入图片描述
2.이미지 팽창
투영 하기 전에 이미지 그 레이스 케 일 을 조정 하여 팽창 조작 을 하고 적당 한 핵 을 선택 하여 이미지 에 대해 팽창 처 리 를 한다.
在这里插入图片描述
3.수직 투영
이 줄 의 텍스트 영역 지정:
수치 가 0 이 아 닌 구역 은 문자 가 존재 하 는 곳(즉,이치 화 후 흰색 부분의 구역)이 고 0 인 구역 은 줄 마다 떨 어 진 거리 이다.
1.앞의 수가 0 이면 첫 번 째 0 이 아 닌 좌 표를 기록한다.
2.앞의 수가 0 이 아니라면 첫 번 째 가 0 인 좌 표를 기록한다.이미지 란 첫 번 째 비 공백 열 이 나타 날 때 부터 첫 번 째 공백 열 이 나타 날 때 까지 이 구역 이 바로 문자 가 존재 하 는 구역 이라는 것 이다.
상기 규칙 을 통 해 각 열 문자 의 시작 점 과 종료 점 을 찾 아 각 열의 위치 정 보 를 확정 할 수 있다.
수직 투영 결과:
在这里插入图片描述
위의 수직 투영 을 통 해 흰색 작은 산봉우리 의 시작 위치 에 따라 각 열의 시작 위 치 를 정 하고 각 열 을 나 눌 수 있다.
4.수평 투영
투영 의 길이 와 높이 에 따라 전체 줄 과 블록 정 보 를 구하 다.
수평 투영 을 통 해 모든 문자 좌우 의 시작 위 치 를 얻 을 수 있 습 니 다.그러면 모든 문자 의 구체 적 인 좌표 위치,즉 사각형 상자 의 위 치 를 얻 을 수 있 습 니 다.

import cv2
import numpy as np
import os

img = cv2.imread(r"C:\Users\An\Pictures\3.jpg")
save_path=r"E:\crop_img\result" #             
crop_path=r"E:\crop_img\img" #         
cv2.imshow("Orig Image", img)
#            
sp = img.shape
print("    :", sp)
sz1 = sp[0]  # height(rows) of image
sz2 = sp[1]  # width(columns) of image
sz3 = sp[2]  # the pixels value is made up of three primary colors
print('width: %d 
height: %d
number: %d' % (sz2, sz1, sz3)) gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) retval, threshold_img = cv2.threshold(gray_img, 120, 255, cv2.THRESH_BINARY_INV) cv2.imshow("threshold_img", threshold_img) cv2.imwrite(os.path.join(save_path,"threshold_img.jpg"),threshold_img) # gray_value_y = [] for i in range(sz2): white_value = 0 for j in range(sz1): if threshold_img[j, i] == 255: white_value += 1 gray_value_y.append(white_value) print("", gray_value_y) # veri_projection_img = np.zeros((sp[0], sp[1], 1), np.uint8) for i in range(sz2): for j in range(gray_value_y[i]): veri_projection_img[j, i] = 255 cv2.imshow("veri_projection_img", veri_projection_img) cv2.imwrite(os.path.join(save_path,"veri_projection_img.jpg"),veri_projection_img) text_rect = [] # inline_y = 0 start_y = 0 text_rect_y = [] for i in range(len(gray_value_y)): if inline_y == 0 and gray_value_y[i]> 30: inline_y = 1 start_y = i elif inline_y == 1 and gray_value_y[i] < 30 and (i - start_y) > 5: inline_y = 0 if i - start_y > 10: rect = [start_y - 1, i + 1] text_rect_y.append(rect) print(" , Y:", text_rect_y) # # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 3)) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) dilate_img = cv2.dilate(threshold_img, kernel) cv2.imshow("dilate_img", dilate_img) cv2.imwrite(os.path.join(save_path,"dilate_img.jpg"),dilate_img) for rect in text_rect_y: cropImg = dilate_img[0:sp[0],rect[0]:rect[1]] # y-start:y-end,x-start:x-end sp_x = cropImg.shape # gray_value_x = [] for i in range(sp_x[0]): white_value = 0 for j in range(sp_x[1]): if cropImg[i, j] == 255: white_value += 1 gray_value_x.append(white_value) # hori_projection_img = np.zeros((sp_x[0], sp_x[1], 1), np.uint8) for i in range(sp_x[0]): for j in range(gray_value_x[i]): veri_projection_img[i, j] = 255 # cv2.imshow("hori_projection_img", hori_projection_img) # inline_x = 0 start_x = 0 text_rect_x = [] ind=0 for i in range(len(gray_value_x)): ind+=1 if inline_x == 0 and gray_value_x[i] > 2: inline_x = 1 start_x = i elif inline_x == 1 and gray_value_x[i] < 2 and (i - start_x) > 5: inline_x = 0 if i - start_x > 10: rect_x = [start_x - 1, i + 1] text_rect_x.append(rect_x) text_rect.append([start_x - 1, i + 1,rect[0], rect[1]]) cropImg_rect = threshold_img[start_x - 1:i + 1,rect[0]:rect[1]] # crop_img=img[start_x - 1:i + 1,rect[0]:rect[1]] # # cv2.imshow("cropImg_rect", cropImg_rect) # cv2.imwrite(os.path.join(crop_path,str(ind)+".jpg"),crop_img) # break # break # print(" (y-start:y-end,x-start:x-end):", text_rect) rectangle_img = cv2.rectangle(img, (text_rect[0][2], text_rect[0][0]), (text_rect[0][3], text_rect[0][1]), (255, 0, 0), thickness=1) for rect_roi in text_rect: rectangle_img = cv2.rectangle(img, (rect_roi[2], rect_roi[0]), (rect_roi[3], rect_roi[1]), (255, 0, 0), thickness=1) cv2.imshow("Rectangle Image", rectangle_img) cv2.imwrite(os.path.join(save_path,"rectangle_img.jpg"),rectangle_img) key = cv2.waitKey(0) if key == 27: print(key) cv2.destroyAllWindows()
분할 결 과 는 다음 과 같다.
在这里插入图片描述
분할 의 결 과 를 보면 기본적으로 그림 속 문자 의 분할 을 실현 했다.그러나 중국어 구조의 복잡성 으로 인해 일부 문자 의 분할 이 이상 적 이지 않 고 글 자 는 과도 하 게 분할 되 고 붙 어 있 는 두 글 자 는 분할 이 부족 한 현상 이 나타 날 수 있다.이미지 전처리(이미지 부식 팽창),경계 판단 한도 값 조정 등 측면 에서 최적화 할 수 있다.
python 에서 opencv 가 문자 분할 을 실현 하 는 실천 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 opencv 문자 분할 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기