公司网站开发可行性报告南宁网页设计价格
公司网站开发可行性报告,南宁网页设计价格,网站集约化建设难点,9377传奇世界MusePublic圣光艺苑实战教程#xff1a;基于CLIP特征相似度的风格聚类分析
1. 引言#xff1a;从艺术直觉到数据洞察
当你沉浸在MusePublic圣光艺苑的创作中#xff0c;看着一幅幅融合了文艺复兴与梵高笔触的作品诞生时#xff0c;有没有想过一个问题#xff1a;这些作品…MusePublic圣光艺苑实战教程基于CLIP特征相似度的风格聚类分析1. 引言从艺术直觉到数据洞察当你沉浸在MusePublic圣光艺苑的创作中看着一幅幅融合了文艺复兴与梵高笔触的作品诞生时有没有想过一个问题这些作品之间到底有什么内在联系传统的艺术分析依赖人的直觉和专业知识但今天我们可以用技术来“看见”那些肉眼难以察觉的风格关联。这就是风格聚类分析的价值所在——它像一台艺术X光机能透视作品背后的风格DNA。本教程将带你完成一次完整的艺术风格探索之旅学习目标掌握如何用CLIP模型提取图像特征并通过聚类算法发现MusePublic作品的风格规律前置知识只需要基础的Python编程经验不需要深度学习专业知识教程价值你将学会一套可复用的分析方法不仅能分析圣光艺苑的作品还能应用到任何AI生成的艺术品分析中想象一下当你生成了一百幅作品后能够自动将它们按风格分组找出你最擅长的创作方向或者发现那些意想不到的风格组合。这就是数据驱动的艺术创作。2. 环境准备搭建你的艺术分析实验室2.1 系统要求与依赖安装开始之前确保你的环境满足以下要求Python 3.8推荐使用Python 3.9或3.10显存要求至少8GB用于CLIP模型加载和特征提取磁盘空间预留5-10GB用于模型和数据集存储安装必要的依赖包# 创建虚拟环境可选但推荐 python -m venv art_analysis_env source art_analysis_env/bin/activate # Linux/Mac # 或 art_analysis_env\Scripts\activate # Windows # 安装核心依赖 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install transformers pillow scikit-learn matplotlib seaborn pandas numpy pip install opencv-python tqdm为什么选择这些库torch和transformers用于加载和运行CLIP模型scikit-learn提供各种聚类算法和评估工具matplotlib和seaborn数据可视化让结果一目了然opencv-python图像预处理和读取2.2 准备你的艺术作品集分析的第一步是收集作品。假设你已经用MusePublic圣光艺苑生成了一批作品存放在本地文件夹中import os from pathlib import Path # 设置作品文件夹路径 artworks_dir Path(./muse_artworks) # 支持的图片格式 supported_formats [.jpg, .jpeg, .png, .bmp, .webp] # 检查文件夹并列出所有作品 if not artworks_dir.exists(): print(f错误文件夹 {artworks_dir} 不存在) # 创建示例文件夹结构 artworks_dir.mkdir(parentsTrue, exist_okTrue) print(已创建示例文件夹请将你的作品放入其中) else: # 获取所有图片文件 image_files [] for ext in supported_formats: image_files.extend(artworks_dir.glob(f*{ext})) image_files.extend(artworks_dir.glob(f*{ext.upper()})) print(f找到 {len(image_files)} 张作品) for i, img_path in enumerate(image_files[:5]): # 显示前5个 print(f {i1}. {img_path.name})文件命名建议为了后续分析更方便建议在生成作品时使用有意义的命名比如van_gogh_starry_city_001.jpgrenaissance_portrait_golden_002.pngmixed_style_landscape_003.webp这样在分析结果中你一眼就能看出每组的风格特点。3. 核心概念CLIP模型如何“看懂”艺术在开始写代码之前我们先花几分钟理解CLIP模型的工作原理。不用担心我会用最直白的方式解释。3.1 CLIP是什么为什么选它CLIPContrastive Language-Image Pre-training是OpenAI开发的一个多模态模型它的核心思想很简单让模型学会把图片和描述它的文字联系起来。想象一下教小孩认图你给他看一张猫的图片说这是猫给他看一张狗的图片说这是狗反复多次后他就能把猫这个词和猫的图片联系起来CLIP的训练过程类似但它看了4亿个图片-文字对所以它学会了非常丰富的视觉概念。为什么CLIP适合艺术风格分析理解高级语义不仅能识别物体还能理解梵高风格、文艺复兴这样的抽象概念特征提取能力强把图片转换成512维的向量相似风格的图片向量距离近无需标签我们不需要事先给作品打标签模型自己能从图片中学习特征3.2 特征向量艺术的数字指纹CLIP把每张图片转换成一个512维的向量可以理解为一串512个数字。这个向量就是图片的数字指纹# 简单示例理解特征向量 import numpy as np # 假设这是三张图片的CLIP特征向量简化版实际是512维 van_gogh_vector [0.12, 0.45, -0.23, 0.67, ...] # 512个数字 renaissance_vector [0.15, 0.42, -0.20, 0.65, ...] modern_vector [0.85, -0.12, 0.34, -0.45, ...] # 计算向量之间的距离欧氏距离 def calculate_distance(vec1, vec2): return np.sqrt(np.sum((np.array(vec1) - np.array(vec2)) ** 2)) # 梵高和文艺复兴风格更接近 distance1 calculate_distance(van_gogh_vector, renaissance_vector) # 较小 # 梵高和现代风格差异较大 distance2 calculate_distance(van_gogh_vector, modern_vector) # 较大 print(f风格相似度梵高 vs 文艺复兴 {distance1:.3f}) print(f风格相似度梵高 vs 现代 {distance2:.3f})关键理解在特征空间中风格相似的图片会聚集在一起风格不同的图片会离得远。我们的任务就是找到这些自然的聚集点。4. 实战步骤从图片到聚类结果现在进入最核心的部分——完整的代码实现。我会一步步带你完成每个步骤都有详细解释。4.1 加载CLIP模型并提取特征首先我们需要加载CLIP模型并用它处理所有作品import torch from PIL import Image from transformers import CLIPProcessor, CLIPModel import numpy as np from tqdm import tqdm class ArtFeatureExtractor: def __init__(self, model_nameopenai/clip-vit-base-patch32): 初始化CLIP特征提取器 参数 model_name: CLIP模型名称这里用基础版平衡速度和精度 print(f正在加载CLIP模型: {model_name}) self.device cuda if torch.cuda.is_available() else cpu print(f使用设备: {self.device}) # 加载模型和处理器 self.model CLIPModel.from_pretrained(model_name).to(self.device) self.processor CLIPProcessor.from_pretrained(model_name) # 确保模型在评估模式 self.model.eval() print(模型加载完成) def extract_features(self, image_paths, batch_size8): 批量提取图片特征 参数 image_paths: 图片路径列表 batch_size: 批处理大小根据显存调整 返回 features: 特征向量数组 (n_images, 512) valid_paths: 成功处理的图片路径 all_features [] valid_paths [] print(f开始处理 {len(image_paths)} 张图片...) # 分批处理 for i in tqdm(range(0, len(image_paths), batch_size)): batch_paths image_paths[i:i batch_size] batch_images [] batch_valid_paths [] # 加载图片 for img_path in batch_paths: try: image Image.open(img_path).convert(RGB) batch_images.append(image) batch_valid_paths.append(img_path) except Exception as e: print(f无法加载图片 {img_path}: {e}) continue if not batch_images: continue # 预处理并提取特征 try: with torch.no_grad(): # 不计算梯度加快推理 inputs self.processor( imagesbatch_images, return_tensorspt ).to(self.device) # 获取图像特征 image_features self.model.get_image_features(**inputs) # 归一化特征向量重要 image_features image_features / image_features.norm(dim-1, keepdimTrue) # 转移到CPU并转换为numpy all_features.append(image_features.cpu().numpy()) valid_paths.extend(batch_valid_paths) except RuntimeError as e: if out of memory in str(e): print(显存不足尝试减小batch_size) # 清理缓存 torch.cuda.empty_cache() # 尝试更小的batch if batch_size 1: return self.extract_features(image_paths, batch_sizebatch_size//2) else: print(f处理批处理时出错: {e}) # 合并所有特征 if all_features: features np.vstack(all_features) print(f特征提取完成形状: {features.shape}) return features, valid_paths else: print(没有成功提取任何特征) return None, [] # 使用示例 if __name__ __main__: # 初始化提取器 extractor ArtFeatureExtractor() # 获取图片路径假设有100张作品 image_files list(artworks_dir.glob(*.jpg)) list(artworks_dir.glob(*.png)) image_paths [str(p) for p in image_files[:100]] # 先处理前100张 # 提取特征 features, valid_paths extractor.extract_features(image_paths) # 保存特征供后续使用 if features is not None: np.save(artwork_features.npy, features) with open(artwork_paths.txt, w) as f: for path in valid_paths: f.write(path \n) print(特征已保存到 artwork_features.npy 和 artwork_paths.txt)代码要点解释批处理一次处理多张图片提高效率错误处理处理损坏的图片文件特征归一化确保所有特征向量长度相同便于后续计算距离显存管理自动检测显存不足并调整批大小4.2 可视化特征看看作品在空间中的分布在聚类之前我们先看看特征在空间中的分布。由于特征是512维的我们需要先降维到2D或3D才能可视化import matplotlib.pyplot as plt from sklearn.manifold import TSNE from sklearn.decomposition import PCA import seaborn as sns def visualize_features(features, image_paths, n_samples100): 可视化特征分布 参数 features: 特征矩阵 image_paths: 图片路径列表 n_samples: 可视化样本数太多会拥挤 # 如果样本太多随机抽样 if len(features) n_samples: indices np.random.choice(len(features), n_samples, replaceFalse) sample_features features[indices] sample_paths [image_paths[i] for i in indices] else: sample_features features sample_paths image_paths print(f可视化 {len(sample_features)} 个样本...) # 方法1使用PCA降维速度快 print(使用PCA降维...) pca PCA(n_components2) features_2d_pca pca.fit_transform(sample_features) # 方法2使用t-SNE降维保持局部结构更好但速度慢 print(使用t-SNE降维可能需要几分钟...) tsne TSNE(n_components2, random_state42, perplexity30) features_2d_tsne tsne.fit_transform(sample_features) # 创建可视化 fig, axes plt.subplots(1, 2, figsize(16, 6)) # PCA结果 axes[0].scatter(features_2d_pca[:, 0], features_2d_pca[:, 1], alpha0.6, s30) axes[0].set_title(PCA降维可视化, fontsize14) axes[0].set_xlabel(主成分1) axes[0].set_ylabel(主成分2) axes[0].grid(True, alpha0.3) # t-SNE结果 scatter axes[1].scatter(features_2d_tsne[:, 0], features_2d_tsne[:, 1], alpha0.6, s30) axes[1].set_title(t-SNE降维可视化, fontsize14) axes[1].set_xlabel(t-SNE维度1) axes[1].set_ylabel(t-SNE维度2) axes[1].grid(True, alpha0.3) # 添加一些样本标签前5个 for i in range(min(5, len(sample_features))): # 从路径提取文件名不含扩展名 label Path(sample_paths[i]).stem[:15] # 只取前15个字符 axes[0].annotate(f{i1}, (features_2d_pca[i, 0], features_2d_pca[i, 1]), fontsize9) axes[1].annotate(f{i1}, (features_2d_tsne[i, 0], features_2d_tsne[i, 1]), fontsize9) plt.tight_layout() plt.savefig(feature_visualization.png, dpi150, bbox_inchestight) plt.show() # 解释可视化结果 print(\n 可视化解读) print(1. 每个点代表一幅作品) print(2. 距离越近的点风格越相似) print(3. 明显的聚集点可能代表不同的风格簇) print(4. 散落的点可能是独特或混合风格的作品) return features_2d_pca, features_2d_tsne # 使用示例 if features is not None: pca_result, tsne_result visualize_features(features, valid_paths)你会看到什么如果作品有明显的风格分组你会看到几个明显的聚集点混合风格的作品可能位于不同聚集点之间独特风格的作品可能远离所有聚集点4.3 聚类分析发现隐藏的风格分组现在是核心步骤——聚类。我们会尝试几种不同的聚类算法看看哪种最适合你的作品集from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering from sklearn.metrics import silhouette_score, calinski_harabasz_score import warnings warnings.filterwarnings(ignore) class ArtStyleCluster: def __init__(self, features): 初始化聚类分析器 参数 features: 特征矩阵 self.features features self.n_samples features.shape[0] def find_optimal_clusters(self, max_clusters10): 寻找最佳聚类数量 参数 max_clusters: 尝试的最大聚类数 返回 optimal_k: 最佳聚类数 scores: 各种评估指标 print(寻找最佳聚类数量...) silhouette_scores [] calinski_scores [] # 尝试不同的k值 k_values range(2, min(max_clusters, self.n_samples // 2) 1) for k in k_values: if k self.n_samples: break kmeans KMeans(n_clustersk, random_state42, n_init10) cluster_labels kmeans.fit_predict(self.features) # 计算评估指标 if len(np.unique(cluster_labels)) 1: sil_score silhouette_score(self.features, cluster_labels) cal_score calinski_harabasz_score(self.features, cluster_labels) else: sil_score 0 cal_score 0 silhouette_scores.append(sil_score) calinski_scores.append(cal_score) print(f k{k}: 轮廓系数{sil_score:.3f}, Calinski指数{cal_score:.3f}) # 找到最佳k轮廓系数最高 if silhouette_scores: optimal_k k_values[np.argmax(silhouette_scores)] print(f\n 推荐聚类数量: {optimal_k}) else: optimal_k 3 # 默认值 print(f\n 无法确定最佳k使用默认值: {optimal_k}) # 可视化评估指标 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(k_values[:len(silhouette_scores)], silhouette_scores, bo-) axes[0].set_xlabel(聚类数量 (k)) axes[0].set_ylabel(轮廓系数) axes[0].set_title(轮廓系数 vs 聚类数量) axes[0].grid(True, alpha0.3) axes[1].plot(k_values[:len(calinski_scores)], calinski_scores, ro-) axes[1].set_xlabel(聚类数量 (k)) axes[1].set_ylabel(Calinski-Harabasz指数) axes[1].set_title(Calinski指数 vs 聚类数量) axes[1].grid(True, alpha0.3) plt.tight_layout() plt.savefig(optimal_clusters.png, dpi150, bbox_inchestight) plt.show() return optimal_k def cluster_analysis(self, n_clustersNone, methodkmeans): 执行聚类分析 参数 n_clusters: 聚类数量如果为None则自动确定 method: 聚类方法 (kmeans, dbscan, agglomerative) 返回 labels: 每个样本的聚类标签 model: 聚类模型 if n_clusters is None: n_clusters self.find_optimal_clusters() print(f\n使用 {method} 进行聚类k{n_clusters}...) if method kmeans: model KMeans(n_clustersn_clusters, random_state42, n_init10) elif method agglomerative: model AgglomerativeClustering(n_clustersn_clusters) elif method dbscan: # DBSCAN不需要指定聚类数量 model DBSCAN(eps0.5, min_samples5) else: raise ValueError(f不支持的聚类方法: {method}) labels model.fit_predict(self.features) # 统计聚类结果 unique_labels, counts np.unique(labels, return_countsTrue) print(\n 聚类结果统计:) for label, count in zip(unique_labels, counts): if label -1: # DBSCAN中的噪声点 print(f 噪声点: {count} 个样本 ({count/len(labels)*100:.1f}%)) else: print(f 聚类 {label}: {count} 个样本 ({count/len(labels)*100:.1f}%)) # 计算聚类质量 if len(unique_labels) 1 and -1 not in unique_labels: sil_score silhouette_score(self.features, labels) print(f 轮廓系数: {sil_score:.3f} (越接近1越好)) return labels, model # 使用示例 if features is not None: cluster_analyzer ArtStyleCluster(features) # 自动确定最佳聚类数量 optimal_k cluster_analyzer.find_optimal_clusters() # 使用KMeans进行聚类 labels, kmeans_model cluster_analyzer.cluster_analysis( n_clustersoptimal_k, methodkmeans ) # 保存聚类结果 np.save(cluster_labels.npy, labels) print(聚类标签已保存到 cluster_labels.npy)聚类方法选择指南KMeans最常用适合球形分布的数据需要指定聚类数量DBSCAN能发现任意形状的簇自动识别噪声点但参数敏感Agglomerative层次聚类可以得到树状图适合探索不同粒度的分组4.4 结果可视化让聚类结果一目了然聚类完成后我们需要直观地看到结果def visualize_clusters(features_2d, labels, image_paths, title聚类结果可视化): 可视化聚类结果 参数 features_2d: 降维后的2D特征 labels: 聚类标签 image_paths: 图片路径列表 title: 图表标题 # 创建颜色映射 unique_labels np.unique(labels) n_clusters len(unique_labels) if -1 not in unique_labels else len(unique_labels) - 1 # 为每个聚类分配颜色 if n_clusters 10: colors plt.cm.tab10(np.linspace(0, 1, max(10, n_clusters))) else: colors plt.cm.rainbow(np.linspace(0, 1, n_clusters)) plt.figure(figsize(12, 8)) # 绘制每个聚类的点 for i, label in enumerate(unique_labels): if label -1: # 噪声点 color gray label_name 噪声 alpha 0.3 size 20 else: color colors[i if label -1 else label] label_name f聚类 {label} alpha 0.7 size 50 # 找到属于该聚类的点 mask labels label if np.any(mask): plt.scatter(features_2d[mask, 0], features_2d[mask, 1], c[color], labellabel_name, alphaalpha, ssize, edgecolorsw, linewidth0.5) # 添加一些示例图片的缩略图前几个聚类的代表性样本 for label in unique_labels[:min(5, len(unique_labels))]: if label -1: continue # 找到该聚类的第一个样本 indices np.where(labels label)[0] if len(indices) 0: sample_idx indices[0] sample_path image_paths[sample_idx] try: # 加载图片并创建缩略图 from matplotlib.offsetbox import OffsetImage, AnnotationBbox import matplotlib.image as mpimg img mpimg.imread(sample_path) # 调整图片大小 img_size 0.1 # 缩略图大小 imagebox OffsetImage(img, zoomimg_size) # 在对应位置添加缩略图 ab AnnotationBbox(imagebox, (features_2d[sample_idx, 0], features_2d[sample_idx, 1]), frameonFalse) plt.gca().add_artist(ab) except: pass # 如果无法加载图片跳过 plt.title(title, fontsize16) plt.xlabel(维度1, fontsize12) plt.ylabel(维度2, fontsize12) plt.legend(locbest) plt.grid(True, alpha0.3) # 添加统计信息 stats_text f总样本数: {len(labels)}\n聚类数: {n_clusters} plt.figtext(0.02, 0.02, stats_text, fontsize10, bboxdict(boxstyleround,pad0.3, facecolorwheat, alpha0.5)) plt.tight_layout() plt.savefig(cluster_visualization.png, dpi150, bbox_inchestight) plt.show() return n_clusters # 使用示例假设已经有降维后的特征 if features is not None and labels in locals(): # 使用t-SNE结果进行可视化 n_clusters visualize_clusters(tsne_result, labels, valid_paths, titleMusePublic作品风格聚类分析) print(f\n 发现 {n_clusters} 个主要风格聚类) print(每个聚类的代表性作品已显示在图中)4.5 深入分析理解每个聚类的风格特点知道作品被分成了几组还不够我们还需要理解每组的特点def analyze_cluster_characteristics(features, labels, image_paths, top_n3): 分析每个聚类的特征 参数 features: 特征矩阵 labels: 聚类标签 image_paths: 图片路径列表 top_n: 每个聚类显示的代表作品数量 unique_labels np.unique(labels) # 排除噪声点 unique_labels [l for l in unique_labels if l ! -1] print( * 60) print( 聚类详细分析报告) print( * 60) for cluster_id in unique_labels: # 获取该聚类的所有样本 cluster_indices np.where(labels cluster_id)[0] cluster_size len(cluster_indices) print(f\n 聚类 {cluster_id}:) print(f 作品数量: {cluster_size} ({cluster_size/len(labels)*100:.1f}%)) if cluster_size 0: # 计算聚类中心 cluster_features features[cluster_indices] cluster_center np.mean(cluster_features, axis0) # 找到最接近中心的样本代表性作品 distances np.linalg.norm(cluster_features - cluster_center, axis1) representative_indices cluster_indices[np.argsort(distances)[:top_n]] print(f 代表性作品:) for i, idx in enumerate(representative_indices): img_name Path(image_paths[idx]).stem # 尝试从文件名推断风格 if any(keyword in img_name.lower() for keyword in [van, gogh, starry]): style_hint 可能为梵高风格 elif any(keyword in img_name.lower() for keyword in [renaissance, classic]): style_hint 可能为文艺复兴风格 elif any(keyword in img_name.lower() for keyword in [mixed, fusion]): style_hint 可能为混合风格 else: style_hint print(f {i1}. {img_name[:30]}... {style_hint}) # 计算聚类紧密度平均距离 avg_distance np.mean(distances) print(f 风格一致性: {1/avg_distance:.3f} (值越大表示风格越一致)) # 分析该聚类与其他聚类的距离 if len(unique_labels) 1: other_clusters [l for l in unique_labels if l ! cluster_id] distances_to_others [] for other_id in other_clusters: other_indices np.where(labels other_id)[0] if len(other_indices) 0: other_center np.mean(features[other_indices], axis0) dist np.linalg.norm(cluster_center - other_center) distances_to_others.append((other_id, dist)) # 找到最相似的聚类 if distances_to_others: closest_cluster min(distances_to_others, keylambda x: x[1]) print(f 最相似聚类: {closest_cluster[0]} (距离: {closest_cluster[1]:.3f})) print(\n * 60) print( 分析建议:) print(1. 查看每个聚类的代表性作品总结风格特点) print(2. 风格一致性高的聚类说明该风格明确且稳定) print(3. 聚类间距离大的说明风格差异明显) print(4. 可以考虑为每个聚类命名如强烈梵高风、古典文艺复兴等) print( * 60) # 使用示例 if features is not None and labels in locals(): analyze_cluster_characteristics(features, labels, valid_paths)5. 进阶技巧提升分析效果的实用方法掌握了基础分析后这里有一些进阶技巧可以让你的分析更精准5.1 使用文本提示增强特征CLIP是图文多模态模型我们可以用文本提示来增强对特定风格的理解def enhance_with_text_prompts(features, text_prompts): 使用文本提示增强特征表示 参数 features: 图像特征 text_prompts: 文本提示列表如 [van gogh style, renaissance painting] 返回 enhanced_features: 增强后的特征 from transformers import CLIPTokenizer, CLIPTextModel # 加载文本编码器 model_name openai/clip-vit-base-patch32 tokenizer CLIPTokenizer.from_pretrained(model_name) text_model CLIPTextModel.from_pretrained(model_name) if torch.cuda.is_available(): text_model text_model.cuda() text_model.eval() # 编码文本提示 text_features_list [] for prompt in text_prompts: inputs tokenizer(prompt, return_tensorspt, paddingTrue) if torch.cuda.is_available(): inputs {k: v.cuda() for k, v in inputs.items()} with torch.no_grad(): text_outputs text_model(**inputs) text_features text_outputs.pooler_output # 归一化 text_features text_features / text_features.norm(dim-1, keepdimTrue) text_features_list.append(text_features.cpu().numpy()) # 平均所有文本特征 text_features_avg np.mean(text_features_list, axis0) # 将图像特征向文本特征方向调整可选 # 这里简单地将图像和文本特征拼接 enhanced_features np.hstack([features, np.repeat(text_features_avg, len(features), axis0)]) print(f特征增强完成: {features.shape} - {enhanced_features.shape}) return enhanced_features # 使用示例 text_prompts [ oil painting in the style of Van Gogh, renaissance classical painting, impressionist artwork, detailed digital art ] enhanced_features enhance_with_text_prompts(features, text_prompts)5.2 时间序列分析追踪风格演变如果你按时间顺序生成作品可以分析风格的演变过程def analyze_style_evolution(image_paths, labels, date_patternNone): 分析风格随时间的变化 参数 image_paths: 图片路径列表 labels: 聚类标签 date_pattern: 从文件名提取日期的正则模式 import re from datetime import datetime # 尝试从文件名提取日期 dates [] for path in image_paths: filename Path(path).stem if date_pattern: match re.search(date_pattern, filename) if match: try: date_str match.group() date_obj datetime.strptime(date_str, %Y%m%d) dates.append(date_obj) except: dates.append(None) else: # 尝试常见格式 for pattern in [r\d{8}, r\d{6}, r\d{4}-\d{2}-\d{2}]: match re.search(pattern, filename) if match: try: date_str match.group() if len(date_str) 8: # YYYYMMDD date_obj datetime.strptime(date_str, %Y%m%d) elif len(date_str) 6: # YYMMDD date_obj datetime.strptime(date_str, %y%m%d) else: date_obj datetime.strptime(date_str, %Y-%m-%d) dates.append(date_obj) break except: continue else: dates.append(None) # 如果有足够多的日期信息进行分析 valid_dates [d for d in dates if d is not None] if len(valid_dates) 10: # 至少有10个有效日期 print(f找到 {len(valid_dates)} 个有效日期进行时间序列分析) # 按时间排序 sorted_indices np.argsort(valid_dates) # 分析每个时间段的风格分布 n_periods 5 # 分成5个时间段 period_size len(sorted_indices) // n_periods fig, axes plt.subplots(1, n_periods, figsize(16, 4)) for i in range(n_periods): start_idx i * period_size end_idx (i 1) * period_size if i n_periods - 1 else len(sorted_indices) period_indices sorted_indices[start_idx:end_idx] period_labels [labels[idx] for idx in period_indices] # 统计该时间段的风格分布 unique, counts np.unique(period_labels, return_countsTrue) axes[i].pie(counts, labels[f风格{l} for l in unique], autopct%1.1f%%) date_range f{valid_dates[period_indices[0]].strftime(%m/%d)}-{valid_dates[period_indices[-1]].strftime(%m/%d)} axes[i].set_title(f时间段 {i1}\n{date_range}) plt.suptitle(风格随时间演变分析, fontsize14) plt.tight_layout() plt.savefig(style_evolution.png, dpi150, bbox_inchestight) plt.show() print(\n 时间序列分析完成) print(通过饼图可以看到不同时间段的主导风格) else: print(日期信息不足跳过时间序列分析) print(建议在保存作品时在文件名中加入日期如作品名_20240101.jpg) # 使用示例 analyze_style_evolution(valid_paths, labels)6. 总结从数据中看见艺术的规律通过本教程我们完成了一次完整的MusePublic作品风格分析之旅。让我们回顾一下关键收获6.1 核心成果总结技术掌握学会了使用CLIP模型提取图像特征这是多模态AI分析的基础技能分析方法掌握了完整的聚类分析流程从数据准备到结果解读实用工具获得了一套可复用的代码框架可以轻松应用到其他AI艺术分析中艺术洞察能够从数据角度理解作品风格发现肉眼难以察觉的规律6.2 实际应用价值这套分析方法不仅适用于MusePublic圣光艺苑还可以扩展到个人创作分析了解自己的风格偏好找到创作方向作品集管理自动分类整理大量生成的作品风格混合实验分析不同提示词产生的风格差异质量评估识别高质量作品的特征模式6.3 下一步学习建议如果你对这个领域感兴趣可以继续探索深入技术学习更高级的特征提取方法如DINOv2、BLIP等模型扩展应用尝试风格迁移分析研究如何将一种风格应用到另一幅作品实时分析开发实时监控系统在生成过程中即时分析风格社区分享将你的分析结果分享给其他创作者共同探讨风格规律艺术与技术的结合才刚刚开始。通过数据理解艺术通过艺术启发技术这正是AI创作时代的魅力所在。记住技术是工具艺术是灵魂。数据分析不是为了限制创作而是为了更深入地理解创作从而获得更大的创作自由。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。