ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

开放集动物重识别:相似度校准与图聚类实战解析

开放集动物重识别:相似度校准与图聚类实战解析 动物重识别Animal Re-Identification是近年视觉落地里很值得关注的方向尤其是智慧养殖、生态监控和动物园个体管理。大多数公开方案把问题简化成封闭集分类但真实场景几乎都是开放集训练阶段只标注了一批个体测试阶段突然出现从未见过的新个体模型如果继续硬匹配就会把新个体的照片强行归到已知个体上产出大量误检。这篇标题为Calibrated Similarity and Graph Clustering for Open-Set Animal Re-Identification的方法思路很直接先对相似度做校准让“见过”和“没见过的个体”在打分空间上拉开差距再用图聚类把同一个体跨摄像头、跨时间的图像关联起来同时把新个体作为新簇头自动发现。也就是说它不只是换一个分类头而是同时改动了相似度计算和后处理决策链路。只看标题很多人会以为这就是“特征提取 相似度 聚类”三件套的常规流水线。但从技术落地角度看难点恰恰在组合设计相似度不校准图里的边会混入大量噪声聚类算法再强也分不开聚类策略选错即便相似度已经是校准过的也会把同一个体的不同视角拆成两个簇。所以这个方向最值得关注的不是某一个单独的 backbone 或 loss而是“校准相似度”和“图聚类”如何互相配合最终输出一个可用的开放集重识别结果。这篇文章会把这条链路拆开讲清楚。我会先给一份核心能力速览再拆解技术原理然后给出一套可复现的本地实现框架包含环境准备、模型推理、相似度校准、图聚类的代码模板以及功能测试、API 封装、批量任务、资源占用观察和常见问题排查。如果你在做 CV 算法或者想把动物个体识别接到监控系统、养殖管理系统里这篇文章可以直接收藏照着一套流程从零验证。1. 核心能力速览先看一眼这个方向的关键信息方便你判断是否值得继续读下去。能力项说明项目类型开放集动物重识别算法研究方案核心思路相似度校准 图聚类联合决策主要功能动物个体身份匹配、跨摄像头检索、开放集新个体发现、个体聚类输入类型动物图像序列或单张查询图输出类型匹配身份 ID、未知个体标记、聚类簇分配结果推荐硬件特征提取阶段建议 GPUCPU 可跑小规模验证启动方式无官方一键包需要按方法流程自己搭建推理与聚类服务是否支持 API论文未直接说明可自行封装为 HTTP 服务是否支持批量任务可以支持按“特征提取 匹配/聚类”两阶段设计适合读者CV 算法工程师、生态/农业领域研发、论文复现研究者这里需要说明标题和检索材料没有给出明确的仓库地址、作者信息或训练权重所以下面的内容以方法拆解和通用实现为主。实际复现时需要以论文正文和作者公开代码为准如果你手头有官方仓库把里面的特征提取网络和损失函数细节替换到这套框架中即可。2. 适用场景与使用边界这个方案适合三类场景。第一类是跨摄像头动物个体追踪。比如一个养殖场里有几十台摄像头同一头猪、同一只羊可能在不同画面里出现。传统目标检测只能给出“这里有一头猪”不能回答“这头猪是哪个编号”。重识别解决的就是这个问题而开放集设置保证了新购入或新出生的动物不会硬套到旧编号上。第二类是野生动物个体档案构建。斑马、老虎、黑猩猩这类动物纹理和面部特征相对稳定可以通过图像建立个体档案。图聚类可以把同一只动物在不同时间、不同角度、不同光线下拍摄的图像归到一起减少人工比对工作量。第三类是动物园和救助站的个体管理。动物患病、受伤后需要跨拍摄点快速找到它的近期照片但没法保证这只动物一定在历史档案里。开放集重识别可以输出“最相似的若干个历史个体 是否为新个体”给管理员提供复查依据而不是直接给一个可能错误的一对一结果。使用边界也很明显。首先这个方案不是实时检测器它更偏向离线检索和近实时比对如果要在海量视频流上逐帧直接跑需要做抽帧、目标检测、质量筛选的前置管线整体延迟会很高。其次同品种、同毛色的动物之间辨识度很低如果个体外观差异本来就小仅靠 RGB 图像很难达到高准确率需要配合耳标、微芯片、足迹等信息。再次开放集方法中的“未知”判定依赖阈值不同数据集、不同采集环境下的阈值差异很大不能指望一个固定参数打遍所有场景。安全边界上也必须说清楚。动物图像可能涉及养殖场经营数据、野生动物保护区域坐标、动物园内部管理信息采集和使用都需要合法授权。涉及濒危保护动物时不能公开精确拍摄点位涉及人像或饲养员画面时需要做隐私脱敏。模型训练和评测使用的数据集也应确认版权允许避免把受保护的数据直接用于商用模型训练。3. 技术原理拆解从相似度到图聚类要理解这个方案先要区分两个概念封闭集识别和开放集识别。封闭集识别假设测试图像一定来自训练见过的类别模型只做“N 选 1”。常规做法是把 Re-ID 当作分类问题最后一层输出每个个体的概率。这种设计在模型训练时很舒服但部署时会遇到严重问题新个体出现时模型无法拒绝只能从旧类别里硬选一个结果通常很不可信。开放集识别则要求模型有“都不认识”的判断能力。具体到动物 Re-ID输入一张图片输出可能是一个已知个体 ID也可能是“未知”。要做到这一点不能只看最大相似度而是要判断最大相似度是否高到足够可信。这就是“相似度校准”存在的意义。从标题看这个方法把流程拆成四个关键环节特征提取用深度卷积网络或视觉 Transformer 把动物图像编码成特征向量。相似度计算在特征空间里计算查询图像与 Gallery 图像的相似度常用余弦相似度或欧氏距离。相似度校准对原始相似度做转换降低不同个体、不同摄像头风格造成的分数偏差让正样本对和负样本对的分数边界更清晰。图聚类决策以图像为节点、校准后的相似度为边构建图通过聚类算法得到最终个体簇新出现的个体自然形成新的簇也就不需要提前限定类别数量。为什么要用图聚类而不是简单的“top-1 最近邻 阈值”因为单个摄像头单张图片的匹配结果很容易被遮挡、姿态、光线变化干扰。图的好处是可以利用样本之间的传递关系A 和 B 很像B 和 C 很像但 A 和 C 的直接相似度不高通过图结构和相似度传播还是能把它们归到同一个体群组。尤其是在动物视频监控场景里同一个体经常连续多帧出现帧与帧之间构成一条强连边跨摄像头之后又通过外观相似度连到另一台设备的画面。这个结构天然适合图聚类。图聚类阶段通常不会直接使用“完全图”而是先做相似度阈值裁剪只保留高于一定阈值的边。这样做有两个好处第一降低计算复杂度稀疏图比稠密图聚类更快第二过滤噪声边避免把相似但不相同的个体错误连接。校准相似度的作用在这里非常关键如果阈值定在原始相似度上不同摄像头、不同光照下的正样本对分数可能很低漏判严重经过校准后分数分布更稳定阈值才有一般意义。候选的图聚类算法包括近邻传播聚类、密度聚类 DBSCAN、谱聚类、Louvain 社区发现等。具体选择要看图规模和全局簇结构的稳定性小规模验证可以先用 DBSCAN中大规模数据可以试试谱聚类或 Louvain。如果你需要更严格的数学推导论文正文中通常会给出一致性分析或优化目标复现时建议把损失函数和聚类目标一起看清楚。4. 环境准备与前置条件这套流程并不是一个现成的一键包而是标准 Python 机器学习项目。环境准备可以分为四个部分基础环境、深度学习框架、图计算/聚类工具、数据处理工具。基础环境方面需要一台 Linux 或 Windows 机器推荐安装 Anaconda 或 Miniconda 管理 Python 环境。Python 版本建议使用 3.8 到 3.10避免过新版本带来的依赖兼容问题。GPU 不是必须但特征提取阶段如果有 NVIDIA 显卡会快很多。显存需求取决于你选择的 backbone如果是 ResNet50 这类常规网络8GB 左右显存通常可以跑如果你用 ViT-Large 或更大模型20GB 以上显存会更稳妥。这里没有固定数字建议以实际模型、图像分辨率、batch size 为准。深度学习框架选择 PyTorch生态成熟方便做微调和特征导出。图聚类部分可以使用 scikit-learn 的 DBSCAN也可以用 NetworkX 手动建模再配合 python-louvain 做社区发现。近似近邻检索工具推荐 FAISS它在向量规模较大时比暴力检索快很多支持 GPU 加速。下面是一套通用环境安装命令实际使用时按你的 CUDA 版本调整 PyTorch 安装源。# 创建虚拟环境 conda create -n animal_reid python3.10 -y conda activate animal_reid # 安装 PyTorch官方命令请对应当前 CUDA 版本 pip install torch torchvision # 安装常用依赖 pip install numpy opencv-python pillow scikit-learn pip install faiss-cpu networkx2.6 python-louvain pip install pyyaml tqdm安装时最容易踩的坑是 FAISS 和 PyTorch 的版本冲突。如果你只需要小规模测试只装 scikit-learn 也能跑通聚类只有特征数量到十万级以上再引入 FAISS 做加速。数据准备上建议先把图像按个体 ID 分目录组织好一个个体一个文件夹文件名为“个体ID_摄像头ID_时间戳.jpg”。这个命名习惯直接影响后续的特征文件管理也会方便你验证跨摄像头检索效果。5. 算法实现与启动运行因为没有统一的官方代码这里给出一个可运行的通用实现框架。你需要先准备一个特征提取模型可以使用 ImageNet 预训练的 ResNet50也可以替换成任何更贴合动物数据的 Re-ID 模型。下面的脚本展示完整的流程读取图像、提取特征、计算校准相似度、图聚类、输出结果。5.1 项目目录结构建议先建立如下目录animal_reid/ ├── configs/ │ └── config.yaml ├── data/ │ ├── gallery/ │ │ └── individual_001/ │ │ ├── cam1_001.jpg │ │ └── cam2_002.jpg │ └── query/ │ └── query_001.jpg ├── scripts/ │ ├── extract_features.py │ ├── calibrate_similarity.py │ └── graph_cluster.py ├── weights/ │ └── resnet50.pth ├── outputs/ │ ├── features.npy │ └── result.csv └── README.md5.2 配置参数配置文件中包含特征提取、相似度阈值和聚类参数。阈值先给一个保守的初始值后续根据验证结果调整。model: name: resnet50 pretrained: true img_size: 224 feature_dim: 2048 reid: similarity: cosine calibration: temperature temperature: 0.05 low_similarity_threshold: 0.2 high_similarity_threshold: 0.5 clustering: algorithm: dbscan eps: 0.35 min_samples: 2需要注意这里temperature是一个可学习或手工调节的参数。温度缩放是相似度校准里最常见的一种做法把相似度除以温度 T使得正负样本的距离分布更加锐利。T 越大分布越平滑T 越小分布越尖锐。具体数值必须用验证集调整不要直接沿用示例。5.3 特征提取脚本import os import numpy as np import torch from torchvision import transforms, models from PIL import Image device torch.device(cuda if torch.cuda.is_available() else cpu) transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]) model models.resnet50(weightsmodels.ResNet50_Weights.IMAGENET1K_V1) model.fc torch.nn.Identity() # 去掉分类头只保留特征向量 model model.to(device).eval() def extract_feature(image_path): img Image.open(image_path).convert(RGB) img transform(img).unsqueeze(0).to(device) with torch.no_grad(): feat model(img) return feat.cpu().numpy().flatten() def extract_features_from_dir(gallery_dir): features [] paths [] for identity in os.listdir(gallery_dir): identity_dir os.path.join(gallery_dir, identity) if not os.path.isdir(identity_dir): continue for img_name in os.listdir(identity_dir): img_path os.path.join(identity_dir, img_name) features.append(extract_feature(img_path)) paths.append((identity, img_name)) return np.array(features), paths if __name__ __main__: feats, meta extract_features_from_dir(./data/gallery) np.save(./outputs/features.npy, feats) with open(./outputs/meta.txt, w) as f: for identity, img_name in meta: f.write(f{identity}\t{img_name}\n) print(fextracted {feats.shape[0]} features, dim{feats.shape[1]})这个脚本只做最基本的特征提取。如果你用的是训练好的动物 Re-ID 模型把models.resnet50换成对应模型并加载训练权重即可。真实项目中特征提取前还需要做动物目标检测把每只动物单独裁剪出来避免背景干扰。5.4 相似度校准与图聚类脚本特征提取完成后下一步是计算校准相似度并聚类。这里给出一个可运行的组合脚本。import numpy as np from sklearn.metrics.pairwise import cosine_similarity from sklearn.cluster import DBSCAN import networkx as nx def calibrate_similarity(sim_matrix, temperature0.05): # 温度校准将原始余弦相似度除以温度 calibrated sim_matrix / temperature # 对数值稳定性做裁剪 calibrated np.clip(calibrated, -5, 5) # 这里使用 sigmoid 把校准后的值压回 0~1 区间 return 1 / (1 np.exp(-calibrated)) def build_graph(calibrated_sim, threshold0.5): n calibrated_sim.shape[0] G nx.Graph() G.add_nodes_from(range(n)) for i in range(n): for j in range(i 1, n): if calibrated_sim[i, j] threshold: G.add_edge(i, j, weightfloat(calibrated_sim[i, j])) return G def cluster_by_dbscan(features, eps0.35, min_samples2): # 直接用特征做 DBSCAN也可以先做相似度校准再转距离 clustering DBSCAN(epseps, min_samplesmin_samples, metriccosine) labels clustering.fit_predict(features) return labels def cluster_by_graph(features, temperature0.05, threshold0.5): sim cosine_similarity(features) cal_sim calibrate_similarity(sim, temperature) G build_graph(cal_sim, threshold) # 取连通分量作为聚类结果适合小规模数据 components list(nx.connected_components(G)) labels np.zeros(features.shape[0], dtypeint) for label, comp in enumerate(components): for node in comp: labels[node] label return labels if __name__ __main__: feats np.load(./outputs/features.npy) labels cluster_by_graph(feats) print(cluster labels:, labels)这个脚本是一个基础模板不是论文的官方实现。它展示了“相似度校准 图聚类”两个阶段如何代码化。实际复现时你需要把温度校准替换成论文中的校准函数把连通分量替换成论文选择的聚类算法。5.5 启动运行流程完整运行顺序如下数据准备把图像放进data/gallery和data/query。运行特征提取脚本生成features.npy。运行聚类脚本得到聚类标签。打开outputs目录检查每个簇的图像是否属于同一个体。如果你在服务器上跑建议用tmux或nohup挂载任务因为特征提取在大规模数据集上可能耗时较长。nohup python scripts/extract_features.py logs/extract.log 21 6. 功能测试与效果验证搭建完流程后不能只看特征能跑必须对每个核心功能设计验证实验。下面是一套适合开放集动物重识别的测试方案。6.1 已知个体匹配测试这一项测试模型能否正确检索到已知个体。操作步骤是从gallery中取一张图作为查询图其余图作为候选库计算 top-1、top-5 检索结果。预期结果是查询图同一身份的图像出现在 top-1 或 top-5 中。如果出现大量错检先检查图像质量比如是否模糊、是否包含多只动物、是否背景遮挡严重。再检查特征提取模型是否针对动物数据训练如果直接用 ImageNet 模型动物部位特征可能不够稳定。6.2 开放集拒绝测试这是整个方法里最重要的测试。构造一个包含大量未知个体的查询集合这些个体从未出现在 gallery 中。对每张查询图计算它和 gallery 的最相似分数然后看系统能否把这些查询判定为“未知”。判断标准是未知个体被拒绝的比例以及已知个体被误判为未知的比例。这两个指标需要平衡。如果系统把所有图像都判定为未知说明相似度阈值过高或校准不充分如果系统把所有未知都判定为已知说明阈值过低需要调高拒绝敏感度。6.3 聚类一致性测试聚类一致性测试关注同一个体是否被分到同一个簇不同个体是否被分到不同簇。用标准化互信息 NMI 或调整兰德指数 ARI 来评估。操作方法是拍摄同一只动物在多个角度、多个时间的图片打上真实个体 ID运行聚类脚本后对比聚类标签和真实标签。如果 NMI 低于 0.8说明相似度校准或聚类参数有问题。重点检查不同摄像头间的颜色偏移是否被处理必要时增加色彩校正。6.4 跨摄像头检索测试跨摄像头是动物重识别最常见的部署场景。把摄像头 A 的图像作为 gallery摄像头 B 的图像作为 query检验模型能否忍受视角和光照变化。如果跨摄像头效果远差于同摄像头效果说明特征受到摄像头域偏移影响。可以考虑加入域自适应方法或者在数据集中增加多摄像头样本对让模型学习跨域不变特征。6.5 批量任务稳定性测试连续跑 100 次查询或 1000 张图的聚类观察是否出现内存溢出、进程卡死、结果不一致等问题。这个测试主要是为后续接口化和批处理做铺垫。7. 接口 API 与批量任务设计论文本身没有接口说明但真实系统接入时接口是必须的。最简单的方式是使用 FastAPI 封装两个核心接口单图查询接口和批量接口。7.1 单图查询接口输入一张查询图返回最相似的若干个候选身份以及该查询图是否属于已知个体的判断。from fastapi import FastAPI, UploadFile, File import numpy as np import torch from scripts.extract_features import extract_feature from sklearn.metrics.pairwise import cosine_similarity app FastAPI() gallery_features np.load(./outputs/features.npy) gallery_ids [line.split(\t)[0] for line in open(./outputs/meta.txt)] app.post(/query) async def query_image(file: UploadFile File(...)): temp_path f./temp/{file.filename} with open(temp_path, wb) as f: f.write(await file.read()) query_feat extract_feature(temp_path) sim cosine_similarity([query_feat], gallery_features)[0] top_indices np.argsort(sim)[::-1][:5] top_results [] for idx in top_indices: top_results.append({ identity: gallery_ids[idx], score: float(sim[idx]) }) max_score float(sim.max()) is_known max_score 0.5 # 阈值需要根据校准结果调整 return { is_known: is_known, max_score: max_score, top5: top_results }这里需要注意top1的最高分数阈值 0.5 只是示例。实际系统中阈值必须从验证集统计得到不能照抄。7.2 批量目录处理接口批量任务更适合做成离线任务上传一个包含多张图像的目录服务端逐张提取特征然后统一聚类最后返回分组结果。app.post(/batch_cluster) async def batch_cluster(files: list[UploadFile] File(...)): temp_paths [] for i, file in enumerate(files): temp_path f./temp/batch_{i}_{file.filename} with open(temp_path, wb) as f: f.write(await file.read()) temp_paths.append(temp_path) feats np.array([extract_feature(p) for p in temp_paths]) labels cluster_by_graph(feats) result {} for path, label in zip(temp_paths, labels): result.setdefault(int(label), []).append(path) return {cluster_count: len(result), clusters: result}批量任务设计需要注意几点第一图像上传要有大小和数量限制避免大量大图拖垮服务第二每个任务要记录日志包括输入路径、特征文件、聚类参数、输出结果第三聚类是计算密集型任务建议用队列串行执行避免并发时内存爆炸。7.3 失败重试建议特征提取偶尔会因为图像损坏或格式问题失败。建议在批量脚本里加入异常捕获try: feat extract_feature(path) except Exception as e: print(ffailed {path}: {e}) continue接口服务也建议对超时调用返回明确错误码方便前端重试。8. 资源占用与性能观察运行这套流程时资源占用主要集中在两个阶段。特征提取阶段占用 GPU 显存和部分 CPU。显存消耗取决于 backbone 大小、图像尺寸和 batch size。如果你使用的是 ResNet50输入 224x224batch size 1显存占用通常较低如果换成更大的模型或者一次处理 64 张图显存会明显上涨。实操时建议用nvidia-smi或gpustat实时观察显存变化。聚类阶段基本不占用 GPU但会消耗内存。完全图相似度矩阵的规模是 N×NN 是特征数量。如果特征数量是 10 万那么相似度矩阵是 100 亿个浮点数需要大约 40GB 内存单机很容易扛不住。解决办法有两个一是先用 FAISS 做最近邻检索只保留 top-k 相似边构建稀疏图二是直接使用 FAISS 自带的聚类方法避免生成全量矩阵。观察性能时建议重点记录三个指标单张图平均特征提取时间、十万级特征建图时间、单次聚类时间。不同硬件差异很大所以不要在文章里记死数字用你自己的环境跑一遍才最有价值。降低资源占用的通用手段图像先做动物检测和裁剪只提取动物区域特征减少背景干扰也降低图像尺寸。把图片压缩到 256x256 或 224x224不要用原图直接提取。使用半精度 FP16 推理能明显降低显存占用。聚类阶段先抽样验证参数再全量运行避免参数不合理时反复跑全量。分批次提取特征把特征文件落盘不要一次性把所有图像加载到内存。9. 常见问题与排查方法问题现象可能原因排查方式解决方案依赖安装失败Python 版本过高或 CUDA 版本不匹配查看 pip 安装日志检查 torch 是否可用更换 Python 3.10按官方命令装对应 CUDA 版本特征提取后所有特征都一样模型没有加载正确权重或输入图像全黑/全灰打印特征标准差随机取几张图查看重新加载预训练权重检查图像读取路径聚类结果把同一个体分成多簇相似度阈值过高或温度参数过小查看簇数量和每个簇的图像降低阈值增大温度 T或改用密度聚类开放集阈值把新个体误判为已知校准集不具代表性分数分布偏移统计已知/未知个体最高相似度分布重建校准集加入更多负样本动态调整阈值显存不足图像尺寸太大batch size 太大backbone 过大观察 nvidia-smi 显存占用降低分辨率减小 batch使用 FP16API 调用失败服务未启动或请求字段和接口不匹配查看 FastAPI 日志测试健康检查接口确认端口检查请求格式批量任务卡住特征提取阶段没有异常捕获或聚类生成全量矩阵查看日志输出监控内存占用加入异常捕获改用 FAISS 稀疏图跨摄像头效果差颜色分布差异大特征域偏移检查不同摄像头下同一动物特征距离增加跨摄像头样本加入色彩归一化10. 最佳实践与使用建议开放集动物重识别项目最容易失败的地方不是模型训练而是数据管理和阈值设计。下面这几条建议来自常见的工程经验可以直接拿来用。第一所有图像按“个体ID_摄像头ID_时间戳”命名。这个命名习惯能让你在分析聚类错误时快速定位问题比如发现某两个簇经常混在一起可以马上检查是不是同一只动物在不同摄像头下的外观差异。第二第一次跑通流程时只使用少量数据。比如 10 个个体的 100 张图先把流程走通再逐步放大数据量。小数据量能快速暴露代码问题也方便对比相似度校准前后的结果。第三校准集一定要包含足够多的负样本。很多开放集方案失败是因为校准数据里都是正样本对模型学会了“高分意味着同一只动物”但没见过“高分但不认识的个体”导致开放集拒绝能力很弱。校准集应覆盖已知个体对、未知个体对、跨摄像头对、跨时间段对。第四聚类阈值不要完全手工调。先从验证集上统计正负样本对的相似度分布再选择分布重叠区域的临界值作为初始阈值。之后用聚类结果反推再微调。第五接口服务要限制访问范围。如果部署在服务器上不要直接绑定0.0.0.0对外开放推荐只监听内网或加 API Key 认证。第六涉及动物图像、个人隐私数据、商业数据时必须确认数据来源合法获得采集和授权许可。野生动物监测数据尤其要谨慎不要公开敏感位置信息。第七商用前做效果复核。重识别结果只适合做辅助参考正式决策前需要人工确认尤其是医疗、繁殖、检疫等场景错误身份可能造成实质影响。11. 总结与下一步这个方向最值得尝试的点是把“开放集判定”从简单的阈值比较升级成“相似度校准 图聚类”的组合决策。对于动物重识别这类个体外观差异大、环境变化强的任务这种组合比单一分类头更贴近真实部署。最先要验证的功能是开放集拒绝能力。你可以先拿 100 张已知动物图和 20 张新动物图跑一遍查询看看系统能不能把新动物判为未知。如果这一步不达标后面的聚类再准也没有意义。最容易踩的坑就是相似度阈值。很多复现项目在公开数据集上效果不错一到自己的摄像机场景就崩本质上是分数分布变了阈值却没有跟着变。解决方法是把阈值当成一个需要随数据分布更新的参数而不是一次调好就固定不改。下一步可以扩展的方向有三个一是接入动物检测模型形成“检测 跟踪 重识别”的完整管线二是做跨摄像头特征域自适应减少不同设备间的颜色偏差三是引入增量学习让系统能够在运行过程中逐步学习新个体特征不需要全量重训。把这些点一个个落地开放集动物重识别就可以从论文里的方法变成一个真正可用的系统。
返回列表