웹캠을 사용한 필기 숫자 인식 예제(OpenCV+python)

  • by

코드를 보자.

PC에 탑재된 웹캠으로 촬영중인 영상을 OpenCV로 읽은 후 영상 내에서 필기체 수를 검출하는 예입니다.

필기체수는, 랜덤 포레스트 방식으로 사전 학습된 모델을 개입시켜 예측하는 방법으로 검출합니다.

학습은 다음 이미지에서 수행되었습니다.


코드를 봐!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#웹캠을 사용한 필기 숫자 인식
import cv2
import numpy as np
import pickle
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
# 필기 수치 데이터 읽기
img = cv2.imread(“digits.png”cv2.IMREAD_GRAYSCALE)
= (np.hsplit(row,100) forin np.vsplit(img,50))
x = np.array(cells)
X = x(:,:).reshape(1,400).astype(np.float32)
y = np.repeat (np.arange (10),500)
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.3)
test_y(:100)
모델 = RandomForestClassifier()
model.fit(train_X, train_y)
model.score(test_X, test_y)
# 모델 저장
with open(“digits.model”, “wb”) as f:
pickle.dump(model, f)
# 모델 로드
with open(“digits.model”, “rb”) as f:
모델 = pickle.load(f)
# 실시간으로 동영상을 로드하고 숫자 인식
cap = cv2.VideoCapture (0)
if cap.isOpened():
while True:
ret, img = cap.read()
if ret:
g_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thr, bin_img = cv2.threshold(g_img, 110, 255cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(bin_img, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
try:
for i in 범위(len(contours)):
contour = contours(i)
(x,y), radius = cv2.minEnclosingCircle(contour)
if radius > 3:
xs, xe = int(xradius), int(x+radius)
ys, ye = int(yradius), int(y+radius)
cv2.rectangle(bin_img, (xs,ys), (xe,ye), (200,0,0), 1)
roi = bin_img(ys:ye, xs:xe)
dst = cv2.resize(roi, dsize=(50, 50), interpolation=cv2.INTER_AREA)
dst = cv2.resize(dst, dsize=(16, 16), interpolation=cv2.INTER_AREA)
A = np.zeros((20,20))
A(2:2,2:2) = dst(:,:)
A = A.reshape (1,400)
num = model.predict(A)
cv2.putText(bin_img, str(num), (xs, ys), cv2.FONT_HERSHEY_PLAIN, 2(200,0,0))
except 예외 as e:
#print(e)
pass
cv2.imshow (“Video Capture”bin_img)
= cv2.waitKey (1)
if== 27:
#ESC 키를 누르면
break
else:
인쇄(“No Frame…”)
break
else :
인쇄(“Camera not opened…”)
cap.release()
cv2.destroyAllWindows()

주석을 기반으로 예제 시나리오(?)를 쉽게 정리합니다.

# 필기 수치 데이터 읽기

그럼 문자 그대로 필기 수치 데이터를 읽습니다.

필기체수로 채워진 이미지를 읽고, 영역을 일정한 크기의 셀로 나누고, 그 중 일정량을 학습용 데이터에, 일정량을 검증 테스트용 데이터로 나누어 학습 결과를 확인합니다.

코드의 16번째 줄을 보면 여기에서 랜덤 포리스트 분류가 사용되고 있음을 알 수 있습니다.

랜덤 포리스트 방식의 설명을 정리하려면 문장이 길어질 수밖에 없는 것 같습니다.

# 모델 저장하기 모델 로드

모델을 저장하는 경우 다른 Python 스크립트에서도 모델을 사용할 수 있도록 바이너리 프로토콜로 내보내는 프로세스이고, 모델 로드는 해당 모델을 다시 로드하는 프로세스입니다.

따라서 이 두 프로세스는 위의 예가 아니더라도 괜찮습니다.

# 실시간으로 동영상을 로드하고 숫자 인식

라인 29에서는 OpenCV의 VideoCapture 함수를 사용하여 웹캠에서 비디오를 로드합니다.

이때 영상을 한 번만 읽으면 정지화면이 나타나게 되므로 while 반복문을 통해 지속적으로 영상을 읽어오게 했습니다.

35행과 36행에서는 이미지를 회색조로 만들고, 임계값을 조정하여 물체를 더 잘 감지할 수 있습니다.

단지 수만 검출되는 것이 아니라, 물체라고 판단되는 것을 모방 검출하기 때문에 주의가 필요합니다.

이미지에서 물체가 검출되면, 그 영역에 사각형을 그려 물체가 검출되었음을 나타내(45회), 모델이 숫자를 예측하고(52회) 숫자를 표시하는 방법(53번) 로 작업합니다.

아래 이미지는 위의 예를 실행한 후 웹캠에 숫자 5가 쓰여진 종이를 넣을 때(?) 결과 화면입니다.