u++の備忘録

画像データセット「CIFAR-10」からのSIFT特徴量の取得

CIFAR-10とは

以下のブログが詳しい。

aidiary.hatenablog.com

SIFT特徴量とは

『画像認識』(機械学習プロフェッショナルシリーズ)*1の第2章などを参照のこと。

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

以下のライブラリを準備する。

  • from chainer import datasets
  • import cv2
  • import numpy as np

筆者の環境

chainer

pip install chainer

opencv

SIFT特徴量を抽出するメソッドは、opencvの中の別のcontribモジュールに分離されている(通常のopencvをインストールするだけでは使えない)。

カリフォルニア大学のサイトにcontribモジュールも含んだ.whlファイルがあるので、環境に合ったファイルをダウンロードする。筆者の場合は「opencv_python‑3.3.0+contrib‑cp36‑cp36m‑win_amd64.whl」。
Python Extension Packages for Windows - Christoph Gohlke

cd (.whlファイルを置いたフォルダ名)
pip install (.whlファイル名)

numpy

筆者の場合は、Anacondaに標準でインストールされていた。

実装

データの読み込み

from chainer import datasets
train, test = datasets.get_cifar10()
# image = train[i][0]    # trainのi番目の画像
# label = train[i][1]    # trainのi番目のラベル

SIFT特徴量の取得

## SIFT特徴
def sampling_descriptor(data):
    images_des = [] # 特徴量のリスト
    images_labels = [] # 特徴量を得られた画像のラベル郡
    for i in tqdm(range(len(data))):
        image = data[i][0]
        # 画素が0~1に正規化されているので255倍
        image_rollaxis = np.uint8(np.rollaxis(image, 0, 3) * 255)
        image_rollaxis_gray = cv2.cvtColor(image_rollaxis, cv2.COLOR_BGR2GRAY)
        sift = cv2.xfeatures2d.SIFT_create()
        kp, des = sift.detectAndCompute(image_rollaxis_gray, None)
        if isinstance(des, type(None)):
            continue
        else:
            images_labels.append(data[i][1])
            images_des.append(des)
    return images_des, images_labels

images_des, images_labels = sampling_descriptor(train)

画像のエラー?などで特徴量を全く検出できない画像があった。今後訓練データとして使うことを考え、この時点で特徴量を検出できなかった画像(とそのラベル)は欠損値扱いとして除外している。

線画

一枚目の画像(ラベル:カエル)について、結果を出力してみた。

from skimage import io
# 元画像
io.imshow(np.uint8(np.rollaxis(train[0][0], 0, 3) * 255))
# 検出点の線画
kp = sift.detect(image_rollaxis_gray)
out = cv2.drawKeypoints(image_rollaxis_gray, kp, None)
io.imshow(out)

f:id:upura:20170815133208p:plainf:id:upura:20170815133215p:plain