- 이미지 읽기
- 이미지 이진화 (그레이스케일로 변환 -> 블러 처리 -> 이진화)
- 윤곽 검출
GaussianBlur() - 화이트 노이즈 제거에 많이 사용
img = cv2.GaussianBlur(img, (ax, ay), sigma_x)
- img : 원본 이미지
- (ax, ay) : 블러 처리를 적용할 화소 크기를 픽셀 단위로 지정, 값에는 홀수를 지정
- sigma_x : 가로 방향 표준 편차, 0으로 지정하면 전체 크기를 기반으로 자동 지정
블러 처리 함수를 적용하면 이미지 전체에 흐림 효과가 적용, cv2.bilateralFilter()는 엣지를 남기고 흐림 효과 적용
ret, img = cv2.threshold(img, thresh, maxval, type)
- 이미지의 화소가 지정한 역치보다 크면 흰색, 작으면 검은색으로 만들어 줌
- img : 그레이스케일 이미지
- thresh : 역치 값
- maxval : 역치 값 이상의 값에 설정할 값
- type : 어떻게 역치값을 처리할 것인가 (THRESH_BINARY_INV - 역치 값보다 큰 값일 때 0, 그 외는 maxval 할당)
contours, hierarchy = cv2.findContours(imgae, mode, method)
-
mode |상수|의미| |:-----------:|:-------------:| |cv2.RETR_LIST|단순한 윤곽 검출| |cv2.RETR_EXTERNAL|가장 외곽에 있는 윤곽을 검출| |cv2.RETR_CCOMP|계층을 고려해 2레벨 윤곽을 검출| |cv2.RETR_TREE|모든 윤곽을 검출하고 계층 구조로 저장|
-
method |상수|의미| |:----------------:|:----------------:| |cv2.CHAIN_APPROX_NONE|윤곽 위에 있는 모든 점을 반환| |cv2.CHAIN_APPROX_SIMPLE|의미 없는 정보를 제거하고 반환|
import cv2
import matplotlib.pyplot as plt
# 엽서 이미지에서 우편 번호를 추출하는 함수
def detect_zipno(fname):
# 이미지 읽어 들이기
img = cv2.imread(fname)
# 이미지 크기 구하기
h, w = img.shape[:2]
# 이미지의 오른쪽 윗부분만 추출하기 (우편 번호가 이미지의 우측 상단에 있으니 위의 1/2부분과 오른쪽의 2/3부분만 추출)
img = img[0:h//2, w//3:]
# 이미지 이진화하기
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 그레이스케일
gray = cv2.GaussianBlur(gray, (3, 3), 0) # 흐림 처리
im2 = cv2.threshold(gray, 140, 255, cv2.THRESH_BINARY_INV)[1] # 이진화
# 윤곽 검출하기
cnts = cv2.findContours(im2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
# 추출한 이미지에서 윤곽 추출
result = []
for pt in cnts:
x, y, w, h = cv2.boundingRect(pt) # 추출한 윤곽을 단순한 [x, y, 너비, 높이] 형태의 리스트로 변환
# 너무 크거나 너무 작은 부분 제거하기
if not(50 < w < 70): continue
result.append([x, y, w, h])
# 추출한 윤곽을 위치에 따라 정렬하기
result = sorted(result, key=lambda x: x[0]) # 추출한 영역을 x 방향으로 정렬 (왼쪽부터 차례대로 영역을 추출하기 위함)
# 추출한 윤곽이 너무 가까운 것들 제거하기
result2 = []
lastx = -100
for x, y, w, h in result:
if (x - lastx) < 10: continue
result2.append([x, y, w, h])
lastx = x
# 초록색 테두리 출력하기
for x, y, w, h in result2:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 3)
return result2, img
if __name__ == '__main__':
# 이미지를 지정해서 우편번호 추출하기
cnts, img = detect_zipno('./data/letter01.png')
# 결과 출력하기
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
import matplotlib.pyplot as plt
import joblib
# 학습한 데이터 읽어 들이기
clf = joblib.load('./data/digits.pkl')
# 이미지에서 영역 읽어 들이기
cnts, img = detect_zipno('./data/letter01.png')
# 읽어 들인 데이터 출력
for i, pt in enumerate(cnts):
x, y, w, h = pt
# 윤곽으로 감싼 부분을 작게 만들기
x += 8
y += 8
w -= 16
h -= 16
# 이미지 데이터 추출
im2 = img[y:y+h, x:x+w]
# 데이터를 학습에 적합하게 변환
im2gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 그레이스케일
im2gray = cv2.resize(im2gray, (8,8)) # 크기 변경
im2gray = 15 - im2gray // 16 # 이진화
im2gray = im2gray.reshape((-1, 64)) # 차원 변환
# 데이터 예측
res = clf.predict(im2gray)
# 출력
plt.subplot(1, 7, i+1)
plt.imshow(im2)
plt.axis('off')
plt.title(res)
plt.show()