画像の整理をしよう(2)
これの続きです
Chat-GPTくんに言われたコードが違っていたのでそこを微修正しました。
クラスタリングの結果が文字で言われても私には何のことか分からないのでChat-GPTにサムネ付きで分かりやすく提示してね!って命令を出しました。
メモリ足らないってさ
DefaultCPUAllocator: not enough memory: you tried to allocate 12006000 bytes.
まあ、そんな気はしてた。
最終的なコード
import collections import cv2 import glob import numpy as np import os import pickle import random import torch import torchvision.transforms as transforms from PIL import Image from sklearn.cluster import KMeans from torchvision.models import resnet18 from tqdm.notebook import tqdm as tqdm def imread(filename, flags=cv2.IMREAD_COLOR, dtype=np.uint8): try: n = np.fromfile(filename, dtype) img = cv2.imdecode(n, flags) return img except Exception as e: print(e) return None jpg = [] Error = [] for f in tqdm(glob.glob("./**/*.jpg", recursive=True)): try: im = imread(f) jpg.append(im.shape) except Exception as e: Error.append([f,e]) jpg_counter = collections.Counter(jpg) png = [] for f in tqdm(glob.glob("./**/*.png", recursive=True)): try: im = imread(f) png.append(im.shape) except Exception as e: Error.append([f,e]) png_counter = collections.Counter(png) data = {} Error = [] shape = (1334, 750, 3) l = [] for f in tqdm(glob.glob("./**/*.jpg", recursive=True)): im = imread(f) if type(im) != type(None): if im.shape == (1334, 750, 3): l.append(f) data["jpg"] = l l = [] for f in tqdm(glob.glob("./**/*.png", recursive=True)): im = imread(f) if type(im) != type(None): if im.shape == (1334, 750, 3): l.append(f) data["png"] = l # 画像を読み込んでPyTorch Tensorに変換する関数 def load_image(image_path): image = Image.open(image_path).convert('RGB') transform = transforms.Compose([ # transforms.Resize((224, 224)), # 画像サイズを変更する transforms.ToTensor() # PyTorch Tensorに変換する ]) return transform(image).unsqueeze(0) # 画像を3次元Tensorに変換し、バッチの次元を追加する device = 'cuda' # 画像を読み込む images = [] for file in tqdm(data["jpg"]): images.append(load_image(file)) from sklearn.model_selection import train_test_split train_rate = 0.3 test_rate = 0.7 MainPngData, UndecidedData = train_test_split(data["png"], train_size=train_rate) for file in tqdm(MainPngData): images.append(load_image(file)) # PyTorch Tensorに変換する images = torch.cat(images) # 特徴量を抽出するためのモデルをロードする(例えば、ResNet18) model = resnet18() model.eval() # 画像の特徴量を抽出する features = [] with torch.no_grad(): for image in tqdm(images): feature = model(image.unsqueeze(0)).squeeze().numpy() features.append(feature) features = np.array(features) # KMeansアルゴリズムを使用してクラスタリングする num_clusters = 10 # クラスタ数 kmeans = KMeans(n_clusters=num_clusters) kmeans.fit(features) # クラスタリング結果を表示する for i in range(num_clusters): cluster_idx = np.where(kmeans.labels_ == i)[0] print(f'Cluster {i}: {cluster_idx}') import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import ImageGrid # クラスタごとに画像のインデックスを分割する cluster_indices = [[] for _ in range(num_clusters)] for i, label in enumerate(kmeans.labels_): cluster_indices[label].append(i) # 各クラスタに属する画像のサムネイルを表示する fig = plt.figure(figsize=(10, 10)) grid = ImageGrid(fig, 111, nrows_ncols=(num_clusters, len(cluster_indices[0][:num_clusters])), axes_pad=0.1) for i in range(num_clusters): for j, idx in enumerate(cluster_indices[i][:num_clusters]): ax = grid[(i*len(cluster_indices[i][:num_clusters]))+j] ax.imshow(images[idx].permute(1, 2, 0).numpy()) ax.set_title(f'Cluster {i}') ax.axis('off') plt.show()
結果
黒ウィズの画像ばかりではないか……
スクショのサイズだしまあそうっちゃそうだよな……
全体的に色を重視している傾向がありそう。
メモ
- K-meansだけじゃなくてWard法でもやってみればよかったかもしれない
↑なんかバージョンのせいかわかんなかったけど読み込めなかった
- 別の方法を試したほうがいいかも……
参考
ValueError: expected 4D input (got 3D input)
ValueError: expected 4D input (got 3D input) - PyTorch Forums
↑このモデルでは(Batch x Channel x Height x Width)の4次元で入力を受け付けてるので3次元で入力しても無駄だぜ!というエラーを貰った。