본문 바로가기
대회

[bobctf 2020] Catcha (ML)

by jskimm 2022. 1. 10.
728x90

bobctf 2020에 Catcha 라는 문제를 출제했습니다.

Catcha

약 5만장의 강아지와 고양이 사진이 랜덤으로 나오며, 1초 안에 사진에 나온 동물이 강아지인지 고양이인지 맞춰야 하는 captcha solver 문제입니다. 300개의 스테이지를 모두 클리어하면 플래그를 획득할 수 있었습니다.

 

출제 의도는 일종의 '자동 의사 결정기'를 만들 수 있는가?' 였습니다.

 

의도했던 풀이는 사실 CNN과 GAN을 적절히 섞어 하나의 앙상블 모델을 컴파일하고 주어진 데이터셋으로 학습 후 정답을 예측하는 것이였으나, 문제의 난이도를 하향 조절 하다 보니(...) 문제에 제공되는 데이터셋을 전부 제공하게 되었고, 그로 인해 따로 모델을 컴파일하지 않고 주어진 데이터셋으로 일종의 hash table을 만들어 문제를 풀이할 수 있게 되었습니다.

머신러닝으로 풀기

분류해야 할 데이터가 이미지이기 때문에 CNN(Convolutional Neural Network) 모델을 사용합니다. 주어진 데이터셋의 이미지 사이즈가 모두 제각각이기 때문에 어느정도의 preprocessing 이 필요해 보입니다. 또한 훈련의 연산량을 줄여 훈련 효율을 높이기 위해 이미지를 grayscale로 변환했습니다.

  • 이미지 전처리 (Preprocessing)
import numpy as np
import pandas as pd
import cv2
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Dropout, Activation, Conv2D, MaxPooling2D

path = './dataset/train'

X = []
y = [] # target
convert = lambda category : int(category == 'dog')

def preprocess(path):
    for p in os.listdir(path):
        category = p.split(".")[0]
        category = convert(category)
        img_array = cv2.imread(os.path.join(path,p),cv2.IMREAD_GRAYSCALE)
        new_img_array = cv2.resize(img_array, dsize=(80, 80))
        X.append(new_img_array)
        y.append(category)

# preprocess the data
preprocess(path)
X = np.array(X).reshape(-1, 80,80,1)
y = np.array(y)

# normalize data
X = X/255.0
  • 모델 빌드 및 컴파일
model = Sequential()

# add a densely-connected layer with 64 units to the model:
model.add(Conv2D(64,(3,3), activation = 'relu', input_shape = X.shape[1:]))
model.add(MaxPooling2D(pool_size = (2,2)))

# add another layer:
model.add(Conv2D(64,(3,3), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2,2)))

model.add(Flatten())
model.add(Dense(64, activation='relu'))

# add a softmax layer with 10 output units:
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer="adam",
              loss='binary_crossentropy',
              metrics=['accuracy'])
  • 모델 학습
model.fit(X, y, epochs=10, batch_size=32, validation_split=0.2)
  •  이미지 예측
cv2.imread(path, cv2.IMREAD_GRAYSCALE)
# resize
cv2.resize(img_array, dsize=(80,80))
# reshape
data = np.array(data).reshape(-1,80,80,1)
# normalize
data = data/255.0

# predict
model.predict(data)

이후, 학습한 모델을 이용해 문제 이미지를 실시간으로 받아오고 문제의 정답을 예측한 뒤 정답을 서버로 전송하면 됩니다.

hashtable로 풀기

소스코드에 나와있는 kaggle competition에 접속하여 주어진 데이터셋을 모두 다운로드 받은 다음 hash table 을 제작합니다. 이후 문제 이미지에 해당하는 hash를 이용하여 문제의 정답을 구합니다.

728x90

댓글