资讯详情 CUT图像翻译用于SSDA-YOLO数据准备的原理与实践
📅 2026/10/26 6:26:15
1. 项目概述这不是在“翻译”图像而是在教模型理解“为什么这张图看起来像那张图”你点开这个标题大概率是刚读完那篇CUTContrastive Unpaired Translation论文或者在复现某个基于SSDA-YOLO的跨域检测项目时被卡在了数据准备这一步。别急——这确实是个容易让人困惑的坎。CUT本身不是为YOLO设计的它最初是为图像风格迁移比如把照片转成梵高画风提出的无配对对比学习框架而SSDA-YOLO指的是“半监督域自适应目标检测”核心诉求是用少量带标注的目标域数据比如真实街景中的车辆框配合大量无标注的源域数据比如合成的CARLA仿真图像让检测模型在目标域上表现更好。两者乍看不搭界但业内已有不少团队把CUT作为“域桥接器”来用先用CUT把源域图像“翻译”得更接近目标域分布视觉上更真实、纹理更自然、光照更一致再把这些翻译后的图像喂给SSDA-YOLO训练从而缓解域偏移带来的性能断崖。我去年在某高校实验室参与一个城市交通监控项目时就踩过这个坑。当时拿到的仿真数据源域非常干净但实拍视频目标域存在雨雾、低光照、镜头畸变等问题直接训练YOLOv5smAP掉到32%我们尝试用CUT做预处理把CARLA渲染图翻译成“带雾感低照度”的版本再输入SSDA-YOLO框架最终mAP回升到58.7%且推理速度几乎没损失。关键在于CUT不生成像素级精确重建而是学习域间不变的语义结构映射——它不关心一扇窗具体怎么反光但会确保“窗户”这个物体在翻译前后仍能被模型稳定识别。这种特性恰恰是SSDA-YOLO最需要的“语义对齐”能力。所以这个标题里的“[SSDA-YOLO数据集准备]”不是套壳而是精准定位了CUT在此类任务中的真实角色它不是最终检测模型而是数据增强的智能引擎。你不需要从零训练CUT也不必把它嵌进YOLO的loss里你只需要用它批量生成一批“伪目标域图像”再按标准SSDA-YOLO流程组织数据即可。接下来我会拆解为什么必须用CUT而不是传统GAN如何避免翻译后图像丢失关键检测特征比如车牌反光、行人轮廓以及最关键的——怎样用不到20行代码完成整个数据流水线且保证每张输出图都可用于YOLO训练。2. 核心思路拆解CUT为何比CycleGAN更适合SSDA-YOLO的数据准备2.1 传统方法的三大硬伤CycleGAN、UNIT、MUNIT全栽在这三点上很多初学者第一反应是用CycleGAN做域迁移毕竟它开源、教程多、显存占用小。但我在实测中发现CycleGAN在SSDA-YOLO场景下有三个致命缺陷缺陷一循环一致性强制像素级重建牺牲语义保真度CycleGAN要求A→B→A和B→A→B都尽可能还原原图。问题来了一张CARLA仿真车图源域翻译成实拍图目标域后再翻回去模型会拼命保留车灯位置、轮胎纹理等细节导致它不敢改变任何像素——结果就是翻译图和原图几乎一样只是加了层模糊滤镜。我用PS手动对比过CycleGAN输出一辆红色轿车在翻译后车顶反光区域被错误地“平滑”掉了而这个反光区恰恰是YOLO判断车辆朝向的关键线索。计算显示CycleGAN翻译图在YOLOv5s的cls_loss上比原图高47%说明分类分支已开始混淆。缺陷二缺乏显式对比机制无法抑制域无关噪声UNIT和MUNIT虽引入了VAE结构能学习潜在表示但它们没有对比学习模块。这意味着当源域仿真图存在大量“非现实”元素如完美平滑的路面、无阴影的建筑模型会把这些也当成“可迁移特征”一起翻译过去。我们曾用UNIT处理一段夜间仿真数据结果翻译图里出现了“发光的路标”——现实中根本不存在但YOLO在训练时却把它学成了“夜间车辆”的强相关特征导致在真实夜间视频中误检率飙升3倍。缺陷三单向翻译不可控无法聚焦检测关键区域所有传统GAN都是端到端黑箱输入整张图输出整张图。但SSDA-YOLO真正需要的是让“车辆”“行人”“交通灯”这些ROI区域更真实而非背景天空或远处楼宇。CycleGAN对整图施加同等强度变换结果常出现“车很真实但背景变成油画质感”的情况——YOLO的FPN结构会因背景失真产生异常特征金字塔干扰head层的定位精度。2.2 CUT的破局逻辑用对比学习锚定语义用patch判别器聚焦局部CUT的核心创新在于把“图像翻译”重构为“局部特征对比”问题。它不追求整图像素还原而是问“同一块图像区域patch在源域和目标域中哪些特征应该保持一致哪些可以自由变化” 这个问题的答案直接决定了SSDA-YOLO能否学到鲁棒的域不变特征。它的技术实现分三层第一层PatchNCE Loss —— 让模型学会“找相同”CUT将图像切分为64×64的重叠patch默认步长32对每个源域patch从目标域图像中采样正样本同一空间位置的patch和负样本随机位置的patch。然后用一个轻量级encoder提取特征计算InfoNCE lossL_NCE -log[exp(sim(z_i^s, z_i^t)/τ) / Σ_j exp(sim(z_i^s, z_j^t)/τ)]其中z_i^s是源域第i个patch特征z_i^t是目标域同位置patch特征τ是温度系数默认0.07。这个公式本质是让同位置patch特征尽可能靠近不同位置patch特征尽可能远离。实测表明当τ设为0.07时车辆轮胎patch在源/目标域的特征余弦相似度达0.89而轮胎与天空patch相似度仅0.12——模型已自发分离出“可迁移语义”。第二层Patch Discriminator —— 强制局部真实性拒绝全局造假CUT不用传统GAN的全图判别器而用多个小型patch判别器每个只看64×64区域。这带来两个好处计算高效单个patch判别器参数仅12K远低于全图判别器的2.3M局部约束模型若想“糊弄”判别器必须让每个64×64区域都看起来真实无法靠全局模糊掩盖局部失真。我们在验证时发现CUT翻译图的边缘梯度直方图与真实图高度重合KL散度0.05而CycleGAN的KL散度达0.31——说明CUT真正修复了检测最敏感的边缘信息。第三层Identity Mapping —— 为YOLO保留关键几何结构CUT在训练时加入identity loss当输入目标域图像时强制输出与输入相同。这听起来多余实则关键——它让模型明白“目标域图像的几何结构如车辆长宽比、行人站立姿态是黄金标准源域图像必须向它对齐而非相反”。在SSDA-YOLO中这意味着翻译后的车辆不会被拉长或压扁YOLO的anchor box尺寸无需重新聚类。提示CUT的patch机制天然适配YOLO的网格化预测。YOLO将图像划分为S×S网格每个网格预测B个box而CUT的64×64 patch与常见YOLO输入尺寸640×640恰好形成10×10的对应关系。这意味着CUT优化的patch特征可直接映射到YOLO的feature map层级减少特征错位。2.3 为什么CUT能成为SSDA-YOLO的“数据预处理器”而非“模型插件”很多团队试图把CUT嵌入YOLO训练流程比如在backbone后加CUT模块。这是误区。CUT的价值在于离线生成高质量中间数据而非在线增强。原因有三训练效率CUT单图翻译耗时约0.8秒V100但YOLO单次前向传播仅23ms。若在线调用训练速度下降35倍确定性离线生成可确保每张图被翻译一次避免同一张图在不同epoch被不同随机种子扰动破坏SSDA-YOLO的半监督一致性约束可控性你能对翻译结果做后处理——比如用OpenCV检测翻译图中的车牌区域若反光过强则用CLAHE算法局部提亮这种精细操作在线模式无法实现。我们最终采用的方案是CUT生成 → 质量过滤 → YOLO格式转换 → SSDA-YOLO训练。整个流程中CUT只负责第一步且这一步可并行化到8卡集群2小时处理10万张仿真图。这才是工业级落地的正确姿势。3. 数据准备全流程从原始仿真图到SSDA-YOLO可用数据集3.1 环境搭建与依赖确认避开CUDA版本陷阱CUT官方代码基于PyTorch 1.7但SSDA-YOLO常用PyTorch 1.10因YOLOv7/v8依赖新算子。直接混用会触发undefined symbol: _ZN3c104cuda10stream_t10get_streamEv错误。我的解决方案是用conda创建隔离环境而非pip全局安装。# 创建专用环境关键指定cudatoolkit版本 conda create -n cut-ssda python3.8 conda activate cut-ssda # 安装与你的GPU匹配的cudatoolkit以RTX 3090为例驱动版本515对应cudatoolkit 11.3 conda install pytorch1.10.2 torchvision0.11.3 torchaudio0.10.2 cudatoolkit11.3 -c pytorch # 安装CUT依赖注意不要用pip install pytorch-CUT那是旧版 git clone https://github.com/taesungp/contrastive-unpaired-translation.git cd contrastive-unpaired-translation pip install -e . # 额外安装SSDA-YOLO必需库 pip install opencv-python4.5.5.64 numpy1.21.6 tqdm4.62.3注意CUT的train.py默认使用--batch_size 1因为patch判别器对内存敏感。但如果你的GPU显存≥24GB如A100可安全提升至--batch_size 2训练速度提升1.8倍。实测--batch_size 2时V100显存占用从19.2GB升至22.7GB仍在安全阈值内。3.2 数据目录结构标准化让CUT和SSDA-YOLO无缝对接CUT对数据路径有严格约定而SSDA-YOLO以UDA-YOLO为例要求特定目录结构。我设计了一套兼容双框架的布局避免重复拷贝project_root/ ├── data/ │ ├── cut/ # CUT工作目录 │ │ ├── datasets/ │ │ │ ├── sim2real/ # CUT数据集根目录 │ │ │ │ ├── trainA/ # 源域图像仿真图.jpg │ │ │ │ └── trainB/ # 目标域图像实拍图.jpg仅需200张 │ │ ├── checkpoints/ # CUT模型保存路径 │ │ └── results/ # CUT翻译结果存放处 │ └── ssda_yolo/ # SSDA-YOLO数据目录 │ ├── images/ │ │ ├── train/ # SSDA-YOLO训练集含翻译图实拍图 │ │ └── val/ # 验证集纯实拍图 │ └── labels/ │ ├── train/ # YOLO格式标签.txt │ └── val/关键细节trainA只需放源域图像无需任何标签文件——CUT是无监督的trainB只需200~500张目标域图像越多越好但200张已足够学习域统计同样无需标签ssda_yolo/images/train/将同时包含CUT生成的翻译图命名加前缀cut_和原始实拍图命名保持原样这样SSDA-YOLO能自然学习“翻译图-实拍图”的混合分布。3.3 CUT训练配置详解参数背后的物理意义CUT的train.py有37个参数但SSDA-YOLO数据准备只需关注6个核心参数。我逐个解释其影响--name sim2real_cyclegan模型保存名建议包含sim2real标识便于后续管理--model cut必须设为cut若误设为cycle_gan会退化为传统GAN--netG resnet_9blocks生成器结构。resnet_9blocks比unet_256更适合高分辨率图如1920×1080因其残差连接能更好保留车辆边缘锐度。实测在1080p图上resnet_9blocks的PSNR比unet_256高2.3dB--n_epochs 50初始训练轮数。注意CUT采用线性衰减学习率前50轮用初始lr后50轮线性降到0。对于SSDA-YOLO50轮足够收敛再多易过拟合--lr 0.0002学习率。这是CUT论文推荐值但若你的源域图质量极差如CARLA低渲染设置可降至0.0001避免梯度爆炸--lambda_NCE 1.0对比损失权重。这是最关键参数默认1.0可能使模型过于关注局部patch而忽略全局结构。我们通过消融实验发现--lambda_NCE 0.5时翻译图的车辆长宽比误差3%而1.0时达8%——因为过高的NCE权重会压制生成器的全局协调能力。训练命令示例python train.py \ --dataroot ./data/cut/datasets/sim2real \ --name sim2real_cut_v1 \ --model cut \ --netG resnet_9blocks \ --n_epochs 50 \ --n_epochs_decay 50 \ --lr 0.0002 \ --lambda_NCE 0.5 \ --batch_size 1 \ --display_id 0 \ --gpu_ids 0,1,2,3实操心得训练时务必开启--display_id 0用TensorBoard实时观察G_GAN,G_NCE,D_real,D_fake四条曲线。健康训练的标志是G_NCE在20轮后稳定在0.15~0.25之间G_GAN略高于D_real说明生成器略占优。若G_NCE持续0.4说明lambda_NCE过大需中断训练调整。3.4 翻译阶段批量生成与质量过滤的工业级脚本训练完成后用test.py生成翻译图。但官方脚本默认只处理testA目录且输出为.pngYOLO常用.jpg。我重写了批量处理脚本generate_cut_images.pyimport os import torch from options.test_options import TestOptions from data import create_dataset from models import create_model from util.visualizer import save_images from PIL import Image import numpy as np opt TestOptions().parse() # get test options opt.num_threads 0 # test code only supports num_threads 0 opt.batch_size 1 # test code only supports batch_size 1 opt.serial_batches True # disable data shuffling; comment this line if results in fixed order opt.no_flip True # no flip; comment this line if results in flipped output opt.display_id -1 # no visdom display opt.dataroot ./data/cut/datasets/sim2real # 指向你的数据根目录 opt.name sim2real_cut_v1 # 模型名 opt.model cut opt.netG resnet_9blocks opt.results_dir ./data/cut/results/ # 输出目录 opt.phase train # 用trainA目录非testA opt.load_iter 0 # load best model opt.isTrain False dataset create_dataset(opt) # create a dataset given opt.dataset_mode and other options model create_model(opt) # create a model given opt.model and other options model.setup(opt) # regular setup: load and print networks; create schedulers for i, data in enumerate(dataset): if i % 5 0: # 每5张图打印一次进度 print(fProcessing {i}/{len(dataset)}) model.set_input(data) # unpack data from dataset and apply preprocessing model.test() # run inference visuals model.get_current_visuals() # get image results img_path model.get_image_paths() # get image paths # 只保存fake_B翻译图且转为JPEG fake_b visuals[fake_B] # 转numpy并裁剪到[0,255] fake_b_np (fake_b[0].cpu().float().numpy().transpose(1,2,0) 1) * 127.5 fake_b_np np.clip(fake_b_np, 0, 255).astype(np.uint8) # 保存为JPG质量95平衡体积与画质 pil_img Image.fromarray(fake_b_np) base_name os.path.basename(img_path[0]) out_path os.path.join(opt.results_dir, sim2real_cut_v1, images, fcut_{base_name.replace(.png, .jpg)}) pil_img.save(out_path, quality95)运行此脚本后./data/cut/results/sim2real_cut_v1/images/下将生成所有cut_*.jpg文件。但并非所有翻译图都合格。我设计了三重过滤机制亮度一致性检查计算翻译图与对应源域图的HSV通道均值差异若V通道明度差异30则丢弃说明翻译过度变暗/变亮影响YOLO的亮度鲁棒性边缘锐度检测用Canny算子提取边缘统计边缘像素占比。若8%过于模糊或25%过度锐化则丢弃目标区域完整性用预训练YOLOv5s在源域上训过对翻译图做快速推理若最高置信度0.3则丢弃说明翻译破坏了关键目标特征。过滤脚本filter_cut_images.py核心逻辑def filter_by_brightness(src_img_path, cut_img_path): src_hsv cv2.cvtColor(cv2.imread(src_img_path), cv2.COLOR_BGR2HSV) cut_hsv cv2.cvtColor(cv2.imread(cut_img_path), cv2.COLOR_BGR2HSV) v_diff abs(src_hsv[:,:,2].mean() - cut_hsv[:,:,2].mean()) return v_diff 30 def filter_by_sharpness(cut_img_path): img cv2.imread(cut_img_path, cv2.IMREAD_GRAYSCALE) edges cv2.Canny(img, 100, 200) sharp_ratio edges.sum() / (img.shape[0] * img.shape[1]) return 0.08 sharp_ratio 0.25 def filter_by_objectness(cut_img_path, yolo_model): results yolo_model(cut_img_path) confs results.xyxy[0][:,4].cpu().numpy() return len(confs) 0 and confs.max() 0.3实测10000张CARLA仿真图经CUT翻译后约87%通过三重过滤。被过滤的13%中72%因亮度失衡CARLA默认渲染过曝21%因边缘模糊源图本身分辨率低7%因目标消失翻译时误将车辆“溶解”进背景。3.5 SSDA-YOLO数据集组装让翻译图真正融入训练流程过滤后的cut_*.jpg需与原始实拍图共同构成SSDA-YOLO的训练集。关键在于标签同步CUT只处理图像不生成标签因此cut_*.jpg必须复用其源图的标签。假设源图carla_001.png对应标签carla_001.txtYOLO格式则cut_carla_001.jpg应使用同一份carla_001.txt。但要注意两点坐标系一致性CUT默认不进行几何变换如旋转、缩放只做外观迁移因此bbox坐标可直接复用文件名映射编写map_labels.py自动建立映射# 遍历cut结果目录 for cut_file in os.listdir(./data/cut/results/sim2real_cut_v1/images/): if cut_file.startswith(cut_) and cut_file.endswith(.jpg): src_name cut_file[4:].replace(.jpg, .png) # cut_carla_001.jpg - carla_001.png src_label src_name.replace(.png, .txt) # 复制标签到SSDA-YOLO目录 shutil.copy(f./data/original_labels/{src_label}, f./data/ssda_yolo/labels/train/{cut_file.replace(.jpg, .txt)})最终./data/ssda_yolo/目录结构为images/train/ ├── cut_carla_001.jpg # 翻译图 ├── cut_carla_002.jpg ├── real_001.jpg # 原始实拍图带标注 └── real_002.jpg labels/train/ ├── cut_carla_001.txt # 复用源图标签 ├── cut_carla_002.txt ├── real_001.txt # 实拍图真实标签 └── real_002.txt注意SSDA-YOLO通常要求训练集包含“有标签实拍图”和“无标签实拍图”但此处我们用“有标签翻译图”替代部分“有标签实拍图”因为翻译图的标签虽来自源域但其视觉分布已逼近目标域能提供更有效的监督信号。我们的消融实验显示用500张翻译图500张实拍图效果优于1000张实拍图mAP高3.2%证明了这一策略的有效性。4. 实操避坑指南那些论文里不会写的血泪教训4.1 “翻译后图像变色”问题不是bug是CUT在帮你发现数据偏差几乎所有新手第一次运行CUT都会惊呼“我的蓝色车翻译成绿色了” 别慌这往往不是模型故障而是CUT在揭示源域数据的隐性偏差。根源在于CARLA等仿真引擎的材质库中“蓝色”定义为RGB(0,100,255)而真实世界中蓝色车辆在阴天下的RGB均值是(30,120,230)。CUT的patch对比机制会捕捉到这种系统性差异并主动校准。我们用色卡实测将同一张Pantone色卡图放入trainA和trainBCUT翻译后色差ΔE从12.3降至4.1CIEDE2000标准说明它确实在做色彩域对齐。解决方案若你确定源域色彩准确如用专业相机拍摄的标定图可在CUT训练时添加--no_dropout参数关闭生成器中的dropout层减少色彩扰动更推荐的做法是接受CUT的色彩校准但用OpenCV的cv2.xphoto.BalanceWhite对翻译图做白平衡微调使其更贴近目标域均值。4.2 “小目标翻译后消失”CUT的patch大小与YOLO尺度的隐性冲突CUT默认patch size为64×64这对1920×1080图很合适但对YOLO检测的小目标如远处行人仅32×64像素就成问题——一个行人可能被切在两个patch交界处导致特征被割裂。实测现象在CARLA中100米外的行人约24×48像素经CUT翻译后检测置信度从0.62降至0.18。根本原因CUT的patch采样是随机的小目标区域可能从未被选为正样本patch导致其特征未被NCE loss约束。破解方法预处理源图用cv2.resize将源图放大1.5倍如1920×1080→2880×1620再送入CUT。翻译后缩回原尺寸小目标区域被放大更易被捕获修改CUT源码在models/cut_model.py中将self.patch_size 64改为self.patch_size 32并相应调整--crop_size 256原为286。实测32×32 patch使小目标mAP提升11.4%后处理增强对翻译图用cv2.createCLAHE(clipLimit2.0, tileGridSize(8,8))对小目标区域做局部对比度增强。4.3 “训练崩溃CUDA out of memory”显存优化的5个硬核技巧CUT在大图上训练极易OOM。除了前述--batch_size 1还有五个被低估的技巧技巧1禁用梯度检查点CUT默认启用torch.utils.checkpoint但对V100反而增加显存。在models/networks.py中注释掉from torch.utils.checkpoint import checkpoint及所有checkpoint()调用显存降低1.2GB。技巧2降低判别器深度在models/networks.py中将NLayerDiscriminator的n_layers从4改为3判别器参数从1.8M降至0.6M显存节省800MB。技巧3混合精度训练添加--fp16参数需PyTorch 1.6用torch.cuda.amp自动混合精度。实测V100上--fp16使显存占用从19.2GB降至14.5GB训练速度提升1.4倍。技巧4Patch缓存复用CUT每次迭代都重新采样patch开销大。在data/paired_dataset.py中将self.A_paths和self.B_paths预加载为内存映射np.memmap避免IO瓶颈。技巧5渐进式分辨率不要直接训1920×1080图。先用--load_size 512 --crop_size 256训50轮再--load_size 1024 --crop_size 512训30轮最后--load_size 1920 --crop_size 1024训20轮。总时间只增15%但最终模型稳定性提升3倍。4.4 “翻译图带伪影”如何识别并清除CUT的“创造性发挥”CUT有时会添加源域/目标域都不存在的纹理比如在车辆引擎盖上生成“水波纹”或在行人衣服上添加“编织纹”。这些伪影会被YOLO误学为特征。识别方法用频域分析。对翻译图做FFT若在高频区0.3周期/像素出现尖锐峰值则存在人工纹理。正常图的FFT能量应呈平滑衰减。清除方案空域滤波对翻译图用cv2.bilateralFilter(img, d9, sigmaColor75, sigmaSpace75)双边滤波能在保边前提下抹除高频伪影频域掩膜用scipy.fft.fft2获取频谱对高频区u²v²0.3²设为0再ifft2重建GAN指纹检测用预训练的GAN fingerprint detector如ForenSynths扫描若检测概率0.8则丢弃该图。我们测试了1000张翻译图23%含可检测伪影其中87%可通过双边滤波清除剩余13%需重训CUT降低--lambda_NCE至0.3。4.5 SSDA-YOLO训练时的标签漂移为什么翻译图的标签不能直接用这是最隐蔽的坑。CUT翻译后车辆位置理论上不变但实际中由于透视校正或光照变化bbox可能轻微偏移。我们用激光雷达标定数据验证500张翻译图中32%的车辆bbox中心偏移5像素在640×640输入下。解决方案轻量级refine用YOLOv5s在翻译图上做一次快速推理conf0.1取最高置信度bbox与原标签做IoU匹配若IoU0.7则用YOLO预测框替换原标签坐标微调对原标签bbox按翻译图与源图的SIFT特征点匹配结果做仿射变换校正。我们开发了refine_labels.py5分钟处理1000张图平均偏移降至1.2像素。实操心得在SSDA-YOLO的train.py中务必设置--mixup 0.1和--mosaic 0.5让翻译图与实拍图在增强阶段充分混合。我们发现关闭mosaic时模型对翻译图的过拟合率高达41%开启后降至12%——证明数据增强是消化翻译图的关键缓冲。5. 效果验证与量化评估用数据说话而非主观感受5.1 构建可信的评估协议避免“幸存者偏差”很多团队只报告“翻译后mAP提升”却不说明基线。我们采用三级评估Level 1CUT自身指标用LPIPSLearned Perceptual Image Patch Similarity衡量翻译质量。LPIPS越低感知越相似。CUT在sim2real任务上LPIPS0.21CycleGAN0.38证明其语义对齐更强。Level 2中间表征评估冻结YOLOv5s backbone用CUT翻译图和实拍图分别提取feature map计算各层特征的CKACentered Kernel Alignment相似度。结果显示CUT翻译图在P3层对应小目标的CKA达0.63CycleGAN仅0.41——说明CUT真正提升了小目标特征的域一致性。Level 3下游任务指标在SSDA-YOLO框架下对比四组实验Baseline仅用实拍图训练500张SimOnly仅用仿真图训练10000张SimReal仿真图实拍图混合训练CUTRealCUT翻译图实拍图训练。方法mAP0.5mAP0.5:0.95推理FPSBaseline32.114.742.3SimOnly28.411.245.1SimReal41.619.840.2CUTReal58.727.341.8关键发现CUTReal的mAP比SimReal高17.1%证明CUT翻译图提供的监督信号远超原始仿真图。5.2 消融实验每个CUT组件对SSDA-YOLO的贡献度为验证CUT各模块价值我们做了控制变量实验配置GAN LossNCE LossIdentity LossmAP0.5A✓✗✗