머신 러닝 : 데이터 분석 → 규칙성, 패턴 찾기
과정
일부 : 성능 측정을 위한 테스트 용도
분류
supervised learning(지도 학습)
unsupervised learning(비지도 학습)
영상 픽셀값 : 머신러닝 입력으로 사용 X
개요
기계학습 - 수치적 방법 (오류 조금씩 줄이는 과정)
모델의 오류 측정하는 손실 함수 필요
훈련 데이터에 포함된 잡음, 이상치(outlier) 영향 고려
훈련데이터를 효과적으로 구분하는 경계면 찾기
→ 실제 새로운 입력 데이터에 대해서는 정확도 떨어짐
→ 잡음, 잘못 측정된 값일 가능성
→ 녹색 실선 경계면 사용
train(samples, layout, responses);
//정상 학습되면 true 반환
R | G | B | Label | |
---|---|---|---|---|
S1 | 250 | 150 | 100 | 사과 |
S2 | 바나나 | |||
… |
predict(samples, results=noArray(), flags = 0)
import numpy as np
import cv2
train = [] # 훈련 데이터와 레이블 저장할 리스트
label = []
k_value = 1 # 초기 K값 설정
def on_k_changed(pos): # 변경될 때마다 k-NN 모델 재학습
global k_value
k_value = pos
if k_value < 1: # 최소 1이 되도록
k_value = 1
trainAndDisplay() # 결과 훈련 및 표시
def addPoint(x, y, c): # 훈련 세트에 새 데이터 포인트 추가
train.append([x, y]) # 훈련 데이터에 점 추가
label.append([c]) # 해당 레이블 추가
def trainAndDisplay(): # k-NN 분류기 훈련 -> 결과 표시
train_array = np.array(train).astype(np.float32)
label_array = np.array(label)
knn.train(train_array, cv2.ml.ROW_SAMPLE, label_array)
for j in range(img.shape[0]): # 이미지 각 픽셀에 대해 반복
for i in range(img.shape[1]):
# 샘플 포인트 생성
sample = np.array([[i, j]]).astype(np.float32)
# 가장 가까운 이웃 찾기
ret, res, _, _ = knn.findNearest(sample, k_value)
response = int(res[0, 0]) # 예측된 레이블 가져오기
if response == 0: # 예측된 레이블에 따라 픽셀 색상 변경
img[j, i] = (128, 128, 255)
elif response == 1:
img[j, i] = (128, 255, 128)
elif response == 2:
img[j, i] = (255, 128, 128)
for i in range(len(train)): # 훈련 포인트 이미지에 그리기
x, y = train[i]
l = label[i][0]
if l == 0: # 각 훈련 포인트에 원 그리기
cv2.circle(img, (x, y), 5, (0, 0, 128), -1, cv2.LINE_AA)
elif l == 1:
cv2.circle(img, (x, y), 5, (0, 128, 0), -1, cv2.LINE_AA)
elif l == 2:
cv2.circle(img, (x, y), 5, (128, 0, 0), -1, cv2.LINE_AA)
cv2.imshow('knn', img)
img = np.zeros((500, 500, 3), np.uint8) # 500x500크기 3개의 색상 채널
knn = cv2.ml.KNearest_create() # k-NN 분류기 생성
cv2.namedWindow('knn')
cv2.createTrackbar('k_value', 'knn', k_value, 5, on_k_changed)
NUM = 30
rn = np.zeros((NUM, 2), np.int32)
cv2.randn(rn, 0, 50) # 클래스 0 에 속하는 점 추가
for i in range(NUM):
addPoint(rn[i, 0] + 150, rn[i, 1] + 150, 0)
cv2.randn(rn, 0, 50)
for i in range(NUM): # 클래스 1에 속하는 점 추가
addPoint(rn[i, 0] + 350, rn[i, 1] + 150, 1)
cv2.randn(rn, 0, 70)
for i in range(NUM): # 클래스 2에 속하는 점 추가
addPoint(rn[i, 0] + 250, rn[i, 1] + 400, 2)
trainAndDisplay()
cv2.imshow('knn', img)
cv2.waitKey()
cv2.destroyAllWindows()
2차원 점 분류
(a) k = 1
클래스 경계면이 유난히 볼록하게 튀어나온 부분 발생
(b) k = 3, (c) k = 5
다소 완만한 형태
k값이 증가함에 따라 잡음, 이상치 영향 감소
import sys
import numpy as np
import cv2
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] # 이미지에서 각 숫자 분리
cells = [np.hsplit(row, w/20) for row in np.vsplit(digits, h/20)]
cells = np.array(cells)
train_images = cells.reshape(-1, 400).astype(np.float32)
train_labels = np.repeat(np.arange(10), len(train_images) / 10)
knn = cv2.ml.KNearest_create() # k-NN 분류기 생성
knn.train(train_images, cv2.ml.ROW_SAMPLE, train_labels)
img = np.zeros((400, 400), np.uint8)
cv2.imshow('img', img)
cv2.setMouseCallback('img', on_mouse)
while True:
c = cv2.waitKey()
if c == 27:
break
elif c == ord(' '):
img_resize = cv2.resize(img, (20, 20), interpolation=cv2.INTER_AREA)
img_flatten = img_resize.reshape(-1, 400).astype(np.float32)
_ret, res, _, _ = knn.findNearest(img_flatten, 3)
print(int(res[0, 0]))
img.fill(0) # 이미지 초기화
cv2.imshow('img', img)
cv2.destroyAllWindows()
import numpy as np
import cv2
train = np.array([[150, 200], [200, 250],
[100, 250], [150, 300],
[350, 100], [400, 200],
[400, 300], [350, 400]]).astype(np.float32)
label = np.array([0,0,0,0,1,1,1,1])
svm = cv2.ml.SVM_create() # SVM 분류기 생성
svm.setType(cv2.ml.SVM_C_SVC) # 유형 설정
svm.setKernel(cv2.ml.SVM_RBF) # 커널 설정
# svm.setKernel(cv2.ml.SVM_LINEAR)
svm.trainAuto(train, cv2.ml.ROW_SAMPLE, label) # 자동 매개변수 조정
img = np.zeros((500, 500, 3), np.uint8)
for j in range(img.shape[0]): # 각 픽셀에 대해 예측 수행
for i in range(img.shape[1]):
test = np.array([[i, j]], dtype = np.float32) # 현재 픽셀 위치
_, res = svm.predict(test) # SVM으로 예측
if res == 0: # 레이블 0일 경우 색상 설정
img[j, i] = (128, 128, 255)
elif res == 1: # 레이블 1일 경우
img[j, i] = (128, 255, 128)
color = [(0, 0, 128), (0, 128, 0)] # 레이블 별 색상 정의
for i in range(train.shape[0]):
x = int(train[i, 0])
y = int(train[i, 1])
l = label[i]
cv2.circle(img, (x, y), 5, color[l], -1, cv2.LINE_AA)
cv2.imshow('svm', img)
cv2.waitKey()
cv2.destroyAllWindows()
20x20 영상
5x5 셀
10x10 블록 사용
9개의 그래디언트 방향 히스토그램
→ hog(Size(20, 20), Size(10, 10), Size(5, 5), Size(5, 5), 9);
import sys
import numpy as np
import cv2
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]
# HOG 디스크립터 설정 : 윈도우크기, 블록크기, 셀크기, 블록스트라이드, 방향그래디언트 빈의수
hog = cv2.HOGDescriptor((20, 20), (10, 10), (5, 5), (5, 5), 9)
# 숫자 이미지 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)
# HOG 특징 벡터 계산
desc = []
for img in cells:
dd = hog.compute(img)
desc.append(dd)
train_desc = np.array(desc).squeeze().astype(np.float32)
train_labels = np.repeat(np.arange(10), len(train_desc)/10)
# SVM 분류기 생성 및 설정
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF)
svm.setC(2.5)
svm.setGamma(0.50625)
svm.train(train_desc, cv2.ml.ROW_SAMPLE, train_labels)
img = np.zeros((400, 400), np.uint8)
cv2.imshow('img', img)
cv2.setMouseCallback('img', on_mouse)
while True:
c = cv2.waitKey()
if c == 27:
break
elif c == ord(' '):
img_resize = cv2.resize(img, (20, 20), interpolation=cv2.INTER_AREA)
desc = hog.compute(img_resize)
test_desc = np.array(desc).astype(np.float32)
_, res = svm.predict(test_desc.T)
print(int(res[0,0]))
img.fill(0)
cv2.imshow('img', img)
cv2.destroyAllWindows()