Posts Mahotas로 해보는 비슷한 이미지 찾기
Post
Cancel

Mahotas로 해보는 비슷한 이미지 찾기

1. Mahotas


1.1 Mahotas

https://mahotas.readthedocs.io/en/latest/

  • pip install mahotas
  • Mahotas는 Python 용 컴퓨터 비전 및 이미지 처리 라이브러리
  • 여기에는 속도를 위해 C ++로 구현 된 많은 알고리즘이 포함되어 있으며 매우 깨끗한 Python 인터페이스를 사용하여 numpy 배열에서 작동함

2. 실습


2.1 데이터 설명

https://github.com/luispedro/BuildingMachineLearningSystemsWithPython/tree/master/SimpleImageDataset

  • 건물, 자연경관, 문서 각 30장짜리 데이터
  • Building Machine Learning Systems with Python의 예제 자료

2.2 Data Load

1
2
3
4
5
6
7
from glob import glob
import mahotas as mh
import numpy as np
import matplotlib.pyplot as plt

images = glob('./data/SimpleImageDataset/*.jpg')
images[:5]
1
2
3
4
5
['./data/SimpleImageDataset/text20.jpg',
 './data/SimpleImageDataset/building13.jpg',
 './data/SimpleImageDataset/text08.jpg',
 './data/SimpleImageDataset/building07.jpg',
 './data/SimpleImageDataset/scene07.jpg']
  • 필요한 패키지를 불러오고, glob을 활용하여 각 이미지경로를 list에 담음


2.3 라벨 처리

1
images[0][26:-len('00.jpg')]
1
'text'
  • 파일의 라벨을 보면 text20.jpg 처럼 text의 20번째 jpg 파일이란 뜻
  • 라벨 뒤의 번호는 버리고 text만 가져옴
  • 이미지 파일이 있는 경로가 다르기 떄문에 오프셋인덱스의 26은 각자 상황에 맞게 바꿔야함


2.4 Gray로 변경

1
2
3
im = mh.imread(images[0])
im = mh.colors.rgb2gray(im, dtype=np.uint8)
im
1
2
3
4
5
6
7
array([[156, 176, 175, ..., 189, 187, 186],
       [154, 171, 169, ..., 188, 186, 185],
       [161, 175, 170, ..., 187, 186, 186],
       ...,
       [152, 153, 153, ..., 181, 181, 182],
       [152, 152, 152, ..., 181, 180, 182],
       [151, 152, 152, ..., 182, 181, 183]], dtype=uint8)
  • 이미지들을 Gray 컬러로 변경함


2.5 Haralick 적용

1
mh.features.haralick(im)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
array([[ 3.66204021e-03,  7.44385321e+01,  9.69875419e-01,
         1.23551148e+03,  4.76090180e-01,  3.21647886e+02,
         4.86760740e+03,  7.07458389e+00,  9.51129063e+00,
         1.00520606e-03,  2.93680057e+00, -4.35358414e-01,
         9.97483493e-01],
       [ 2.84549272e-03,  1.19362555e+02,  9.51673431e-01,
         1.23495790e+03,  4.04957709e-01,  3.21652894e+02,
         4.82046903e+03,  7.07435139e+00,  9.86550048e+00,
         8.21391898e-04,  3.27570061e+00, -3.76958948e-01,
         9.94872815e-01],
       [ 3.66198391e-03,  5.61980068e+01,  9.77246908e-01,
         1.23495320e+03,  4.78601123e-01,  3.21649202e+02,
         4.88361480e+03,  7.07197481e+00,  9.44835451e+00,
         1.03328177e-03,  2.83518971e+00, -4.45619712e-01,
         9.97778262e-01],
       [ 2.82616958e-03,  1.26394950e+02,  9.48826212e-01,
         1.23495792e+03,  4.03305323e-01,  3.21652893e+02,
         4.81343672e+03,  7.07529020e+00,  9.88137065e+00,
         8.17570442e-04,  3.28551507e+00, -3.74348101e-01,
         9.94707031e-01]])
  • Haralick는 이미지의 날카로움을 잘 나타낸다고 알려져 있음
  • Haralick는 이미지의 질감에 대해 2차원 특징을 추출하는 알고리즘


2.6 이미지를 특성 데이터로 전환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time

features = []
labels = []

start = time.time()

for im in images:
    labels.append(im[26:-len('00.jpg')])
    im = mh.imread(im)
    im = mh.colors.rgb2gray(im, dtype = np.uint8)
    features.append(mh.features.haralick(im).ravel())

print(f'fit time : {time.time() - start}')
1
fit time : 26.879966974258423
  • 이미지간 유사도 검출을 위해 이미지를 특성 데이터로 전환함


2.7 Array 전환

1
2
3
features = np.array(features)
labels = np.array(labels)
features
1
2
3
4
5
6
7
8
9
10
11
12
13
array([[ 3.66204021e-03,  7.44385321e+01,  9.69875419e-01, ...,
         3.28551507e+00, -3.74348101e-01,  9.94707031e-01],
       [ 1.28249663e-02,  4.87581223e+01,  9.94975935e-01, ...,
         3.91602238e+00, -3.87974632e-01,  9.97929776e-01],
       [ 7.63507483e-04,  4.50258748e+01,  9.89989318e-01, ...,
         3.76396230e+00, -3.97447535e-01,  9.98546677e-01],
       ...,
       [ 2.75960062e-03,  1.08364337e+02,  9.54449800e-01, ...,
         3.44586857e+00, -3.70228466e-01,  9.95528380e-01],
       [ 4.44557401e-03,  5.74946979e+01,  9.54265194e-01, ...,
         3.42370629e+00, -3.36906001e-01,  9.90473989e-01],
       [ 3.85204285e-04,  8.62514064e+01,  9.89901742e-01, ...,
         4.11483879e+00, -3.67041452e-01,  9.98309470e-01]])
  • 생성한 결과를 array로 변경함


2.8 Logistic Regression 적용

1
2
3
4
5
6
7
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

clf = Pipeline([('preproc', StandardScaler()),
                ('classifier', LogisticRegression())])
clf
1
2
Pipeline(steps=[('preproc', StandardScaler()),
                ('classifier', LogisticRegression())])
  • Standardscaler와, LogisticRegression을 pipeline으로 생성


2.9 Cross Validation

1
2
3
4
from sklearn.model_selection import cross_val_score

scores = cross_val_score(clf, features, labels)
scores
1
array([0.77777778, 0.88888889, 0.83333333, 0.88888889, 0.77777778])
  • CV를 5번 진행하였을떄 라벨(text 등)을 맞춘 확률


1
print('Accuracy: {:2%}'.format(scores.mean()))
1
Accuracy: 83.333333%
  • CV의 Accuracy는 83%정도 나온다


2.10 Scaler

1
2
3
4
5
6
from scipy.spatial import distance

sc = StandardScaler()
features = sc.fit_transform(features)

dists = distance.squareform(distance.pdist(features))
  • feature에 scaler를 손으로 적용


2.11 Dists는?

1
dists[0]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
array([ 0.        ,  9.52430388,  6.80370623,  9.32497065, 11.25987833,
       10.61131364,  9.4115134 , 10.59962453,  1.77757172,  9.41331504,
       13.44918325,  3.00852352,  6.28968132,  8.65644664, 10.61250131,
       14.90126811, 16.93407315,  8.82744014, 13.01219666, 12.19972587,
        7.91865399,  3.32765773, 10.00279286,  9.30144472,  6.9250823 ,
        5.90013122,  9.86700903, 14.41636827, 11.73352847,  7.69310467,
       14.42948581, 11.93597518,  8.64056175,  4.14724299, 10.57420591,
        9.42784866,  2.71311061,  9.60793104,  9.13885778,  3.21521643,
        7.92824414,  8.97416642, 11.45093424, 10.59822376,  1.63251016,
        9.21061649,  7.58279627, 10.7034599 ,  7.53869737,  3.80226852,
        3.70638927,  8.66907659, 12.77482358, 10.85494835,  3.99808513,
       10.18964684,  3.56897747, 16.7687143 , 10.46788865,  5.13169458,
        6.0190094 , 10.50286623, 14.49668247, 16.94976398, 11.12082812,
        8.78755595, 14.83611024,  5.64524318, 11.34606274,  3.85074009,
        9.24280937,  8.01420865,  6.93247105,  4.90357171, 10.93565002,
       12.63837001, 19.37773956,  9.68593925, 10.77371778,  3.27491197,
        2.13785205, 10.99261702,  8.97774871,  4.225051  ,  4.6199186 ,
       11.70321631, 15.44084137,  2.30388604,  3.66714748, 10.50795977])
  • dists 행렬은 각 이미지가 어떤 이미지와 가장 비슷한지 거리를 보여주는것임
  • dists[0]은 0번째 이미지가 다른 나머지 이미지들과의 거리를 나타냄


2.12 유사한 이미지를 찾는 함수

1
2
3
4
def selectimage(n, m, dists, images):
    image_position = dists[n].argsort()[m]
    image = mh.imread(images[image_position])
    return image
  • n : 유사한 이미지를 찾을 이미지
  • m : 찾을 갯수


2.13 유사한 이미지 4개를 그리는 함수

1
2
3
4
5
6
7
8
9
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()
  • 유사한 이미지를 찾을 번호를 입력하면 비슷한 이미지 4개를 출력해준다


2.14 유사한 이미지 찾기

1
plotImages(10)

  • 10번 이미지와 비슷한 사진을 찾아봤음


1
plotImages(11)

  • 11번 이미지와 비슷한 사진을 찾았고, 문서 이미지는 잘 찾는듯 함


1
plotImages(32)

  • 32번 이미지와 비슷한 사진을 찾았고, 건물도 잘찾음


3. 요약


3.1 요약

  • 이미지를 처리하는 알고리즘을 사용하여 유사 이미지 검색을 해보았는데 생각보다 잘 나와서 신기했다.
  • 또한 이미지에 대한 라벨을 넣고 그 라벨을 맞추는 것도 83%라고 하니 낮은 수준은 아닌듯 하다
  • 하지만 이미지는 딥러닝 부분이 더 강력한것으로 알고 있으니, 나중에 딥러닝도 해보는것이 좋을듯 하다
  • 유사 이미지라는게 사실 추천 시스템과도 맥락을 같이 한다.
This post is licensed under CC BY 4.0 by the author.

Good Books 데이터로 해보는 추천 시스템(Recommendations)

딥러닝 기초 (1) (Basic of Deeplearning 1)

Comments powered by Disqus.