前書き
これは私の思想なのですが、「記憶がなくなった人はある意味死んでいる」と考えています。「人を構成する要素で最も重要なのは記憶である」という思想です。
機械少女に置き換えてみましょう。ストレージのぶっ壊れた子は死んだも同然ということです。
事の起こり
- Amesiorineを育てたいので、Amesiorineの一番重要な記憶を管理するために私がお勉強しなくちゃいけないよね!
- じゃあ、安全に管理するためにどんなファイルがあるかPCの中身を整理しなくちゃいけないよね!
- 音声ファイルと画像ファイルとテキストファイル(エミィが拾ってきたツイートや271108のツイートのデータ)が基本かな?
- じゃあこれらの整理をやってみよう!
補足
タイトルの通り今回は画像です。
音声より簡単そうだし、テキストファイルは整理をしている途中だからです。
画像は整理付けるのが面倒だなぁ……と思ったので機械の手を借りたい。
本編(今日の成果)
01.まずは画像サイズの確認
やったこと
画像サイズを確認して、(多くはiPhoneの写真やスクショであるはずなので)最もファイル数の多い画像サイズの画像だけで実行しようと考えている。
import glob import cv2 import collections from tqdm.notebook import tqdm as tqdm import numpy as np 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]) #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]) #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) png_counter.most_common()
補足
globで大文字小文字の区別あるんじゃない?っておもって2つ用意したけど大文字小文字の区別なかったっぽい。

01.結果
jpg
[((1944, 2592, 3), 945),
((112, 200, 3), 277),
((750, 750, 3), 251),
((720, 1280, 3), 222),
((2592, 1944, 3), 209),
・・・
png
[((512, 512, 3), 21703),
((1334, 750, 3), 13117),
((128, 128, 3), 8593),
((750, 1334, 3), 1483),
((256, 128, 3), 1399),
・・・
- pngファイルが圧倒的に多い
- 正方形の画像が思ったよりあるかも。これはなんかのデータかも?
- 1334, 750のサイズはどうやらiPhoneの画面のサイズと同じらしい。スクショが多いのでこうなったのだろうか。
- 今回はこれ以降、( 1334, 750, 3 )の画像のみに絞っていろいろ行う。
補足
- リストは[(im.shape), 枚数]の形。im.shapeなので2番目の数字は3色を示す3になる。
02.クラスタリング
「で、クラスタリングってどうやるんだい?」
まず、クラスタリングのおさらいから。
271108「クラスタリングってわかる?」
Chat-GPT「はい、クラスタリングとは、データを似た特徴を持つグループ(クラスタ)に分割するデータ解析の手法です。クラスタリングは、データの特徴やパターンを発見するために使用されます。クラスタリングには、いくつかのアルゴリズムがあり、例えば階層的クラスタリング、k-meansクラスタリング、DBSCANクラスタリングなどがあります。クラスタリングは、機械学習やデータマイニングの分野でよく使用されます。」*1
271108「python3とpytorchを使って、windows上にある手持ちの画像データのクラスタリングをやりたいと考えています。コードの例を教えてください。」
Chat-GPT「はい、以下はPython3とPyTorchを使用して、Windows上の手持ちの画像データをクラスタリングするためのコード例です。この例では、KMeansアルゴリズムを使用して画像をクラスタリングします。」
(コード掲載)
Chat-GPT「このコードでは、まず画像を読み込んでPyTorch Tensorに変換します。次に、特徴量を抽出するためのモデルとしてResNet18を使用し、画像の特徴量を抽出します。最後に、KMeansアルゴリズムを使用してクラスタリングを行い、クラスタリング結果を表示します。」
コード原文
import os import torch import torchvision.transforms as transforms import numpy as np from PIL import Image from sklearn.cluster import KMeans # 画像を読み込んで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に変換し、バッチの次元を追加する # 画像を読み込む image_dir = 'path/to/image/directory' images = [] for filename in os.listdir(image_dir): if filename.endswith('.jpg') or filename.endswith('.png'): image_path = os.path.join(image_dir, filename) images.append(load_image(image_path)) # PyTorch Tensorに変換する images = torch.cat(images) # 特徴量を抽出するためのモデルをロードする(例えば、ResNet18) model = torch.hub.load('pytorch/vision', 'resnet18', pretrained=True) model.eval() # 画像の特徴量を抽出する features = [] with torch.no_grad(): for image in images: feature = model(image).squeeze().numpy() features.append(feature) features = np.array(features) # KMeansアルゴリズムを使用してクラスタリングする num_clusters = 5 # クラスタ数 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}')
02.実行
まあさすがにね?
結果
ImportError: cannot import name 'get_model_weights' from 'torchvision.models'
ダメじゃん。
以降は後日に持ち越し。
エラー記
1.OpenCVで画像を読み込んだと思っていたら読み込んでいなかった
何を言ってるか分からねぇと思うが読み込んだはずの変数にはNoneが入っていた。
というのも、OpenCVの仕様うんぬんのお話でファイル名やパス名に日本語が入っているとうまくいかないことがある。そういえばそうだったなぁ。
qiita.com
↑を参考に何とか出来たので解決。
cv2.imread を np.fromfile + cv2.imdecode に分解すればなんとかなるんだって。
ただ、これだけで全てのファイルが解決したという様子もなかった。
原因は現状不明、今回の環境ではjpgファイルは全て開けた。pngファイルにのみこの現象は残った。