Python/파이썬 OpenCV 공부

[OpenCV 머신러닝] OpenCV에서 HOG 알고리즘을 이용한 SVM 필기체 숫자 인식

AI 꿈나무 2020. 10. 25. 21:21
반응형

HOG & SVM 필기체 숫자 인식

 픽셀값을 이용하여 SVM을 학습시키는 것보다 HOG 알고리즘으로 추출한 특징 벡터를 이용하여 SVM을 학습시키는 것이 정확도가 더 뛰어납니다.

 이번 포스팅에서는 HOG 특징 벡터를 이용한 SVM 학습 방법에 대해 알아보고 필기체 숫자를 인식해 보겠습니다.

 

필기체 숫자 데이터

 필기체 숫자 데이터는 OpenCV 깃허브에서 제공하는 숫자 데이터를 이용했습니다.

 

opencv/opencv

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

필기체 숫자 데이터

 

 데이터에는 20X20 숫자 영상이 가로 100개, 세로 50개 총 5000개의 숫자가 있습니다.

 각 행에 100개의 데이터가 있고 각 숫자(0~9)는 5줄마다 구분 됩니다.

 

 이 데이터를 이용해서 머신러닝 알고리즘을 학습시키고 추론까지 진행해 보겠습니다.

HOG 특징 벡터를 이용한 SVM 학습

 HOG 알고리즘으로 방향성 정보를 추출하고 방향성 정보를 SVM 알고리즘을 이용하여 10개의 클래스로 분할하는 방법입니다.

 

 OpenCV HOG 알고리즘에 대한 내용은 여기에서 확인할 수 있습니다.

 

[파이썬 OpenCV] HOG 알고리즘을 이용해서 사람 검출하기 - cv2.HOGDescriptor

1. HOG - Histogram of Oriented Gradients  영상의 지역적 그래디언트 방향 정보를 히스토그램으로 표현해서 영상의 형태를 표현하는 방법입니다.  HOG와 SVM 머신러닝을 결합하여 정형화된 객체를 검출하

deep-learning-study.tistory.com

 

 HOG 알고리즘은 입력 영상을 여러 개의 셀과 여러 개의 블록으로 구분합니다.

 여기서 입력 영상은 필기체 숫자 이미지이며 크기는 20x20입니다.

 셀 하나가 5x5크기 이며 4개의 셀을 합쳐 하나의 블록을 만듭니다.

 10x10 크기의 블록이 생성됩니다.

 블록을 겹치게 이동하면 3x3, 총 9개의 블록이 생성됩니다.

 블록 하나당 셀 4개를 갖고 있고 셀 1개당 9개의 방향성 정보를 담고 있기 때문에 블록 하나는 36개의 히스토그램 정보를 담고 있습니다.

 하나의 입력 영상에 블록이 9개이므로 9x36=324 차원의 hog 특징 벡터를 검출합니다.

 

 1행 324열의 특징벡터 5000개를 하나로 묶어 5000x324, float32 형태로 SVM 알고리즘에 입력을 주면 됩니다.

 

HOG & SVM 필기체 숫자 인식 예제

 예제 코드 출처 :  황선규 박사님 github홈페이지 sunkyoo.github.io/opencv4cvml/

 황선규 박사님의 예제코드를 분석하고 실습해보았습니다.

 주의할 점은 입력 데이터의 shape와 type을 알맞게 설정해줘야 합니다.

 

# 마우스로 그림을 그리기 위해 마우스 좌표 갖고오기
oldx, oldy = -1, -1

# 마우스 그림 그리는 인터페이스
def on_mouse(event, x, y, flags, _):
    global oldx, oldy
    
    if event == cv2.EVENT_LBUTTONDOWN:
        oldx, oldy = x, y
        
    elif event == cv2.EVENT_LBUTTONUP:
        oldx, oldy = -1, -1
        
    elif event == cv2.EVENT_MOUSEMOVE:
        if flags & cv2.EVENT_FLAG_LBUTTON:
            cv2.line(img, (oldx, oldy), (x, y), (255, 255, 255), 40, cv2.LINE_AA)
            oldx, oldy = x, y
            cv2.imshow('img', img)
            
# 학습 데이터 & 레이블 행렬 생성
digits = cv2.imread('digits.png', cv2.IMREAD_GRAYSCALE)

if digits is None:
    print('Image load failed!')
    sys.exit()

# 입력 영상의 높이, 넓이
h, w = digits.shape[:2]

# HOGDescriptor 객체 생성
# 영상크기 : 20,20 셀 크기: 5,5 스트라이드: 5,5 방향 히스토그램 빈: 0
hog = cv2.HOGDescriptor((20, 20), (10, 10), (5, 5), (5, 5), 9)

# hog.getDescriptorSize 확인
print('Descriptor Size:', hog.getDescriptorSize())

# 입력 영상 20x20로 분할
cells = [np.hsplit(row, w//20) for row in np.vsplit(digits, h//20)]
cells = np.array(cells)
cells = cells.reshape(-1, 20, 20) # shape = (5000, 20, 20)

# 각각의 셀에 대해서 hogDescriptor 계산
desc = []
for img in cells:
    # 1행 324열을 desc에 차곡차곡 채워 넣기
    desc.append(hog.compute(img))

# train_desc 생성. desc는 5000행 324열
train_desc = np.array(desc) # (5000, 324, 1)

# (5000,324,1) -> (5000,324)
train_desc = train_desc.squeeze().astype(np.float32)

# train_labels 생성
train_lables = np.repeat(np.arrange(10), len(train_desc)/10)

print('train_desc.shape:', train_desc.shape)
print('train_labels.shape:', train_labels.shape)

# SVM 학습

svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF)

# trainAuto로 찾은 값
svm.setC(2.5)
svm.setGamma(0.50625)

svm.train(train_desc, cv2.ml.ROW_SAMPLE, train_labels)
svm.save('svmdigits.yml') # 학습 결과 저장, 이 파일을 이용하면 학습을 하지 않고 predict를 할 수 있다.

# 사용자 입력 영상에 대해 예측

img = np.zeros((400, 400), np.uint8)

cv2.imshow('img', img)
cv2.setMouseCallback('img', on_mouse)

while True:
    key = cv2.waitKey()

    if key == 27:
        break
    elif key == ord(' '): # 스페이스바 누르면 작동
        test_image = cv2.resize(img, (20, 20), interpolation=cv2.INTER_AREA)
        test_desc = hog.compute(test_image).T # svm.predict는 1행 1열로 입력되어야 하므로

        _, res = svm.predict(test_desc)
        # 결과값 출력
        print(int(res[0, 0]))

        img.fill(0)
        cv2.imshow('img', img)

cv2.destroyAllWindows()

 

 

 

 7을 그리니 7을 인식한 모습입니다.

 픽셀값을 이용하는 것보다 방향성 정보를 이용한 것이 정확도가 뛰어난 것을 확인할 수 있었습니다.

 


OpenCV 홈페이지와 황선규 박사님의 'OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝' 을 공부하면서 정리해 보았습니다.

반응형