Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

画像クラスタリングのコードを書いてる際のエラーを助けていただきたいです。

解決したいこと

現在顕微鏡画像をクラスタリングするようなソースコードを書いています。
その際に発生したエラー(UnboundLocalError)の解決方法をご教授いただきたいです。

使用環境は
jupyetr notebook
python
になっています。
他に必要な情報があれば追記いたします。
よろしくお願いいたします。

この方の記事を参考にさせていただいております。
https://noleff.hatenablog.com/entry/2021/02/22/004156

発生している問題・エラー

UnboundLocalError                         Traceback (most recent call last)
Cell In[1], line 122
    118     plot_scatter3d(pca_df)
    121 if __name__ == "__main__":
--> 122     main()

Cell In[1], line 100, in main()
     97 CSV_PATH = r'C:/Users/kuror/image1/microscope_pca.csv'
     99 try:
--> 100     pca_df.to_csv(CSV_PATH, index=False)
    101 except FileNotFoundError:
    102     npy_image_list = load_image(LOAD_PATH)

UnboundLocalError: cannot access local variable 'pca_df' where it is not associated with a value

該当するソースコード

import glob as gb
import shutil
import cv2
import os
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
from mpl_toolkits.mplot3d import Axes3D


# 画像の読み込み
def load_image(path):
    image_list = []
    npy_image_list = []
    image_path_list = gb.glob(f"{path}/*")  # 画像の保存先次第で変更

    for i, image in enumerate(image_path_list):
        image_path = image.replace(chr(92), '/')  # Windows特有の問題を修正
        if i % 100 == 0:
            print(i)
        
        img_npy = cv2.imread(image_path, cv2.IMREAD_COLOR)
        img_npy = cv2.cvtColor(img_npy, cv2.COLOR_BGR2RGB)
        img_npy = cv2.resize(img_npy, (64, 64))
        img_npy = img_npy.flatten()
        npy_image_list.append(img_npy / 255)

    return npy_image_list


def build_kmeans(df, cluster_num):
    kmeans = KMeans(n_clusters=cluster_num, random_state=2021)
    kmeans.fit(df)
    return kmeans


def build_pca(df):
    pca = PCA()
    pca.fit(df)
    return pca


def plot_contribution_rate(pca):
    fig = plt.figure()
    plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
    plt.plot([0] + list(np.cumsum(pca.explained_variance_ratio_)), "-o")
    plt.xlabel("Number of principal components")
    plt.ylabel("Cumulative contribution rate")
    plt.grid()
    plt.show()


def plot_scatter2d(df):
    fig = plt.figure()
    sns.scatterplot(data=df, x='PC1', y='PC2', hue='label', palette='bright', legend='full')
    plt.show()


def plot_scatter3d(df):
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.set_xlabel("PC1")
    ax.set_ylabel("PC2")
    ax.set_zlabel("PC3")

    for label in df['label'].values:
        ax.plot(df.loc[df['label'] == label, 'PC1'],
                df.loc[df['label'] == label, 'PC2'],
                df.loc[df['label'] == label, 'PC3'],
                alpha=0.8, marker=".", linestyle='None')
    plt.show()


def make_cluster_dir(load_path, save_path, kmeans):
    shutil.rmtree(save_path, ignore_errors=True)
    os.makedirs(save_path, exist_ok=True)

    for i in range(kmeans.n_clusters):
        cluster_dir = os.path.join(save_path, f"cluster{i}")
        os.makedirs(cluster_dir, exist_ok=True)

    image_path_list = gb.glob(os.path.join(load_path, '*'))
    for label, path in zip(kmeans.labels_, image_path_list):
        shutil.copyfile(path, os.path.join(save_path, f'cluster{label}', os.path.basename(path)))

    print('クラスタごとにファイル作成完了')


def main():
    LOAD_PATH = 'C:/Users/kuror/image1/microscope'
    SAVE_PATH = 'C:/Users/kuror/image1/microscope_clustering'
    CSV_PATH = r'C:/Users/kuror/image1/microscope_pca.csv'
    
    try:
        pca_df.to_csv(CSV_PATH, index=False)
    except FileNotFoundError:
        npy_image_list = load_image(LOAD_PATH)
        df = pd.DataFrame(npy_image_list)
        print(df.shape)
        
        pca = build_pca(df)
        pca_df = pd.DataFrame(pca.transform(df), columns=[f"PC{x + 1}" for x in range(len(df.columns))])
        plot_contribution_rate(pca)
        pca_df.to_csv(CSV_PATH, index=False)
    
    train_df = pca_df.iloc[:, :1200]
    cluster_num = int(input('cluster_num > '))
    kmeans = build_kmeans(train_df, cluster_num)
    make_cluster_dir(LOAD_PATH, SAVE_PATH, kmeans)

    pca_df['label'] = kmeans.labels_
    plot_scatter2d(pca_df)
    plot_scatter3d(pca_df)


if __name__ == "__main__":
    main()
0

4Answer

pca_df 変数に代入する前に変数を使っているからです。
参考サイトでは try の中で最初に pca_df = pd.read_csv(CSV_PATH) を行ってます。

1Like

元々の100行目はpca_df = pd.read_csv(CSV_PATH)でしたが、pca_df.to_csv(CSV_PATH, index=False)に変更されています。これがUnboundLocalErrorの原因だと思います。

一つ前の質問で回答済みです。

1Like

直接的な回答はshiracamusさんやnak435さんがされていますので一つアドバイスをいたします。
質問者さんはPythonの知識が不足しているようなので入門書を一読された方が良いかと思います。その方が結局は近道になると思います。

ところで他にも質問を投稿されていますが、未だ未解決でしょうか?解決されたのであれば質問のクローズ処理をしましょう。放置を続けていると新しい質問にも回答が付きずらくなるかもしれません。未だ解決されていないなら現状の追記を行うと有識者から回答が付くかもしれません。

0Like

Your answer might help someone💌