

import cv2
import numpy as np
# 물체 추적 함수 정의
def start_tracking():
# 비디오 캡쳐 오브젝트 초기화
cap = cv2.VideoCapture(0)
# 프레임에 대한 크기 조정 인자 정의
scaling_factor = 0.5
# 추적할 프레임 수
num_frames_to_track = 5
# 건너뛸 프레임 수
num_frames_jump = 2
# 변수 초기화
tracking_paths = []
frame_index = 0
# 추적 매개변수(윈도우 크기, 최대 수준, 종료 조건) 정의
tracking_params = dict(winSize = (11, 11), maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,
10, 0.03))
# 사용자가 ESC 키 누를 때까지 반복
while True:
# 카메라에서 현재 프레임 캡쳐
_, frame = cap.read()
# 프레임 크기 조정
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
# RGB 프레임을 흑백으로 변환
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 복사본 생성
output_img = frame.copy()
# 추적 경로의 길이가 0보다 큰지 확인
if len(tracking_paths) > 0:
# 이미지 가져오기
prev_img, current_img = prev_gray, frame_gray
# 특징점 구성
feature_points_0 = np.float32([tp[-1] for tp in \
tracking_paths]).reshape(-1, 1, 2)
# 광학 흐름 계산 (이전 프레임과 현재 프레임 사이의)
feature_points_1, _, _ = cv2.calcOpticalFlowPyrLK(
prev_img, current_img, feature_points_0,
None, **tracking_params)
# 역(reverse) 광학 흐름 계산
feature_points_0_rev, _, _ = cv2.calcOpticalFlowPyrLK(
current_img, prev_img, feature_points_1,
None, **tracking_params)
# 순 광학 흐름과 역 광학 흐름 사이의 차이 계산
diff_feature_points = abs(feature_points_0 - \
feature_points_0_rev).reshape(-1, 2).max(-1)
# 대표 특징점 추출
good_points = diff_feature_points < 1
# 새로운 추적 경로에 대한 변수 초기화
new_tracking_paths = []
# 추출한 대표 특징점에 대해 루프를 돌며 그 주위에 원을 그림
for tp, (x, y), good_points_flag in zip(tracking_paths,
feature_points_1.reshape(-1, 2), good_points):
# 플래그가 차밍 아니면 건너뜀
if not good_points_flag:
continue
# x, y 좌표를 추가하고 추적할 프레임의 수 초과하지 않는지 확인
# (x, y 지점까지의 거리가 임계점을 넘지 않는지 확인)
# 넘으면 삭제
tp.append((x, y))
if len(tp) > num_frames_to_track:
del tp[0]
new_tracking_paths.append(tp)
# 특징점 주위에 원 그리기
cv2.circle(output_img, (x, y), 3, (0, 255, 0), -1)
# 추적 경로 업데이트
tracking_paths = new_tracking_paths
# 선 그리기
cv2.polylines(output_img, [np.int32(tp) for tp in \
tracking_paths], False, (0, 150, 0))
# 지정된 프레임 수만큼 건너뛰고 나서 if 조건문으로 들어감
if not frame_index % num_frames_jump:
# 마스크 생성한 후 원 그림
mask = np.zeros_like(frame_gray)
mask[:] = 255
for x, y in [np.int32(tp[-1]) for tp in tracking_paths]:
cv2.circle(mask, (x, y), 6, 0, -1)
# 추적할 대표 특징점 계산
# 함수에 여러 가지 매개변수(마스크, 최대 모서리, 품질 수준, 최소 거리, 블록 크기)
# 를 지정해서 호출하는 방식으로 처리
feature_points = cv2.goodFeaturesToTrack(frame_gray,
mask = mask, maxCorners = 500, qualityLevel = 0.3,
minDistance = 7, blockSize = 7)
# 특징점이 있다면 추적 경로에 추가
if feature_points is not None:
for x, y in np.float32(feature_points).reshape(-1, 2):
tracking_paths.append([(x, y)])
# 변수 업데이트
frame_index += 1
prev_gray = frame_gray
# 결과 출력
cv2.imshow('Optical Flow', output_img)
# 사용자가 ESC 키 눌렀으면 빠져나감
c = cv2.waitKey(1)
if c == 27:
break
if __name__ == '__main__':
# 추적기 시작
start_tracking()
# 모든 창(window) 닫기
cv2.destroyAllWindows()
Haar cascades(하 케스케이드):
Haar feature(하 특징)에 대한 여러 개의 분류기를 순차적으로 거치는 방식으로 물체를 감지하는 기법
Viola-Jones(비올라-존스) 기법
비올라-존스 기법으로 얼굴 검출하는 머신 러닝 시스템 구축하려면:

import cv2
import numpy as np
# Haar cascade 파일 불러옴
face_cascade = cv2.CascadeClassifier(
'haar_cascade_files/haarcascade_frontalface_default.xml')
# 파일 체크
if face_cascade.empty():
raise IOError('Unable to load the face cascade classifier xml file')
# 비디오 캡처 오브젝트 초기화
cap = cv2.VideoCapture(0)
# 크기 조정 인자 정의
scaling_factor = 0.5
# 사용자가 ESC 키 누를 때까지 반복
while True:
# 카메라에서 현재 프레임 캡쳐
_, frame = cap.read()
# 프레임 크기 조정
frame = cv2.resize(frame, None,
fx=scaling_factor, fy=scaling_factor,
interpolation=cv2.INTER_AREA)
# grayscale로 변환
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 흑백 이미지에 대해 얼굴 검출기 실행
face_rects = face_cascade.detectMultiScale(gray, 1.3, 5)
# 얼굴 주위에 직사각형 그리기
for (x,y,w,h) in face_rects:
cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3)
# 결과 화면 출력
cv2.imshow('Face Detector', frame)
# ESC 눌렸는지 확인하고 빠져나옴
c = cv2.waitKey(1)
if c == 27:
break
# 비디오 캡처 오브젝트 해제
cap.release()
# 창 모두 닫기
cv2.destroyAllWindows()
사람의 학습 과정: 계층적 구성 -> 주어진 물체에 관련된 여러 특성을 순식간에 구분하여 물체를 식별함
사람 뇌 신경망:
인공 신경망:
N차원의 입력 데이터를 처리하기 위해 입력 계층은 N개의 뉴런으로 구성됨
M개의 독립적인 클래스로 구분한 학습 데이터를 처리하기 위해 출력 계층은 M개의 뉴런으로 구성됨
입출력 계층 사이에 존재하는 계층을 hidden layer(은닉 계층, 내부 계층, 중간 계층)라고 함
간단한 신경망은 2계층으로, deep neural network(심층 신경망)은 여러 계층으로 구성됨
데이터 분류 작업을 신경망으로 구현하는 경우:
아래 예제 구현 시 NeuroLab 라이브러리 사용

Perceptron:
뉴로랩 라이브러리로 퍼셉트론 기반 분류기 만들기 시작
import numpy as np
import matplotlib.pyplot as plt
import neurolab as nl
# 입력 데이터 가져오기
text = np.loadtxt('data_perceptron.txt')
# 데이터 포인트와 레이블로 나누기
data = text[:, :2]
labels = text[:, 2].reshape((text.shape[0], 1))
# 입력 데이터 그래프 그리기
plt.figure()
plt.scatter(data[:,0], data[:,1])
plt.xlabel('Dimension 1')
plt.ylabel('Dimension 2')
plt.title('Input data')
# 각 차원에 대한 최댓값, 최솟값 지정하기
dim1_min, dim1_max, dim2_min, dim2_max = 0, 1, 0, 1
# 출력 계층에 있는 뉴런의 수
# 데이터를 두 개의 클래스로 분리했기에 하나의 비트만으로 결과 표현 가능
# 따라서 출력 계층은 하나의 뉴런으로 구성됨
num_output = labels.shape[1]
# 2개의 입력 뉴런으로 구성된 퍼셉트론 정의
# 입력 데이터가 2차원이기 때문
# 각 차원마다 하나의 뉴런 할당
dim1 = [dim1_min, dim1_max]
dim2 = [dim2_min, dim2_max]
perceptron = nl.net.newp([dim1, dim2], num_output)
# 학습 데이터로 퍼셉트론 학습 시키기
error_progress = perceptron.train(data, labels, epochs=100, show=20, lr=0.03)
# 학습 과정을 그래프로 표시
# 오차 값 기준
plt.figure()
plt.plot(error_progress)
plt.xlabel('Number of epochs')
plt.ylabel('Training error')
plt.title('Training error progress')
plt.grid()
plt.show()
# 첫 번째 화면은 입력 데이터 포인트를 보여줌
# 두 번째 화면은 오차 값을 이용한 학습 진행 상태 보여줌
# 4번째 학습 주기(epoch)가 끝나는 시점에 오차가 0으로 떨어짐


