福岡人データサイエンティストの部屋

データサイエンスを極めるため、日々の学習を綴っています。

DELF使って特徴くらべてみた【図解速習Deep Learning】#008

こんにちは!こーたろーです。

今日は【図解速習DEEP LEARNING】の続きです!!

実践はどんどん続き、本日は「DELF」を使ってみます。
DELFは、画像を処理し、特徴点とそれらの特徴量記述を識別するロジックです。


説明を忘れていましたが、最近使っていた「Tensorflow Hub」は、事前に学習されたモジュール群を再利用可能なリソースとしてパッケージ化したものです。
学習を済ませているため、学習データを準備する必要がなく、今後活用例などが出てくるかもしれません。
しかし、特徴を抽出するにとどまっているので、そのあとどう処理するかというところは、開発しなければならないです。

それでは始めます。

1.ライブラリのインストール

!pip install -q 'tensorflow-hub'
!pip install -q 'scikit-image'

2.ライブラリのインポート

from absl import logging

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from PIL import Image, ImageOps
from scipy.spatial import cKDTree
from skimage.feature import plot_matches
from skimage.measure import ransac
from skimage.transform import AffineTransform
from six import BytesIO

import tensorflow as tf

import tensorflow_hub as hub
from six.moves.urllib.request import urlopen


3.比較したい2つの画像のURLを指定

IMAGE_1_URL = 'https://upload.wikimedia.org/wikipedia/commons/d/d8/Eiffel_Tower%2C_November_15%2C_2011.jpg'
IMAGE_2_URL = 'https://upload.wikimedia.org/wikipedia/commons/a/a8/Eiffel_Tower_from_immediately_beside_it%2C_Paris_May_2008.jpg'


4.画像のダウンロードを行い、resizeを行う

ダウンロードとresizeを行う関数を定義

def download_and_resize(name, url, new_width=256, new_height=256):
  path = tf.keras.utils.get_file(url.split('/')[-1], url)
  image = Image.open(path)  image = ImageOps.fit(image, (new_width, new_height), Image.ANTIALIAS)
  return image

各URLに対して、画像を取得する

image1 = download_and_resize('image_1.jpg', IMAGE_1_URL)
image2 = download_and_resize('image_2.jpg', IMAGE_2_URL)

plt.subplot(1,2,1)
plt.imshow(image1)
plt.subplot(1,2,2)
plt.imshow(image2)

f:id:dsf-kotaro:20210131234305p:plain

チュートリアルの中のこちらの画像を使用しました。

5.DELFモジュールのロード

delf = hub.load('https://tfhub.dev/google/delf/1').signatures['default']

6.各イメージにDELFを実行
DELFモジュールは、画像を入力とし、特徴点をベクトル形式で出力します。

DELFを実行するための関数を定義(前処理部分の記述)

def run_delf(image):
  np_image = np.array(image)
  float_image = tf.image.convert_image_dtype(np_image, tf.float32)

  return delf(
      image=float_image,
      score_threshold=tf.constant(100.0),
      image_scales=tf.constant([0.25, 0.3536, 0.5, 0.7071, 1.0, 1.4142, 2.0]),
      max_feature_num=tf.constant(1000))

各画像に対してDELFを実行

result1 = run_delf(image1)
result2 = run_delf(image2)


7.比較結果の描画

def match_images(image1, image2, result1, result2):
  distance_threshold = 0.8

  num_features_1 = result1['locations'].shape[0]
  print("Loaded image 1's %d features" % num_features_1)

  num_features_2 = result2['locations'].shape[0]
  print("Loaded image 2's %d features" % num_features_2)

  d1_tree = cKDTree(result1['descriptors'])
  _, indices = d1_tree.query(
      result2['descriptors'],
      distance_upper_bound=distance_threshold)

  locations_2_to_use = np.array([
      result2['locations'][i,]
      for i in range(num_features_2)
      if indices[i] != num_features_1
  ])
  locations_1_to_use = np.array([
      result1['locations'][indices[i],]
      for i in range(num_features_2)
      if indices[i] != num_features_1
  ])
  
  _, inliers = ransac(
      (locations_1_to_use, locations_2_to_use),
      AffineTransform,
      min_samples=3,
      residual_threshold=20,
      max_trials=1000)

  print('Found %d inliers' % sum(inliers))

  _, ax = plt.subplots()
  inlier_idxs = np.nonzero(inliers)[0]
  plot_matches(
      ax,
      image1,
      image2,
      locations_1_to_use,
      locations_2_to_use,
      np.column_stack((inlier_idxs, inlier_idxs)),
      matches_color='b')
  ax.axis('off')
  ax.set_title('DELF correspondences')
match_images(image1, image2, result1, result2)

f:id:dsf-kotaro:20210131234415p:plain

他のはこんな感じになりました。

f:id:dsf-kotaro:20210131234527p:plain
f:id:dsf-kotaro:20210131234612p:plain
f:id:dsf-kotaro:20210131234658p:plain
f:id:dsf-kotaro:20210131234732p:plain

どんどん難しくなっている気がしますね。。
Tensorflow極めないと。。。そして、メソッドも覚えないと。。。
勉強することはかなりありそうですね。

ではでは。。