Mahotas 모듈을 이용한 유사한 이미지 찾기 모델
학과 경진대회에서 사용하기 위해 찾은 모델이다. Mahotas 모듈을 이용하여 이미지 셋에서 유사한 이미지를 찾아준다. 그대로 사용하려해도 계속 오류가 떠서 수정하고 생략한 부분이 있다. Google Colab을 이용했다. 아직 다 이해하지는 못했지만 아는 부분이라도 기록하려 한다.
https://github.com/luispedro/BuildingMachineLearningSystemsWithPython
pip install numpy --upgrade
pip install mahotas
pip install imread
데이터 불러와서 리스트에 넣기
from glob import glob
import mahotas as mh
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
images = glob('img_set/*.jpg') #img 리스트를 만든다. jpg 외의 파일형을 넣으면 오류가 난다.
이미지 흑백 처리하기
im = mh.imread(images[0])
im = mh.colors.rgb2gray(im, dtype=np.uint8)
# 이미지를 흑백처리하는 부분에서 오류가 나서 추가했다.
im
Haralick을 적용한다. 이를 통해 이미지의 질감(물과 땅이 다르듯)을 구분할 수 있다.
mh.features.haralick(im)
이미지들의 특징으로 리스트로 만든다.
import imageio
import time
import numpy as np
from skimage import data
from skimage.color import rgb2gray
def to_gray_uint(image): # 이미지 흑백 처리하는 부분이다.
return np.uint8(rgb2gray(image) * 255)
features = []
labels = [] # 분류 class list
start = time.time()
for im in images:
labels.append(im[8:-len('land0001.jpg')+5])
# img 이름에 따라 라벨링하는 부분이다. 파일 이름에 따라 수정해야한다.
# 예를 들어 land0001.jpg~land0100.jpg는 land0이라는 라벨이 붙는다.
# 분류하고 싶은 클래스의 이미지끼리 같은 이름으로 만들어야한다.
im = imageio.imread(im)
im=to_gray_uint(im) # 흑백처리, int형으로 변환
# im = mh.colors.rgb2gray(im, dtype=np.unit8)
features.append(mh.features.haralick(im).ravel())
print(f'fit time : {time.time() - start}')
이미지의 특징과 라벨을 배열로 만든다.
features = np.array(features)
labels = np.array(labels)
features
로지스틱 회귀(Logistic Regression)를 적용한다 하는데 이 부분은 이해가 안된다...ㅠㅠ
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
clf = Pipeline([('preproc', StandardScaler()),
('classifier', LogisticRegression())])
clf
이미지의 라벨을 맞출 확률을 구한다.
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, features, labels)
scores
# 정확도
print('Accuracy: {:2%}'.format(scores.mean()))
disits는 각 이미지가 어떤 이미지와 가장 비슷한지를 나타낸다.
from scipy.spatial import distance
sc = StandardScaler()
features = sc.fit_transform(features)
dists = distance.squareform(distance.pdist(features)) # 이미지 간의 차이(오차율이라 할 수 있다)
def selectimage(n, m, dists, images): # n번째로 유사한 이미지를 반환한다.
image_position = dists[n].argsort()[m]
image = mh.imread(images[image_position])
return image
n 번째 이미지와 비슷한 이미지를 3장을 출력한다.
def plotImages(n):
fig, ax = plt.subplots(1,4, figsize = (15,5))
for i in range(4):
ax[i].imshow(selectimage(n,i, dists, images))
# 유사한 이미지를 찾을 이미지, 찾을 갯수, 이미지 간에 거리, 이미지 리스트
ax[i].set_xticks([])
ax[i].set_yticks([])
plt.show()
# 코드에 없던 부분인데 추가했다
# 내가 찾는 이미지의 순서를 찾아 아래 셀에서 출력한다
j=0
k=0
for i in images:
j=j+1
if i=='img_set/water001.jpg': # 내가 찾고자하는 이미지
k=j-1
plotImages(k) # 비슷한 이미지 3장을 출력
기본 원리는 ResNet과 유사하다. 이미지 간의 유사도를 구해서 유사도가 높은 순서대로 이미지 3장을 출력한다.
나는 입력한 배경 사진과 유사한 배경에서 찍은 인물 사진을 찾아주는 모델을 구현하려 했다. water과 land 두 가지 라벨로, water 500장, land 800장을 학습시켰다. 정확도는 약 83%가 나왔고, 사람 눈으로 보았을 때 water는 비슷한 이미지를 잘 찾아주었지만 land는 전혀 다른 이미지를 출력하기도 했다. 발표를 준비하면서는 급한 마음이었는지 발견하지 못했던 문제들이 발표 후에 교수님들의 평가를 들으면서 깨달았다.
- 사용자의 정보(키, 몸매, 나이, 성별 등) 없이 이미지만 추천해 주는 거는 포즈 추천 모델이 아니라 그냥 유사한 이미지를 찾아주는 모델에 불과하다. 다시 한다면 이미지 추천보다는 GAN을 이용한 이미지 합성 방향으로 해야겠다.
- land class를 하나로 묶기에는 종류(산, 건물, 평지 등)가 너무 많아 제대로 분류하지 못한다. class를 나누거나 이미지 수집을 훨씬 많이 해야 한다.
이런 인공지능 프로젝트는 처음이었고 아쉬움이 많았으나 도중에 포기하지 않고 발표까지 마쳤다는 점으로 만족한다. 다음에는 좀 더 잘하고 싶다.