Image 特徴点 Clustering

Image feature Clustering

画像分類器のトレーニング方法について、特に Bag of Words (BoW) モデルとサポートベクターマシン (SVM) を用いた方法を詳しく説明します。以下に、コードを通して各ステップを詳細に解説します。

ステップ1: データセットの準備

まず、各画像の特徴点を抽出し、その特徴量をリストに格納します。また、画像のクラスラベルも準備します。


import os
import cv2
import numpy as np

def extract_sift_features(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    sift = cv2.SIFT_create()
    keypoints, descriptors = sift.detectAndCompute(image, None)
    return descriptors

data_dir = 'path_to_your_dataset'
classes = os.listdir(data_dir)
descriptors_list = []
image_paths = []
labels = []

for label, class_name in enumerate(classes):
    class_dir = os.path.join(data_dir, class_name)
    for image_name in os.listdir(class_dir):
        image_path = os.path.join(class_dir, image_name)
        descriptors = extract_sift_features(image_path)
        if descriptors is not None:
            descriptors_list.append(descriptors)
            image_paths.append(image_path)
            labels.append(label)

ステップ2: Bag of Words モデルの構築

SIFT特徴点を全て集約し、K-meansクラスタリングを使用してボキャブラリを作成します。各画像の特徴点を BoW ヒストグラムに変換します。


from sklearn.cluster import MiniBatchKMeans

num_clusters = 50  # ボキャブラリサイズを設定
all_descriptors = np.vstack(descriptors_list)
kmeans = MiniBatchKMeans(n_clusters=num_clusters, random_state=0).fit(all_descriptors)

def build_bow_histogram(descriptors, kmeans):
    histogram = np.zeros(num_clusters)
    if descriptors is not None:
        clusters = kmeans.predict(descriptors)
        for c in clusters:
            histogram[c] += 1
    return histogram

histograms = []
for descriptors in descriptors_list:
    histogram = build_bow_histogram(descriptors, kmeans)
    histograms.append(histogram)

ステップ3: SVMのトレーニング

BoW ヒストグラムを特徴量として、サポートベクターマシン (SVM) をトレーニングします。


from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline

X = np.array(histograms)
y = np.array(labels)
scaler = StandardScaler()
svm = SVC(kernel='linear', C=1.0, random_state=0)

model = make_pipeline(scaler, svm)
model.fit(X, y)

ステップ4: テストデータの分類

テスト画像に対して同じ特徴量抽出と BoW ヒストグラムの生成を行い、トレーニングしたSVMを使ってクラスを予測します。


def classify_image(image_path, kmeans, model):
    descriptors = extract_sift_features(image_path)
    histogram = build_bow_histogram(descriptors, kmeans)
    histogram = histogram.reshape(1, -1)
    prediction = model.predict(histogram)
    return prediction

# 結果の出力(例として最初の数画像を分類)
for i, image_path in enumerate(image_paths[:10]):
    prediction = classify_image(image_path, kmeans, model)
    true_label = labels[i]
    print(f"Image: {image_path}, Predicted Class: {classes[prediction[0]]}, True Class: {classes[true_label]}")

ステップ5: 分類結果の評価

全体の分類結果を評価し、分類レポートを出力します。


from sklearn.metrics import classification_report

y_pred = model.predict(X)
print(classification_report(y, y_pred, target_names=classes))

コード全体の統合

python
import os
import cv2
import numpy as np
from sklearn.cluster import MiniBatchKMeans
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline
from sklearn.metrics import classification_report

# 特徴点の抽出関数
def extract_sift_features(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    sift = cv2.SIFT_create()
    keypoints, descriptors = sift.detectAndCompute(image, None)
    return descriptors

# データセットの準備
data_dir = 'path_to_your_dataset'
classes = os.listdir(data_dir)
descriptors_list = []
image_paths = []
labels = []

for label, class_name in enumerate(classes):
    class_dir = os.path.join(data_dir, class_name)
    for image_name in os.listdir(class_dir):
        image_path = os.path.join(class_dir, image_name)
        descriptors = extract_sift_features(image_path)
        if descriptors is not None:
            descriptors_list.append(descriptors)
            image_paths.append(image_path)
            labels.append(label)

# Bag of Words モデルの構築
num_clusters = 50
all_descriptors = np.vstack(descriptors_list)
kmeans = MiniBatchKMeans(n_clusters=num_clusters, random_state=0).fit(all_descriptors)

def build_bow_histogram(descriptors, kmeans):
    histogram = np.zeros(num_clusters)
    if descriptors is not None:
        clusters = kmeans.predict(descriptors)
        for c in clusters:
            histogram[c] += 1
    return histogram

histograms = []
for descriptors in descriptors_list:
    histogram = build_bow_histogram(descriptors, kmeans)
    histograms.append(histogram)

# SVMのトレーニング
X = np.array(histograms)
y = np.array(labels)
scaler = StandardScaler()
svm = SVC(kernel='linear', C=1.0, random_state=0)

model = make_pipeline(scaler, svm)
model.fit(X, y)

# テストデータの分類
def classify_image(image_path, kmeans, model):
    descriptors = extract_sift_features(image_path)
    histogram = build_bow_histogram(descriptors, kmeans)
    histogram = histogram.reshape(1, -1)
    prediction = model.predict(histogram)
    return prediction

# 結果の出力
for i, image_path in enumerate(image_paths[:10]):
    prediction = classify_image(image_path, kmeans, model)
    true_label = labels[i]
    print(f"Image: {image_path}, Predicted Class: {classes[prediction[0]]}, True Class: {classes[true_label]}")

# 分類結果の評価
y_pred = model.predict(X)
print(classification_report(y, y_pred, target_names=classes))

説明

  1. 特徴点の抽出: extract_sift_features 関数で各画像からSIFT特徴点を抽出。

  2. データセットの準備: データセットディレクトリから画像を読み込み、特徴点を抽出し、リストに格納。

  3. BoWモデルの構築: MiniBatchKMeans を使用して特徴点のボキャブラリを作成し、各画像の特徴点をBoWヒストグラムに変換。

  4. SVMのトレーニング: BoWヒストグラムを特徴量として、サポートベクターマシンをトレーニング。

  5. テストデータの分類: テスト画像に対して同じ特徴量抽出とBoWヒストグラム生成を行い、トレーニングしたSVMでクラスを予測。

  6. 分類結果の評価: 全体の分類結果を評価し、分類レポートを出力。

この方法を使うと、複数の画像から抽出した特徴点を元に画像分類を行うことができます。データセットの準備やボキャブラリのサイズ、分類器のパラメータなどは具体的なタスクに応じて調整することが重要です。

この記事が気に入ったらサポートをしてみませんか?