데이터분석/Python

머신러닝 Example by Python - 주성분 분석을 이용한 사람 얼굴 인식 (이미지 인식 시스템)

버섯도리 2022. 1. 14. 15:00
### 주성분 분석을 이용한 사람 얼굴 인식


## 2. 사이킷런을 이용한 고유 얼굴 검출

import cv2
import sys
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.decomposition import PCA
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC


def read_data(fin):
    """ 이미지 파일을 읽어 들여 이미지 데이터, 이미지 얼굴 번호, 사람 이름을 리턴합니다.
    fin 파일은 각 이미지 데이터의 경로를 포함하고 있습니다.
    """
    target_li = []
    data_li = []
    
    for line in open(fin):
        #working_dir = fin.split('/')[:-1]
        image_path, face_id = line.strip().split(';')
        #image_path = '/'.join(working_dir) + '/' + image_path
        #target_name = image_path.split('/')[1]
        image_data = cv2.imread(image_path, cv2.COLOR_BGR2GRAY)
        
        data_li.append(image_data)
        target_li.append(int(face_id))
    
    return(np.array(data_li), np.array(target_li))


def create_train_test_data(image_data, label_li):
    # 이미지 데이터 수, 이미지 세로 픽셀 크기, 이미지 가로 픽셀 크기
    n_samples, image_h, image_w = image_data.shape
    
    # 가로 픽셀 강도 벡터와 세로 픽셀 강도 벡터를 이어서 하나의 벡터로 만듭니다.
    # 길이는 image_h x image_w가 되겠죠. 그리고 이 벡터가 피처 벡터가 됩니다.
    X = image_data.reshape(n_samples, -1)
    
    n_features = X.shape[1] # 피처 크기
    y = label_li # 학습 레이블
    n_classes = len(set(y)) # 클래스(인물) 수
    
    print("Total dataset size:")
    print("n_samples: %d" % n_samples)
    print("n_features: %d" % n_features)
    print("n_classes: %d" % n_classes)
    
    # 사이킷런의 함수 train_test_split을 이용하여 학습셋과 평가셋을 나눕니다.
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
    
    return(X_train, X_test, y_train, y_test)


def extract_features(X_train, X_test, n_components, image_h, image_w):
    print("Extracting the top %d eigenfaces from %d faces"
          % (n_components, X_train.shape[0]))
    
    pca = PCA(n_components=n_components, svd_solver='randomized', whiten=True).fit(X_train)
    # 고유 얼굴 추출
    eigenfaces = pca.components_.reshape((n_components, image_h, image_w))
    
    # 주성분을 원래 이미지와 같은 차원으로 바꿉니다.
    X_train_pca = pca.transform(X_train)
    X_test_pca = pca.transform(X_test)
    
    return(X_train_pca, X_test_pca, eigenfaces)


def train_test_classifier(X_train_pca, X_test_pca, y_train, y_test):
    print("Fitting the classifier to the traing set")
    param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5],
                  'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], }
    clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid)
    clf = clf.fit(X_train_pca, y_train)
    print("Best estimator found by grid search:")
    print(clf.best_estimator_)
    
    print("Predictiong people's names on the test set")
    y_pred = clf.predict(X_test_pca)
    print(classification_report(y_test, y_pred))


# 플롯 함수
from matplotlib import pyplot as plt

def plot_gallery(images, n_col=5):
    """ 한 줄에 5개의 이미지를 플롯합니다. """
    n_row = round(images.shape[0] / n_col)
    plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
    plt.subplots_adjust(bottom=0.1, left=0.01, right=0.99, top=0.90, hspace=0.35)
    
    for i in range(n_row * n_col):
        plt.subplot(n_row, n_col, i + 1)
        # cmap을 gray로 설정하여 흑백 이미지로 플롯합니다.
        # imshow는 플롯할 값의 최대치를 흰색으로, 최소치를 검은색으로 변환합니다.
        plt.imshow(images[i], cmap='gray')
        # X축과 Y축의 눈금을 없앱니다.
        plt.xticks(())
        plt.yticks(())


if __name__ == '__main__':
    argv = sys.argv
    image_data, label = read_data('faces.csv')
    n_eigenface = 10 # 추출할 고유 얼굴 수
    X_train, X_test, y_train, y_test = create_train_test_data(image_data, label)
    X_train_pca, X_test_pca, eigenfaces = extract_features(X_train, X_test, n_eigenface, 
                                                           image_data.shape[1], image_data.shape[2])
    train_test_classifier(X_train_pca, X_test_pca, y_train, y_test)
    plot_gallery(eigenfaces)
    plt.show()

 

 

 

 

 

 

 

출처 : 처음 배우는 머신러닝 : 기초부터 모델링, 실전 예제, 문제 해결까지