일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- flask
- 110 옮기기
- git-lfs
- 뤼이드
- 스무고개 Metric
- 프로그래머스 여행경로
- 코딩테스트
- 2003 error
- 딥러닝
- 리멤버나우 요약
- flaks
- Convolutional Neural Networks
- 미국 이란 전쟁
- cs231
- pytorch-tutorial
- 이베이 매각
- multi-task learning
- 프로그래머스
- 2003 에러
- git password
- 알고리즘
- aws rds
- but how?
- 리멤버나우
- C++
- 백준 2193
- 웹 독학
- 장영준
- 경제 요약
- 오픈소스
- Today
- Total
Nam's
[신발검색엔진] 05 - 이미지 유사도 측정 모델 개발(VGG16) 본문
지난 토요일 구현한 Autoencoder with VGG16이 성능이 안좋아서 실망하고 오늘(6.28 월) 다시 새로운 마음으로 시작했다. 사실 Autoencoder를 사용했던 것은 그냥 unsupervised 하게 신발의 feature를 학습하려면 그래야할 것 같아서였다. 참고 자료도 없이 그냥 뇌피셜로 진행했던 건데, 이번에는 이미지 유사도 측정 방법들을 먼저 검색해보고 공부해봤다. 찾다보니 CBIR(Contents-Based Image Retrieval) 라는 용어로 지칭하기도 하는 것 같다.
VGG16 - Feature Extraction
[참고자료, 코드출처] - https://ichi.pro/ko/python-eul-sayonghayeo-imiji-geomsaeg-enjin-guchug-190319101887515
결론부터 이야기하면, Autoencoder 없이 VGG16 모델로 imagenet을 pre-train한 모델을 사용하니 유사한 신발을 찾기 시작했다.
VGG16은 기본적으로 Classification을 위한 모델이고, imagenet도 1000개의 label이 있는 image classification dataset이다. 하지만 결국 CNN이 하는 일은 각 이미지의 Feature를 Extract하는 것이다. Extract한 Feature를 가지고 Softmax를 하면 가장 일치하는 Label을 찾을 수 있는 것인데, Softmax를 안하고 Fully Connected Layer까지만 통과하면 Feature Vector가 나온다. FC Layer를 통과했을 때 output을 뽑아서 저장하면 되는 것이다.
class FeatureExtractor:
def __init__(self):
# Use VGG-16 as the architecture and ImageNet for the weight
base_model = VGG16(weights='imagenet')
# Customize the model to return features from fully-connected layer
self.model = Model(inputs=base_model.input, outputs=base_model.get_layer('fc1').output)
def extract(self, img):
# Resize the image
img = img.resize((224, 224))
# Convert the image color space
img = img.convert('RGB')
# Reformat the image
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
# Extract Features
feature = self.model.predict(x)[0]
return feature / np.linalg.norm(feature)
Feature Extract 모델이 준비되었으니 거의 끝난거나 다름없다. 데이터베이스에 저장된 신발 사진들의 Feature를 모두 뽑아서 저장하고, 사용자가 신발 이미지를 입력하면 Feature를 Extract 해서 Feture Vector 차이가 적은 순서대로 이미지를 정렬하면 된다.
Feature 저장
데이터베이스 신발 사진의 Feature Vector를 .npy 파일로 저장한다.
features = []
img_paths = []
# Save Image Feature Vector with Database Images
for i in range(1, 3000):
if i%100 == 0:
print(i)
try:
image_path = "./dataset/m" + str(i) + ".jpg"
img_paths.append(image_path)
# Extract Features
feature = fe.extract(img=Image.open(image_path))
features.append(feature)
# Save the Numpy array (.npy) on designated path
feature_path = "./features/m" + str(i) + ".npy"
np.save(feature_path, feature)
except Exception as e:
print('예외가 발생했습니다.', e)
유사 이미지 탐색
타겟 이미지를 불러와서 Feature Extraction 한 후, 미리 저장해둔 Feature Vector 들과 비교하면 된다. 그런데 이때 비교를 어떻게 할 것인가도 중요하다. 현재 코드상에는 가장 기본적으로 사용하는 L2 norm을 사용해서 이미지 차이(distance)를 계산하고 있다. 이후 Cosinge Similarity 같은 다른 metric으로 평가해봐도 좋을 것 같다.
# Insert the image query
img = Image.open("./test_dataset/t2.jpeg")
# Extract its features
query = fe.extract(img)
# Calculate the similarity (distance) between images
dists = np.linalg.norm(features - query, axis=1)
# Extract 30 images that have lowest distance
ids = np.argsort(dists)[:30]
scores = [(dists[id], img_paths[id], id) for id in ids]
# Visualize the result
axes=[]
fig=plt.figure(figsize=(8,8))
for a in range(5*6):
score = scores[a]
axes.append(fig.add_subplot(5, 6, a+1))
subplot_title=str(round(score[0],2)) + "/m" + str(score[2]+1)
axes[-1].set_title(subplot_title)
plt.axis('off')
plt.imshow(Image.open(score[1]))
fig.tight_layout()
plt.show()
정렬 결과
이제 구두와 슬리퍼 정도는 간단하게 분류하고, 비슷한 신발을 제법 잘 찾는다.
한계
Shoogle.ml 사용자가 과연 이렇게 잘 찍힌 신발 사진을 입력할까? 내가 생각했던 Use case 중에는, 드라마나 영화를 보다가 배우가 신고 있는 신발이 마음에 들 때, 캡쳐해서 올리는 경우도 있다. 이 경우 사람 다리가 이미지에 포함될 것이다.
이 신발을 사용자가 입력했을 때, 기대하는 1순위 상품은 아래 상품이다.
하지만 이미지 탐색 결과 다음과 같은 결과가 나온다.
개선 방향
1. Image Segmentation - 사용자의 입력 이미지 중 신발만을 추출해서 Feature Extraction 모델에 넘겨준다면 위 문제를 해결할 수 있을 것 같다.
2. Transfer Learning - 현재 Feature Extraction에 사용된 모델은 Imagenet만 학습한 모델이다. Fashion MNIST와 우리 신발 이미지 Data를 추가 학습 시킨다면 신발 특징 추출을 더 잘할 수 있을 것으로 기대된다.
1,2 해결 방안을 실행하기에 앞서서 먼저 1차 런칭을 진행하는게 좋을 것 같다. 최대한 빠르게 서비스를 런칭하고 개선해나가는 것이 내 목표였기 때문에 우선 런칭하고 모델을 개선해야겠다. 1차 런칭을 하고 프론트엔드 개발자를 구해서 프론트도 좀 정리하고 주변 사람들을 대상으로 유저 테스트를 진행할 예정이다.
'개발 > Side Project' 카테고리의 다른 글
[신발검색엔진] 07 - 신발 검색 및 쇼핑에 관한 설문조사 (0) | 2021.07.09 |
---|---|
[신발검색엔진] 06 - 인공지능 모델 배포하기 (1) | 2021.07.03 |
[신발검색엔진] 04 - 이미지 유사도 측정 모델 개발(Autoencoder) (0) | 2021.06.28 |
[신발검색엔진] 03 개발 1주차 - 웹 구현 Debugging (0) | 2021.06.26 |
[신발검색엔진] 02 개발 1주차 - 웹 구현 (0) | 2021.06.26 |