异常检测patchcore 学习笔记 2025
目录
patchcore
原理介绍:
工业零件异常检测
PatchCore 做缺陷检测,不同的光线,角度,反光,偶尔有遮挡 都能处理吗
✅ PatchCore 能处理的情况
1. 不同光线条件 ⚡
2. 不同角度 📐
3. 反光问题 ✨
❌ PatchCore 的局限性
4. 偶尔遮挡 🚫
异常动作检测
patchcore
星星更多:
https://github.com/amazon-science/patchcore-inspection
https://github.com/hcw-00/PatchCore_anomaly_detection
原理介绍:
https://blog.csdn.net/m0_37302966/article/details/147143120
工业零件异常检测
经典的 PatchCore 及其直接变体在处理刚性物体(如工业零件)时表现出色,正是因为它们有统一的标准、外观变化有限、纹理和结构稳定。但当应用到“人类动作”这种非刚性、高方差、充满语义变化的场景时,会面临巨大的挑战,核心矛盾就在于 “无法收集所有正确的样本”。
PatchCore 做缺陷检测,不同的光线,角度,反光,偶尔有遮挡 都能处理吗
您提出了一个非常关键的问题!PatchCore 在这些挑战性场景下的表现需要仔细分析:
✅ PatchCore 能处理的情况
1. 不同光线条件 ⚡
处理能力:中等
-
✅ 如果训练集包含了足够的光线变化样本
-
✅ 对亮度变化有一定的鲁棒性(特征相对不变性)
-
✅ 可以通过数据增强改善
python
# 增强训练数据的光线多样性 def augment_lighting_variation(normal_images):augmented = []for img in normal_images:# 亮度调整augmented.append(adjust_brightness(img, ±30%))# 对比度调整 augmented.append(adjust_contrast(img, ±20%))# 伽马校正augmented.append(gamma_correction(img, [0.7, 1.3]))return augmented
2. 不同角度 📐
处理能力:较好
-
✅ 基于局部特征匹配,对角度变化有一定容忍度
-
✅ 如果训练集包含多角度样本,效果更好
-
⚠️ 大角度变化可能被视为异常
3. 反光问题 ✨
处理能力:有限
-
⚠️ 强烈反光可能被误判为异常
-
✅ 可以通过预处理减少影响
-
✅ 如果反光模式一致,可能被学习为正常
❌ PatchCore 的局限性
4. 偶尔遮挡 🚫
处理能力:较差
-
❌ 遮挡会被直接检测为异常
-
❌ 无法区分"真实缺陷"和"临时遮挡"
-
❌ 需要后处理或额外逻辑处理
异常动作检测
import torch
import torch.nn as nn
from sklearn.neighbors import NearestNeighbors
import numpy as np# 1. 加载预训练的特征提取器 (例如 I3D)
feature_extractor = load_pretrained_i3d_model().eval().to(device)# 2. 构建记忆库 - 训练阶段
memory_bank = [] # 用来存储所有正常特征with torch.no_grad():for normal_video_batch in normal_train_dataloader:# normal_video_batch shape: (B, C, T, H, W)features = feature_extractor(normal_video_batch.to(device)) # 提取特征# 对特征进行重塑和采样 (例如, 取时空维度上的所有点)features = features.permute(0, 2, 3, 4, 1).reshape(-1, features.size(1)) # (B*T*H*W, C)memory_bank.append(features.cpu().numpy())memory_bank = np.vstack(memory_bank)
# 对 memory_bank 进行 Coreset 采样,得到一个小而精的记忆库
# sampled_memory_bank = coreset_sampling(memory_bank, n_samples=10000)# 构建 KNN 模型
knn_model = NearestNeighbors(n_neighbors=1, algorithm='auto', metric='cosine').fit(sampled_memory_bank)# 3. 异常检测 - 推理阶段
def predict_anomaly(video_clip):with torch.no_grad():test_feature = feature_extractor(video_clip.to(device))test_feature = test_feature.permute(0, 2, 3, 4, 1).reshape(-1, test_feature.size(1)).cpu().numpy()distances, indices = knn_model.kneighbors(test_feature)anomaly_score = np.max(distances) # 取最大距离作为异常分数if anomaly_score > threshold:return "Anomaly", anomaly_scoreelse:return "Normal", anomaly_score