본문 바로가기

프로젝트

opencv - 프로젝트 2 - 3. 카드 인식

이전 프로젝트(https://codestudycafe.tistory.com/51)에서 전처리를 했습니다. 이번에는 직접 학습을 시켜 줍시다.

그전에

생각해 보니 모델의 마지막 레이어는 (None, 200, 200, 1)이 됩니다. 이 형식에 train_label을 맞춰줍시다.

모델 생성

이제 모델을 만들어 봅시다.

from keras.layers import Dense, Input, Conv2D, MaxPool2D, Conv2DTranspose, Cropping2D, Concatenate
from keras.models import Model
from keras.activations import sigmoid

input = Input(shape=(200,200,3))
c_1_1 = Conv2D(32,(3,3),padding="same",activation="relu")(input)
c_1_2 = Conv2D(32,(3,3),padding="same",activation="relu")(c_1_1)
c_2_1 = MaxPool2D()(c_1_2)

c_2_2 = Conv2D(64,(3,3), padding="same",activation="relu")(c_2_1)
c_2_3 = Conv2D(64,(3,3), padding="same",activation="relu")(c_2_2)
c_3_1 = MaxPool2D()(c_2_3)

c_3_2 = Conv2D(128,(3,3), padding="same",activation="relu")(c_3_1)
c_3_3 = Conv2D(128,(3,3), padding="same",activation="relu", name="third")(c_3_2)
c_4_1 = MaxPool2D()(c_3_3)

c_4_2 = Conv2D(256,(3,3), padding="same",activation="relu")(c_4_1)
c_4_3 = Conv2D(256,(3,3), padding="same",activation="relu")(c_4_2)

c_5_1 = Conv2DTranspose(128, (3,3), strides=(2,2))(c_4_3)
c_5_2 = Cropping2D(cropping=((0,1),(0,1)))(c_5_1)
c_5_3 = Concatenate()([c_5_2, c_3_3])
c_5_4 = Conv2D(128,(3,3),padding="same",activation="relu")(c_5_3)
c_5_5 = Conv2D(128,(3,3),padding="same",activation="relu")(c_5_4)

c_6_1 = Conv2DTranspose(64, (3,3), strides=(2,2))(c_5_5)
c_6_2 = Cropping2D(cropping=((0,1),(0,1)))(c_6_1)
c_6_3 = Concatenate()([c_6_2, c_2_3])
c_6_4 = Conv2D(64,(3,3),padding="same",activation="relu")(c_6_3)
c_6_5 = Conv2D(64,(3,3),padding="same",activation="relu")(c_6_4)

c_7_1 = Conv2DTranspose(32, (3,3), strides=(2,2))(c_6_5)
c_7_2 = Cropping2D(cropping=((0,1),(0,1)))(c_7_1)
c_7_3 = Concatenate()([c_7_2, c_1_2])
c_7_4 = Conv2D(32,(3,3),padding="same",activation="relu")(c_7_3)
c_7_5 = Conv2D(32,(3,3),padding="same",activation="relu")(c_7_4)

c_8_1 = Conv2D(10,(3,3),padding="same",activation="relu")(c_7_5)
c_8_2 = Conv2D(1,(1,1),padding="same",activation="sigmoid")(c_8_1)

model = Model(input, c_8_2)
model.summary()

처음 팩셀은 200*200이고 이전의 U-net에서 숫자와 층의 개수만 변화를 주었습니다. 그리고 마지막에는 sigmoid를 주었습니다.

 

결과는 0 아니면 1이기 때문에 binary cross entrophy로, optimize는 adam으로 했습니다.

 

데이터가 적기 때문에 아마 오버피팅이 날 것입니다. 어차피 발생할 거 엄청 오버피팅 해보겠습니다. 학습 데이터는 1개, epochs를 50으로 해줍니다.

 

우선 뭔가 줄어든 것이 보입니다. 결과를 보겠습니다.

 

 

 

얼추 보이기는 합니다. 특이한 건 카드의 다이아몬드 부분이 특히 밝게 보입니다.

 

 

데이터의 아래쪽 부분을 보면 아직 학습 중인 것을 알 수 있습니다. 조금 더 학습시켜 봅시다.

 

이전 학습에서 50번을 더 학습시켰습니다. 근데 0.4도 있고 0.09도 있고 그러네요. 이거는 loss를 그래프로 그려봐야 할 것 같습니다.

 

중간에 한번 튀는 게 정말 신경 쓰입니다. 그런데 저의 지식으로는 왜 저러는지 알 수가 없네요. 우선 결과부터 알아봅시다.

 

손 부분이 잘 안 나오지만 어느 정도 비슷하게 알아내고 있습니다. 이제 학습하지 않은 데이터도 넣어봅시다.

원본 이미지

정말 뭔지 전혀 알 수 없네요. 그래도 카드 부분을 살짝은 잡아낼 줄 알았는데 정말 하나도 안 들어가 있습니다.

 

데이터만 조금 모이면 뭔가 될 수도 있을 것 같은데 아직은 부족하네요. 우선 이것으로 만족해야 할 것 같습니다.