본문 바로가기

인공지능/딥러닝

[YOLO] 이미지 증식 테스트 + 사람이미지 증식 및 4차원 독립변수와 종속변수(라벨링) 생성하기 + (응용)비프음 출력

~ 목차 ~

 

이미지 증식 테스트 ✨

 

사용할 라이브러리

 

 

"""이미지 증식에 사용되는 라이브러리"""
from keras.preprocessing.image import ImageDataGenerator

"""numpy 배열을 이미지로 변환하는 라이브러리"""
from keras.preprocessing.image import array_to_img

"""이미지를 numpy 배열로 변환하는 라이브러리"""
from keras.preprocessing.image import img_to_array

"""이미지 읽어들이는 라이브러리"""
from keras.preprocessing.image import load_img

"""시각화"""
import matplotlib.pyplot as plt

 

 

 

이미지 증식 객체 생성하기✨

 

 

* 이미지 증식을 하는 이유?

 - 이미지를 이용하여 모델 훈련 시 데이터 확보가 어려운 경우 수행
 - 기존 이미지 훈련모델의 성능이 낮은 경우에 데이터를 증가 시키고자 할 때 사용
 - 이미지 증식은 하나의 원본 이미지의 형태를 랜덤하게 변형시켜서 많은 양의 이미지를 생성 가능

 

 

이미지 증식 객체 생성하기

 

 

imgGen = ImageDataGenerator(
    ### 이미지 데이터를 0과 1사이의 값으로 정규화하기
    rescale = 1./255,
    ### 이미지 회전 시키기, 0~90사이의 랜덤하게 회전
    rotation_range = 15,
    ### 수평이동 시키기, 0~1 사이의 비율에 따라 랜덤하게 이동
    # - 0.1 = 10%, 10% 비율로 죄/우 랜덤하게 이동
    width_shift_range = 0.1,
    ### 수직이동 시키기
    height_shift_range = 0.1,
    ### 이미지 형태 변형(반시계방향)
    shear_range = 0.5,
    ### 이미지 확대/축소(0.8~2.0 사이의 범위 값으로 랜덤하게 확대/축소)
    zoom_range = [0.8, 2.0],
    ### 수평방향으로 뒤집기 여부
    horizontal_flip = True,
    ### 수직방향으로 뒤집기 여부
    vertical_flip = True,
    ### 이미지 변형 시 발생하는 빈 공간의 픽셀값 처리 방법 지정
    # - nearset : 가까운 곳의 픽셀값으로 채우기(기본값, default, 생략가능)
    #             (주로 사용됨)
    # - reflect : 빈공간 만큼의 영역을 근처 공간의 반전된 픽셀값으로 채우기
    # - wrap :  빈공간을 이동하면서 잘려나간 이미지로 채우기
    # - constant : 빈공간을 검정 또는 흰색으로 채우기
    fill_mode = "nearset"
    
)
imgGen

 

 

원본 이미지 불러오기

 

 - 폴더 생성 : gj_202311/09_딥러닝/08_YOLO_객체탐지_네트워크(모델)/new_img

 

img = load_img("./new_img/cat.jpg")

 

 

 

이미지를 데이터화 시키기 (3차원 데이터)

 

[이미지를 array 배열 데이터로 변환하기]
 - 3차원 데이터로 반환됨

 

img_array = img_to_array(img)
print(img_array.shape)
img_array

 

 

 

 

 

이미지 증식을 위한 데이터는 4차원 데이터

 

 

img_array = img_array.reshape((-1,) + img_array.shape)
img_array.shape

 

(1, 1125, 1125, 3)

 

 

이미지 증식하기 ✨

 

* 이미지를 반복해서 생성

 - flow() : imgGen객체를 이용해서 램덤하게 만들어진 이미지를 저장시키는 함수

 - save_to_dir : 저장할 폴더 위치
 - save_to_prefix : 저장할 파일명에 사용할 이니셜
                            : 이니셜 뒤에 자동으로 이름이 부여됩니다.
 - save_format : 저장할 파일의 포맷, 파일명 뒤에 확장자 정의

 

 - 반복하면서 이미지를 보여주는 경우에는 show()를 사용해야 합니다.
 - 그렇지 않으면 1개의 이미지만 보이게 됩니다.
 - show() 이미지를 보여주고, 자원을 반환하는 역할도 같이 수행됨
 - 자원이 반환되어야 다음 이미지를 plt를 통해서 사용가능

 

 

이미지 증식 코드

 

 - 폴더 생성 : gj_202311/09_딥러닝/08_YOLO_객체탐지_네트워크(모델)/new_img/new

 

### 반복을 종료하기 위한 count값으로 사용
i = 0

### 생성할 이미지 갯수
cnt = 100

### 이미지를 반복해서 생성
for new_img in imgGen.flow(
    img_array,
    save_to_dir="./new_img/new",
    save_prefix="train",
    save_format="png"
) :
    """생성할 이미지 갯수까지만 반복 시키고 반복을 종료시키기"""
    if i > cnt:
        break

    """생성된 이미지 출력하기"""
    plt.imshow(new_img[0])
    plt.axis("off")
    plt.show()

    """반복을 위한 count값 증가"""
    i += 1

print(">>>>>이미지 증식이 종료되었습니다.<<<<<")

 

실행하면 내가 저장한 이미지가 회전 + 이동하면서 총 100개의 이미지로 증식되는 것을 확인할 수 있다. 

 

 

 


 

 

 

사람이미지 증식 및 4차원 독립변수와 종속변수(라벨링) 생성하기 ✨

 

사용할 라이브러리

 

 

import os
import numpy as np
import pandas as pd
"""OpenCV 라이브러리"""
import cv2
"""이미지 증식 라이브러리"""
from tensorflow.keras.preprocessing.image import ImageDataGenerator
"""이미지를 numpy array(배열)로 변환하는 라이브러리"""
from tensorflow.keras.preprocessing.image import img_to_array

 

 

 

 

특정 폴더 내에 모든 원본 이미지를 읽어들이는 함수 정의 ✨

 

특정 폴더 내에 모든 원본 이미지를 읽어들이는 함수 정의

 

* 특정 원본 이미지 폴더 내에 모든 이미지 파일을 읽어들여서, 이미지 픽셀 데이터로 변환해서 리턴하는 함수 정의
- 폴더 생성 : data > 01_org_img, 02_train_img, 03_train_4d_data, 04_detection_img
- 이미지 파일 다운받아서(10개) "01_org_img" 폴더에 넣기

 

def load_images(directory):
    """각 이미지별 변환 데이터를 저장할 리스트 변수"""
    images = []

    """특정 디렉토리의 모든 파일 읽어들이기"""
    for filename in os.listdir(directory):
        
        """특정 확장자를 가지는 파일만 읽어들이기"""
        if filename.endswith((".jpg", ".jpeg", ".png")) :
            """파일명 추출"""
            img_path = os.path.join(directory, filename)

            """이미지를 3차원 데이터로 변환하기"""
            img = cv2.imread(img_path)

            """이미지 데이터의 픽셀 크기를 너비 180, 높이 185로 통일시키기(정규화)"""
            img = cv2.resize(img, (180, 185))

            """변환된 이미지 데이터를 리스트 변수에 담기"""
            images.append(img)
    
    """numpy 배열로 변환하여 리턴"""
    return np.array(images)

 

 

 

 

읽어들인 모든 원본 이미지 각각에 대해서 이미지 증식 및 종속변수(라벨) 정의 함수 ✨

 

읽어들인 모든 원본 이미지 각각에 대해서 이미지 증식 및 종속변수(라벨) 정의 함수

 

 - images : 원본 전체에 대한 각 이미지 데이터
 - output_directory : 증식한 이미지를 저장할 폴더 위치
 - target_filename : 종속변수 데이터를 저장할 (폴더 + 파일명)

 

def create_images(images, output_directory, target_filename):
    ### 종속변수 데이터를 담을 리스트 변수
    target = []

    ### 이미지 10개(원본 이미지 10개에 대한)에 대한 라벨링 기준
    # - 1은 위험인자, 0은 좋은인자
    target_list = [1, 0, 1, 0, 1, 1, 0, 1, 1, 0]

    ######## 이미지 증식 객체 생성하기 ##########
    datagen = ImageDataGenerator(
                rescale = 1./255,
                rotation_range = 15,
                width_shift_range = 0.1,
                height_shift_range = 0.1,
                shear_range = 0.5,
                zoom_range = [0.8, 2.0],
                horizontal_flip = True,
                vertical_flip = True,
                fill_mode = "nearest"
                )
    ######## 이미지 증식 시키기 ########
    # - i : images의 인덱스 번호
    # - img : 각 인덱스별 이미지 데이터
    for i, img in enumerate(images) :
        print(f"-----------------[ {i+1} / {len(images)} ]번째 증식 중-----------------")

        ### 3차원 이미지 데이터를 4차원으로 변환하기
        img = img.reshape((1,) + img.shape)

        ### 증식된 이미지를 저장할 파일명 정의
        save_prefix = "train_img_" + str(i)

        ### 각 이미지 별로 생성(증식)할 이미지의 갯수 정의
        create_img_cnt = 20

        ######## 이미지 증식 및 파일 저장 시키기 ########
        for batch in datagen.flow(
                                  img,
                                  save_to_dir=output_directory,
                                  save_prefix=save_prefix,
                                  save_format="png"
                                  ):
            ### 증식된 이미지 별로 [종속변수]로 사용할 값을 리스트에 담기

            target.append(target_list[i])

            create_img_cnt -= 1

            ### 생성할 이미지 갯수만큼 만들어지면 반복 종료시키기
            if create_img_cnt == 0:
                break

    ### 종속변수 리스트를 numpy 배열 타입으로 변환하기
    target = np.array(target)

    ### 종속변수 리스트를 numpy 파일로 저장시키기
    # - target_filename : 저장할 폴더 + 파일명
    # - target : 종속변수 리스트
    np.save(target_filename, target)

"""
너무 많은 증식을 할 경우, 원하는 갯수만큼 증식이 안되는 경우 있음.
 - 증식을 만드는 시간과, 시스템 폴더에 저장되는 시간차로 발생
 - 많은 양을 만들 경우 조금씩 여러번에 걸쳐서 증식...
"""

 

 

 

 

증식한 이미지 폴더 내에 모든 이미지 파일을 차원 데이터로 변환 및 저장하는 함수 ✨

 

증식한 이미지 폴더 내에 모든 이미지 파일을 차원 데이터로 변환 및 저장하는 함수

 

*  증식된 파일이 저장된 폴더 내 모든 파일에 대해서

 - 4차원 데이터로 변환하여  numpy 배열 형태로 저장시키기
 - output_directory : 증식된 파일이 위치한 폴더
 - save_4d_filename : 저장할 파일명

 

def save_4d_data(output_directory, save_4d_filename) :
    ### 4차원 데이터를 담을 리스트 변수
    data = []

    ### 증식된 모든 파일 읽어들이기
    for filename in os.listdir(output_directory) : 
        if filename.endswith((".jpg", ".jpeg", ".png")) :
            img_path = os.path.join(output_directory, filename)

            ### 3차원 데이터로 읽어들이기
            img = cv2.imread(img_path)

            
            ### 픽셀 정규화
            img = cv2.resize(img, (180, 185))

            # print(img)
            
            ### 리스트에 담기
            data.append(img)

    data = np.array(data)
    print("최종 처리 결과 : ", data.shape)
    
    np.save(save_4d_filename, data)

 

 

 

 

함수 호출✨

 

함수 호출

 

 

"""특정 폴더 내에 모든 이미지 파일 로드하여, 이미지 데이터로 변환하는 함수 호출"""


### 폴더 위치 지정
input_directory="./data/01_org_img/"

### 함수 호출하기
images = load_images(input_directory)
images.shape

 

(10, 185, 180, 3)


 

"""이미지 증식 및 파일저장, 종속변수 생성 및 파일 저장 함수 호출"""
### 증식된 이미지 파일 저장 폴더
output_directory = "./data/02_train_img/"

### 종속변수 데이터 파일명
# - numpy 파일의 확장자는 보통 .npy를 사용합니다.
target_filename = "./data/03_train_4d_data/target_data.npy"

### 함수 호출하기
create_images(images, output_directory, target_filename)

 

-----------------[ 1 / 10 ]번째 증식 중-----------------
-----------------[ 2 / 10 ]번째 증식 중-----------------
-----------------[ 3 / 10 ]번째 증식 중-----------------
-----------------[ 4 / 10 ]번째 증식 중-----------------
-----------------[ 5 / 10 ]번째 증식 중-----------------
-----------------[ 6 / 10 ]번째 증식 중-----------------
-----------------[ 7 / 10 ]번째 증식 중-----------------
-----------------[ 8 / 10 ]번째 증식 중-----------------
-----------------[ 9 / 10 ]번째 증식 중-----------------
-----------------[ 10 / 10 ]번째 증식 중-----------------


 

"""증식된 이미지 각각에 대한 이미지 데이터로 변환하여 numpy 배열 파일로 저장하기"""
save_4d_filename = "./data/03_train_4d_data/train_4d_data.npy"

save_4d_data(output_directory, save_4d_filename)

 

최종 처리 결과 :  (200, 185, 180, 3)

 


 

""" numpy로 저장된 독립변수와 종속변수 데이터 확인하기 """
train = np.load(save_4d_filename)
target = np.load(target_filename)
train.shape, target.shape

 

((200, 185, 180, 3), (200,))

 

 

 

4차원 이미지 데이터와 종속변수 데이터를 읽어들여서 CNN 훈련시키기✨

 

4차원 이미지 데이터와 종속변수 데이터를 읽어들여서 CNN 훈련시키기

 

 - 독립변수 : image_data, 종속변수 : label_data
 - 픽셀 데이터 정규화 (0~1 범위)
 - 훈련 및 테스트 = 8 : 2로 분리
   사용변수 x_train, x_test, y_train, y_test

 

<CNN 모델 생성하기>
 - 입력계층 : CNN 모델 사용, 출력크기 32, 커널사이즈 3, 활성화 함수 렐루
 - 은닉계층 : MaxPooling도 사용해보시고, 전처리 1차원 계층도 자유롭게 사용해서 생성
 - 출력계층 : 직접

<모델 설정>
 - 옵티마이저 : 아담, 손실함수 : 각자, 출력값 : 각자

<훈련>
 - 반복횟수 15번만, 배치사이즈 32개

<테스트 데이터로 검증>

validation_split=0.2 : 훈련 데이터에서 20%를 검증 데이터로 사용하라는 의미
- fit() 함수 실행 시 내부적으로 다시 분류하여 사용함

 

###  사용할 라이브러리 다시 정의
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split

 

"""독립변수 : image_data, 종속변수 : label_data"""
image_data = np.load("./data/03_train_4d_data/train_4d_data.npy")
label_data = np.load("./data/03_train_4d_data/target_data.npy")

"""픽셀 데이터 정규화 (0~1 범위)"""
image_data = image_data / 255.0

 

"""훈련 및 테스트 = 8 : 2로 분리
 - 사용변수 x_train, x_test, y_train, y_test"""

x_train, x_test, y_train, y_test = train_test_split(image_data, label_data, test_size = 0.2, random_state=42)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)

 

model = tf.keras.Sequential()

model.add(tf.keras.layers.Conv2D(kernel_size=3, filters=32, activation="relu", padding="same", strides=1, input_shape=(185, 180, 3)))
model.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
model.add(tf.keras.layers.Conv2D(kernel_size=3, filters=64, activation="relu", padding="same", strides=1))
model.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
model.add(keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64, activation="relu"))
model.add(tf.keras.layers.Dense(1, activation="sigmoid"))

model.compile(optimizer="adam", loss="binary_crossentropy", metrics="accuracy")

 

model.fit(x_train, y_train, epochs=15, batch_size=32, validation_split=0.2)

 

 

(160, 185, 180, 3) (160,)
(40, 185, 180, 3) (40,)

 

 

 

 

(응용)CNN 모델을 이용해서 위험한 사람 확인 및 비프음 발생시키기✨

 

(응용)CNN 모델을 이용해서 위험한 사람 확인 및 비프음 발생시키기

 

 

"""사용 라이브러리"""
import os
import platform
### 윈도우 OS인 경우에만 사용(mac은 제외)
import winsound
import time

 

"""예측할 이미지 불러오기"""
## target_list = [1, 0, 1, 0, 1, 1, 0, 1, 1, 0]

"""위험한 분"""
pred_img = cv2.imread("./data/04_detection_img/0_1.png")

"""착한 분"""
# pred_img = cv2.imread("./data/04_detection_img/1_0.png")

pred_img.shape

"""predict()하기"""
pred_img = cv2.resize(pred_img, (180, 185))
pred_img = pred_img.reshape((1,) + pred_img.shape)
pred_data = pred_img / 255.0
y_pred = model.predict(pred_data)
y_pred

 

"""확률이 50%인 경우 위험인자로 인식해서 비프음 발생하기"""
if y_pred[0] > 0.5 :
    print(f"인식률[{y_pred[0]}] : 위험한 분이셔요~~!!")

    """비프음 발생시키기"""
    ### 윈도우 OS인 경우
    if platform.system() == "Windows" :
        ### 1000 : 소리 주파수(소리 높낮이 조정값)
        # 보통 사람의 청각 범위 : 20Hz~20,000Hz 정도..
        ### 500 : 지속시간 (1000은 1초, 500은 0.5초)
        for i in range(5) :
            winsound.Beep(1000, 500)
            time.sleep(0.5)
            
    ### MAC인 경우 abs
    elif platform.system() == "Darwin" :
        os.system("osascipt -e 'beep'")
else : 
    print(f"인식률[{y_pred[0]}] : 착한분 ^__^ b")

 

 

"""위험한 분"""
pred_img = cv2.imread("./data/04_detection_img/0_1.png")

"""착한 분"""
# pred_img = cv2.imread("./data/04_detection_img/1_0.png")

 

번갈아 가면서 실행을 하면 위험한 분인 경우 

▶ 인식률[[0.770599]] : 위험한 분이셔요~~!!  + 경고음(비프음)

 

착한 분인 경우

▶인식률[[0.16912082]] : 착한분 ^__^ b

 

 

728x90