新闻详情

新闻详情

首页 / 资讯中心 / 详情

鱼数据集VOC与YOLO格式解读及YOLOv8训练实践

发布时间:2026/10/1 3:07:17来源:尧图网络
鱼数据集VOC与YOLO格式解读及YOLOv8训练实践
简介面向目标检测与鱼类识别任务该数据集包含31个鱼种、共2798张图像的多类别标注适合算法学习者、渔业智能化项目开发者以及需要现成训练数据的入门者使用。压缩包约109.1MB共2000个文件主体为1999个XML标注文件可对应VOC格式的目标框与类别信息另含说明txt便于了解目录结构与标注规则文件以xyxr_fish_编号命名方便按图片索引与批量处理。作为VOC风格标注XML会记录图像尺寸、目标类别及边界框坐标可直接解析或转换为YOLO等训练格式。标注类别涵盖Bangus、Big Head Carp、鲶鱼、鲤鱼、金鱼、丝足鲈等31类覆盖常见养殖、观赏与野生鱼种类别粒度较细可以用于检测、分类两类任务的模型训练与误差分析。目前已有417人浏览学习适合需要标准标注数据、希望节省手工注释时间的目标检测研究者与工程开发人员。1. 鱼数据集2798张31个种类分类检测VOCYOLO格式这个数据集到底能做什么做目标检测的都知道公开数据集不缺缺的是能直接拿去训练、标注干净、类别还够细的业务数据。鱼数据集2798张31个种类分类检测VOCYOLO格式这个包解决的正是我要做鱼类识别/鱼种分类但不想从零标数据的痛点。2798张图覆盖31个鱼种每张图都带VOC和YOLO两套标注拿过来可以直接跑训练也能用来做检测模型的迁移学习基座。适合三类人刚入门目标检测、拿现成数据练手的初学者做渔业、水产养殖监测的开发者还有需要细粒度分类场景做模型选型对比的工程师。我拿到这个包的第一件事不是看图片而是先把标注文件从头到尾查了一遍——数据集能不能用标注决定一大半。2. 读懂鱼数据集的VOC与YOLO双格式文件结构、标注字段与坐标换算2.1 目录结构与文件清单先摸清楚包里有什么压缩包解开之后典型的目标检测数据集目录长这样VOC格式和YOLO格式各自独立成目录。VOC那边是JPEGImages、Annotations、ImageSets三个子目录JPEGImages放原始图片Annotations放XML标注文件ImageSets/Main里是train.txt、val.txt这些划分文件。YOLO那边是images和labels两个目录图片与同名txt一一对应。这套结构与Pascal VOC官方数据集、YOLO官方仓库的预期输入保持一致后续接任何训练框架都不用改目录结构。# 解压后建议先跑一遍目录核对确认文件数量对得上 tar -xzf 鱼数据集2798张31个种类分类检测VOCYOLO格式.zip find . -type f | wc -l find . -name *.jpg | wc -l find . -name *.xml | wc -l find . -name *.txt | wc -l这里有个血泪经验下载来的数据集解压后第一件事永远是数文件不要直接开训练。图片数量、XML数量、txt数量三条线对不齐说明有漏标或者漏图。我见过一个数据集图片有3000张XML少了200份训练时YOLO直接报错说找不到标注文件排查了半天。另外注意VOC的ImageSets/Main下面可能同时有train.txt、val.txt、trainval.txt如果包里只给了全量划分训练前要自己重新切。VOC格式的train.txt里面存的是不带扩展名的图片文件名YOLOv8训练时用不了这个需要转成图片路径或者重新划分。2.2 VOC的XML标注到底存了什么解析bndbox与object字段VOC格式的标注核心是XML文件里嵌套的object节点。每一个object代表图中一个鱼实例里面最关键的是name标签鱼种名称和bndbox子节点xmin、ymin、xmax、ymax四个坐标。这四个值是像素绝对坐标左上角为原点x向右增大y向下增大。做检测训练前需要把这四个值读出来换算成YOLO需要的归一化中心坐标与宽高。import xml.etree.ElementTree as ET def parse_voc_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) objects [] for obj in root.iter(object): name obj.find(name).text box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) objects.append({name: name, bbox: [xmin, ymin, xmax, ymax]}) return img_w, img_h, objects这段代码把XML里的图片宽高和每个鱼的目标框读进内存。注意size字段必须读后续YOLO坐标归一化要用。有些数据集标注不规范size字段可能缺失或者写错这时候要自己用PIL或者OpenCV读一遍真实图片尺寸来兜底。我一般会加一道校验bndbox的xmax不能超过img_wymax不能超过img_h一旦有越界要么标注坐标有问题要么图片被resize过但XML没同步更新。2.3 把VOC坐标转成YOLO格式归一化换算与txt写入YOLO格式的核心是把绝对像素坐标转换成相对坐标。每个目标占一行格式是class_id x_center y_center width height四个坐标值都归一化到0到1之间。x_center和y_center是目标框中心点坐标width和height是框的宽高全部除以图片宽高。class_id是从0开始的整数对应names列表里的索引VOC里存的是鱼种名称字符串需要先映射成数字。def voc_to_yolo(img_w, img_h, objects, class_map, out_txt): lines [] for obj in objects: name obj[name] if name not in class_map: print(f[WARN] 未知类别 {name}跳过) continue class_id class_map[name] xmin, ymin, xmax, ymax obj[bbox] x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) box_w min(max(box_w, 0.0), 1.0) box_h min(max(box_h, 0.0), 1.0) lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))参数说明class_map是鱼种名称到数字ID的映射字典必须和后面训练用的data.yaml里names顺序完全一致否则类别就错位了。归一化后的坐标micro数值很小保留六位小数足够。min/max的clip操作是为了防止标注越界导致训练时报错——如果某个框的xmax超过图片宽度归一化后width可能大于1YOLO训练时这种目标会被直接过滤掉造成有效样本白白流失。这里有个易错点VOC的坐标是整数但归一化后是浮点转换脚本不要做四舍五入取整直接保留浮点精度。3. 31个鱼种分类数据体检类别分布、目标尺度与训练集划分3.1 统计每个鱼种的图片数量发现类别不平衡2798张图分31个类平均每类90张左右但真实分布几乎不可能这么均匀。有些鱼种可能有三四百张有些可能只有二三十张。训练前必须把这个分布摸清楚否则模型会严重偏向样本量大的鱼种小样本类别的AP平均精度可能趋近于零。import os from collections import Counter voc_ann_dir Annotations name_counter Counter() # 统计方式一直接数XML里每个object的name for xml_file in os.listdir(voc_ann_dir): xml_path os.path.join(voc_ann_dir, xml_file) img_w, img_h, objects parse_voc_xml(xml_path) for obj in objects: name_counter[obj[name]] 1 for name, cnt in name_counter.most_common(): print(f{name}: {cnt} 个实例)统计维度要区分图片数和实例数。一图多鱼很常见如果一张图里有三条同种鱼实例数加了3但图片数只加了1。YOLO训练时实际关心的是实例数因为每个标注框都会参与损失计算。实例数少于30的鱼种要标记为高风险类后面训练参数需要单独调整。统计完分布后需要把结果保存成CSV格式方便后续对照训练日志。这个操作也顺便能发现标注错误——比如某类突然出现一个离谱的实例数峰值或者出现了31类以外的未知类别名都是标注文件有问题的信号。3.2 分析目标框尺寸分布为imgsz参数提供依据鱼在图片里往往不是均匀分布的。近景的养殖池图片鱼可能占画面三分之一水下监控拍的鱼可能只有几十个像素。目标框的宽高分布直接决定训练时的输入分辨率设置。目标框普遍偏小imgsz用640会导致小目标特征在downsample后丢失这时候就要考虑把imgsz拉到960甚至1280。import numpy as np def compute_box_stats(voc_ann_dir): all_boxes [] for xml_file in os.listdir(voc_ann_dir): xml_path os.path.join(voc_ann_dir, xml_file) img_w, img_h, objects parse_voc_xml(xml_path) for obj in objects: xmin, ymin, xmax, ymax obj[bbox] box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h all_boxes.append((box_w, box_h)) arr np.array(all_boxes) print(f目标框归一化宽度均值{arr[:,0].mean():.3f}中位数{np.median(arr[:,0]):.3f}) print(f目标框归一化高度均值{arr[:,1].mean():.3f}中位数{np.median(arr[:,1]):.3f}) print(f小于0.05宽度的框占比{(arr[:,0] 0.05).mean()*100:.1f}%)参数说明归一化宽高中位数如果小于0.1说明超过一半的鱼目标在图中占比不到10%属于中小目标场景。这类数据用YOLOv8的话建议把imgsz设到960起步或者使用YOLOv8的P2输出层ultralytics版本支持通过scale参数调整。输出了这个统计之后还要关注极端情况——有些框的宽度占比可能是0.8说明是特写镜头这种超大目标和小目标混在一起模型训练时要靠Mosaic增强和Multi-scale训练来平衡。3.3 划分训练集与验证集先划分再训练不要交给框架目标检测训练集划分有一个关键原则先划分再训练。不要偷懒直接把全量数据丢给YOLO让它自己切验证集。尤其是这个数据集是2798张31个种类这种偏业务场景的包鱼种分布天然不均随机划分容易把某个鱼种全部分到训练集验证集里缺了这一类指标会虚高但实际泛化不行。import random from collections import defaultdict def split_dataset_by_class(ann_dir, train_ratio0.8, seed42): random.seed(seed) class_to_files defaultdict(list) for xml_file in os.listdir(ann_dir): xml_path os.path.join(ann_dir, xml_file) img_w, img_h, objects parse_voc_xml(xml_path) class_names set(obj[name] for obj in objects) for cls in class_names: class_to_files[cls].append(xml_file) # 注意这里不是直接划分而是记录每个类别的文件归属后续按图片级去重 train_files set() val_files set() for cls, files in class_to_files.items(): random.shuffle(files) split_point max(1, int(len(files) * train_ratio)) for f in files[:split_point]: train_files.add(f) for f in files[split_point:]: val_files.add(f) return train_files, val_files这里有一个容易被忽略的坑一张图片可能同时包含多个鱼种如果它含有A和B两类A类划分时把这张图放进训练集B类划分时又可能把它放进验证集。所以要按图片级去重——先统计每张图片涉及哪些类别最后判断归属时只要这张图被任一类别划到训练集就整体归训练集或者更严格的做法是优先保证类别覆盖面。对于这个鱼数据集我建议的做法是先把31个类别按实例数排序小样本类少于50实例全部优先放入训练集再从大样本类里按比例补齐验证集。验证集至少要覆盖全部31个鱼种每个鱼种至少留5个实例来评估。4. 用YOLOv8跑通鱼数据集训练data.yaml配置、命令与参数调整4.1 准备data.yaml与目录文件命名空间、路径与类别顺序拿到YOLO格式的鱼数据集后训练前的准备工作集中在data.yaml和目录整理两件事。data.yaml是YOLO系列的灵魂文件它告诉训练器去哪里读图片、去哪里读标注、一共有多少类、各类别叫什么名字。这个文件写错一个字段训练能启动但结果会莫名其妙最常见的就是names顺序和txt里的class_id对不上。# fish.yaml path: /data/fish_dataset # 数据集根目录用绝对路径最省心 train: images/train # 训练集图片目录相对于path val: images/val # 验证集图片目录 nc: 31 # 类别总数 names: [ class_00, class_01, class_02, class_03, class_04, class_05, class_06, class_07, class_08, class_09, class_10, class_11, class_12, class_13, class_14, class_15, class_16, class_17, class_18, class_19, class_20, class_21, class_22, class_23, class_24, class_25, class_26, class_27, class_28, class_29, class_30 ]这里names列表我用的是占位符实际使用时要替换成压缩包内标注的真实鱼种名称。注意一个细节names列表的顺序必须和txt标注里的class_id完全一致class_id是0到30对应names列表里的第1到第31个元素。很多新手在这里翻车——解压数据集后自己把images重新整理过labels也跟着移了但名称没同步结果训练时图片和标注文件配对不上。另外path字段建议写绝对路径因为YOLOv8在训练时如果当前工作目录不同相对路径会解析错。data.yaml文件本身可以放在任意位置训练命令里引用它的路径即可。4.2 YOLOv8训练命令从预训练权重开始还是从头训练鱼数据集有2798张图说多不多说少不少。用COCO预训练权重做迁移学习是性价比最高的路线——YOLOv8默认会自动下载yolov8n.pt、yolov8s.pt这些预训练模型特征提取层已经学到了通用的边缘、纹理、形状特征鱼的鳞片纹理、鱼鳍轮廓这些底层特征不需要从零学。只有在数据量极大十万张级别或者目标域极其特殊时才考虑从头训练。# 使用yolov8s模型输入尺寸960训练150轮 yolo detect train \ datafish.yaml \ modelyolov8s.pt \ epochs150 \ imgsz960 \ batch16 \ lr00.01 \ lrf0.01 \ seed42 \ workers8 \ projectfish_experiment \ namefish_yolov8s_960参数说明imgsz960是基于前面目标框尺寸统计的结论——如果鱼目标偏小640的输入会让小目标在特征图中只剩几个像素。batch16要看显卡显存12GB显存跑yolov8s加960输入batch再往上加容易OOM。lr0是初始学习率迁移学习场景0.01是安全起点如果训练日志里loss剧烈震荡就降到0.005。epochs150对2798张图的量级足够配合Mosaic增强和cosine学习率衰减一般到100轮左右mAP50就会收敛。workers是数据加载线程数Windows下建议改成0或2Linux下可以开大一些。4.3 训练过程的监控与中断恢复怎么判断模型在往好的方向走训练一旦启动不要干等。YOLOv8会在project/name目录下实时写训练日志和权重文件。看train_batch*.jpg可以直观检查mosaic增强后的图片是否正常看results.csv里每一轮的metrics重点盯val的mAP50和mAP50-95两条曲线的走势。如果mAP50在前20轮快速爬升然后平缓这是正常形态如果30轮后还在大起大落说明学习率设置有问题——初始学习率过高会在损失面上震荡。# 查看训练日志的关键指标每5轮输出一次均值 tail -f fish_experiment/fish_yolov8s_960/results.csv # 中断后从断点恢复训练 yolo detect train \ datafish.yaml \ modelfish_experiment/fish_yolov8s_960/weights/last.pt \ epochs200 \ resumeTrue训练途中如果发现数据划分有问题或者需要调整参数不用从头开始。用last.pt断点续训可以保留已经学到的权重只修改epochs或者lr继续跑。我一般的操作节奏是先用yolov8s跑一版baseline记录mAP50和mAP50-95然后换成yolov8m或yolov8l提精度上限最后固定模型规模做一次超参数微调。这里注意resumeTrue时不需要再传data.yaml模型权重里已经记住了数据集配置。5. 鱼数据集训练的避坑指南5个最容易翻车的地方5.1 图片文件名与标注文件名错位导致的漏检现象训练正常跑但训练日志里skipping object loss或者验证时鱼目标大量漏检单类AP剧烈波动。原因这个数据集同时提供VOC和YOLO格式很多人解压后手动整理目录时把图片重命名过比如加了前缀但labels目录里的txt没跟着改。YOLO训练时images和labels通过同名配对机制匹配——图片叫fish_001.jpg就去找fish_001.txt找不到就跳过该图。如果全图都被跳过模型等于没学到任何东西。解决写一段校验脚本遍历images目录下每张图片检查labels目录下是否存在同名txt并报告缺失数量。这个步骤必须在训练前做不要信压缩包解压就能用这种话。我见过有人训练完一轮loss一直不降最后发现600张图片的标注文件全部因为改名对不上模型在纯黑背景上学了个寂寞。5.2 类别编号错位导致的预测正确但标签错误现象训练loss正常下降验证mAP也好看但实际推理时发现模型输出的鱼种名称和标注对不上比如把带鱼识别成鲈鱼而且置信度很高。原因VOC转YOLO时class_map字典的排序和data.yaml里names的排序不一致。比如VOC里带鱼在XML中排在第一位你给它分配class_id0但data.yaml里names第一个元素写的却是鲈鱼。模型学习的是class_id0对应某种视觉特征推理输出时你用names去解释自然错位。这个问题最隐蔽因为你只看loss和mAP根本发现不了。解决写一个幂等校验脚本。随机抽5张图读取VOC XML里的name字段读取对应YOLO txt里的class_id再查data.yaml里names[class_id]是否和XML里的name一致。确保这5张校验全部通过。注意class_map的生成规则要固定建议按鱼种名称的字典序排序生成映射并在data.yaml里用同一个脚本输出names从源头保证一致。5.3 小样本鱼种的AP为0类别不平衡的典型表现现象训练完看per-class结果样本量大的鱼种mAP50能达到0.85以上某个只有20张图片的鱼种AP直接是0模型完全学不会。原因31个鱼种分布不均YOLO默认对所有类别等权训练。小样本类别在每轮epoch里只出现两三次Mosaic增强和随机翻转后有效样本更少梯度贡献被大样本类淹没。20张的样本量连shuffle后分成batch都不够模型很难学到该鱼种的判别性特征。解决优先保证小样本类的图片全部用于训练验证集从大样本类里出训练时开启YOLOv8的class weights按类别实例数的倒数给loss加权对小样本类做离线增强比如复制粘贴目标把小鱼实例粘贴到其他图片的背景区域增加每轮出现的次数。注意增强后的图片要重新生成标注不要直接改原图。5.4 验证集划分不当导致指标虚高现象训练时mAP50显示0.93肉眼检测效果也凑合但换了一批真实场景图片测试mAP直接掉到0.4。原因这个数据集来自真实采集同一个鱼塘或者同一批鱼的视频抽帧不同帧之间背景高度相似。随机划分训练集和验证集时训练集里可能包含某条鱼的画面验证集里也有它的不同角度帧模型在验证集上见过这条鱼相当于开卷考试。解决按数据来源分组——如果压缩包目录本身按视频或场景组织了子目录按照场景划分而不是按图片划分如果没有场景信息用聚类方法按图片的相似度颜色直方图或者特征向量分组再划分train/val。另一个补救办法是验证时用baseline模型在val上跑一遍记录每张图的检测置信度找出置信度异常高的图片确认是否存在数据泄露。5.5 yolo训练loss为NaN学习率和梯度问题现象训练第一个epoch loss就是nan或者跑到第20轮突然变成nan之后权重全部废掉。原因最常见的是学习率过高导致梯度炸掉尤其在迁移学习阶段前几轮预训练权重和鱼数据分布差异大梯度爆炸概率不低。另一个隐藏原因是标注坐标出现负数或者宽高为0归一化后产生无效值模型计算损失时取对数导致的nan。解决把初始学习率从0.01降到0.001batch也跟着减半检查全部标注txt有没有class_id大于30的行有没有x_center为负数或者width为0的目标框。加一个清洗脚本把非法标注行直接过滤掉不要试图修正标注本身有问题修正出来的坐标也是错的。通常清洗完标注再做训练nan就消失了。6. 用混淆矩阵和难例分析优化鱼种分类从mAP数字到可解释性训练跑出不错的mAP只是上半场真正考验模型的是那些长得像的鱼种——比如两种鲳科鱼外观几乎一样模型把A认成B是视觉特征太接近不是模型不行。这时候要看混淆矩阵和难例图片针对性地调整数据或者策略。YOLOv8训练结束后在results目录下会自动生成confusion_matrix.png。这张图是31乘31的矩阵横轴是真实类别纵轴是预测类别对角线越亮越好。重点关注对角线附近非零的格子比如第5行第7列突然有个亮点说明第5类鱼经常被误判成第7类。再把误判的图片抽出来看如果两类鱼在颜色、纹理上确实接近常规做法是把这两类合并成一个超类如果人眼能明显区分说明模型特征提取不够细需要换更大的模型或者用更高分辨率输入。另一个实用技巧是跑一遍val集推理把预测置信度在0.25到0.75之间的边界样本全部导出这些是勉强识别的模棱两可样本。逐张看这些样本你会发现它们要么是目标被遮挡要么是光线极差要么是鱼在快速游动导致运动模糊。针对这三类难例思路是遮挡样本可以通过增加部分遮挡数据增强来模拟光线差的样本引入亮度扰动和对比度变换运动模糊样本追加少量高斯模糊增强。这些都不用重新标数据改增强策略就能让边界样本向高置信度区域移动。# 检查混淆矩阵是否存在确认训练输出完整 ls fish_experiment/fish_yolov8s_960/ | grep confusion训练收敛后我会养成的习惯是把每类鱼的AP单独排序从AP最低的类开始倒序优化而不是一次把所有类都调一遍。低AP类先看出错模式是误检到背景还是和其他类混淆不同的出错模式对应完全不同的优化动作。误检到背景说明模型把背景纹理学进去了需要检查标注框是否贴得太紧和其他类混淆上面已经说了看混淆矩阵。这样一轮一轮地针对单类调参数比盲目改全局学习率或者加数据量要高效得多。这个数据集2798张的体量配合上面的排查流程足够支撑一个可靠的水产鱼类识别基线模型后续如果效果还不够优先补低AP类的图片而不是平均地加数据——数据预算花在刀刃上效率高得多。希望这篇拆解能帮你把这个鱼数据集用起来少走点我当初踩过的弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

《UDS协议从入门到精通》系列——图解0x37:请求退出传输 2026/10/1 7:24:48

《UDS协议从入门到精通》系列——图解0x37:请求退出传输

《UDS协议从入门到精通》系列——图解0x37:请求退出传输 一、简介 二、数据包格式 2.1 服务请求格式 2.2 服务响应格式 2.2.1 肯定响应 2.2.2 否定响应 三、通信示例 Tip📌:本文描述中但凡涉及到其他UDS服务的,均提供专栏内文章链接跳转方式以便快速了解他们。 学习UDS基础…

阅读更多 →
键合设备赋能半导体封测与打样实验室协同 2026/10/1 7:24:34

键合设备赋能半导体封测与打样实验室协同

当前半导体封装环节最受关注的问题,不是有没有设备,而是键合设备在半导体行业应用中如何匹配多材料、多工艺的复杂需求,以及芯片打样联合研发实验室能否真正帮中小团队把试错成本压下来。这两个问题的交集,恰恰是功率器件与先进封…

阅读更多 →
Cortex-M中断里用FPU的陷阱:嵌套抢占如何悄悄踩坏浮点上下文 2026/10/1 7:24:34

Cortex-M中断里用FPU的陷阱:嵌套抢占如何悄悄踩坏浮点上下文

做嵌入式这些年,带FPU的MCU我用了不少,FPU确实香,但也是一颗不拆开看就不知道会踩雷的甜瓜。前阵子一个量产项目在最后测试阶段冒出一个偶发故障:系统运行中,运动控制模块的输出偶尔会出现毛刺,大负载、小负…

阅读更多 →
Unity MCP 插件小白教程:7 步用 TaoToken 配置 AI 游戏开发环境 2026/10/1 7:24:34

Unity MCP 插件小白教程:7 步用 TaoToken 配置 AI 游戏开发环境

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
大模型评测【行业应用篇】教育行业|高中学科考试实测:用TaoToken统一Key跑通多模型对比 2026/10/1 7:24:33

大模型评测【行业应用篇】教育行业|高中学科考试实测:用TaoToken统一Key跑通多模型对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
沈阳口碑好的无隐形收费全屋定制公司,尚品隆宸客户口碑力荐 2026/10/1 7:24:26

沈阳口碑好的无隐形收费全屋定制公司,尚品隆宸客户口碑力荐

辽宁尚品隆宸整体定制家居有限公司,是深耕沈阳全屋定制行业20年的本地源头工厂,土生土长扎根本土市场,深度熟悉沈阳本地户型结构、气候环境以及居民居住生活习惯,摒弃中间商转包模式,凭借多年本土深耕经验与良好口碑&a…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉