当前位置: 首页 > news >正文

【完整源码+数据集+部署教程】【智慧工地监控】建筑工地设备分割系统: yolov8-seg-efficientViT

背景意义

研究背景与意义

随着城市化进程的加快,建筑行业面临着越来越多的挑战,包括安全隐患、资源浪费和环境污染等问题。为了提高建筑工地的管理效率和安全性,智慧工地的概念应运而生。智慧工地利用物联网、人工智能等先进技术,实现对建筑工地的实时监控与管理。设备分割作为智慧工地监控系统中的重要组成部分,能够有效识别和定位工地上的各种设备和人员,从而为工地的安全管理和资源调配提供重要支持。

在众多的计算机视觉技术中,基于深度学习的目标检测与分割技术近年来取得了显著进展。YOLO(You Only Look Once)系列模型因其高效的实时性和准确性,成为目标检测领域的热门选择。YOLOv8作为该系列的最新版本,进一步提升了模型的性能,尤其在小目标检测和复杂场景下的表现上有了显著改善。然而,针对建筑工地这一特定场景,YOLOv8的标准模型仍然存在一些不足之处,如对不同设备和人员的细粒度分割能力不足、在复杂背景下的识别准确率不高等。因此,改进YOLOv8以适应建筑工地设备分割的需求,具有重要的研究价值和实际意义。

本研究基于改进YOLOv8,构建一个针对建筑工地设备的分割系统,旨在通过对工地上各种设备(如起重机、挖掘机、混凝土搅拌机等)和人员(如工人、司机等)的精准识别与分割,实现对工地动态状态的实时监控。我们将使用一个包含2700张图像和24个类别的数据集,涵盖了建筑工地上常见的设备和人员。这一数据集的多样性和丰富性为模型的训练和测试提供了良好的基础,能够有效提升模型在实际应用中的表现。

通过对YOLOv8的改进,我们将重点关注以下几个方面:首先,优化模型的特征提取能力,以提高对不同设备和人员的识别精度;其次,增强模型在复杂背景下的鲁棒性,确保在各种光照和天气条件下均能保持较高的识别准确率;最后,结合实时数据处理技术,实现对工地动态状态的实时监控与反馈。这些改进将为建筑工地的安全管理提供更为可靠的技术支持,帮助管理者及时发现潜在的安全隐患,降低事故发生的风险。

综上所述,基于改进YOLOv8的智慧工地监控建筑工地设备分割系统,不仅具有重要的理论研究价值,也为实际工程应用提供了切实可行的解决方案。通过这一研究,我们希望能够推动建筑行业的智能化进程,提高工地管理的效率和安全性,为实现可持续发展的建筑行业贡献力量。

图片效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据集信息

数据集信息展示

在构建一个高效的建筑工地设备分割系统时,数据集的选择与构建至关重要。本项目所使用的数据集名为“consolidate_all”,它专门为改进YOLOv8-seg模型在智慧工地监控中的应用而设计。该数据集涵盖了12个不同的类别,旨在为模型提供丰富的训练样本,以实现对建筑工地上各种设备和人员的精准识别与分割。

“consolidate_all”数据集的类别包括:水泥搅拌机(cement-mixer)、起重机(crane)、挖掘机(excavator)、安全帽(helmet)、人类(human)、货车(lorry)、未佩戴安全帽的工人(no-helmet)、未穿安全背心的工人(no-safety-vest)、皮卡车(pick-up)、安全背心(safety-vest)、拖车(trailer)以及卡车(truck)。这些类别不仅涵盖了建筑工地上常见的机械设备,还包括了与工人安全相关的个人防护装备(PPE),如安全帽和安全背心。通过对这些类别的细致划分,数据集能够为模型提供全面的上下文信息,帮助其在复杂的工地环境中做出更为准确的判断。

在数据集的构建过程中,研究团队注重了数据的多样性与代表性,确保每个类别都有足够的样本量以支持模型的训练。这些样本不仅包括不同角度、不同光照条件下的图像,还涵盖了多种工地场景,力求在训练过程中使模型能够适应各种可能的实际情况。此外,数据集中的标注信息经过严格审核,确保每个图像中的物体都被准确标记,从而为模型的学习提供高质量的训练数据。

在实际应用中,智慧工地监控系统的目标是通过实时监测和分析工地上的设备与人员活动,提升工地的安全性与效率。借助“consolidate_all”数据集,改进后的YOLOv8-seg模型能够快速识别并分割出不同的设备和工人,实时反馈工地的安全状态。例如,当系统检测到某个工人未佩戴安全帽或安全背心时,能够及时发出警报,提醒相关人员采取措施,降低事故发生的风险。

此外,数据集的设计还考虑到了模型的可扩展性。随着工地监控技术的不断发展,未来可能会引入更多的类别,例如新型建筑设备或其他类型的个人防护装备。数据集的灵活性使得研究人员能够方便地添加新类别,保持模型的更新与适应性。

总之,“consolidate_all”数据集为改进YOLOv8-seg的建筑工地设备分割系统提供了坚实的基础。通过丰富的类别设置和高质量的标注数据,该数据集不仅能够提升模型的识别精度,还能在实际应用中有效保障工人的安全,推动智慧工地的建设与发展。随着数据集的不断完善与模型的优化,未来的建筑工地将更加智能化与安全化。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

核心代码

以下是代码中最核心的部分,并附上详细的中文注释:

from collections import defaultdict
import cv2
from shapely.geometry import Polygon
from shapely.geometry.point import Point

class ObjectCounter:
“”“一个用于管理实时视频流中对象计数的类,基于它们的轨迹进行计数。”“”

def __init__(self):"""初始化计数器,设置各种跟踪和计数参数的默认值。"""self.is_drawing = False  # 是否正在绘制区域self.selected_point = None  # 当前选中的点self.reg_pts = None  # 计数区域的点self.counting_region = None  # 计数区域的多边形self.in_counts = 0  # 进入计数self.out_counts = 0  # 离开计数self.counting_list = []  # 当前计数的对象列表self.track_history = defaultdict(list)  # 轨迹历史记录self.track_thickness = 2  # 轨迹线的厚度self.draw_tracks = False  # 是否绘制轨迹def set_args(self, classes_names, reg_pts, region_color=None, line_thickness=2, track_thickness=2, view_img=False, draw_tracks=False):"""配置计数器的图像、边界框线厚度和计数区域点。Args:classes_names (dict): 类别名称reg_pts (list): 定义计数区域的初始点列表region_color (tuple): 区域线的颜色line_thickness (int): 边界框的线厚度track_thickness (int): 轨迹的厚度view_img (bool): 控制是否显示视频流的标志draw_tracks (bool): 是否绘制轨迹"""self.reg_pts = reg_pts  # 设置计数区域的点self.counting_region = Polygon(self.reg_pts)  # 创建计数区域的多边形self.names = classes_names  # 设置类别名称self.region_color = region_color if region_color else (255, 255, 255)  # 设置区域颜色def extract_and_process_tracks(self, tracks):"""提取并处理对象轨迹。Args:tracks (list): 从对象跟踪过程中获得的轨迹列表。"""boxes = tracks[0].boxes.xyxy.cpu()  # 获取边界框坐标clss = tracks[0].boxes.cls.cpu().tolist()  # 获取类别track_ids = tracks[0].boxes.id.int().cpu().tolist()  # 获取轨迹IDfor box, track_id, cls in zip(boxes, track_ids, clss):# 计算当前对象的中心点track_line = self.track_history[track_id]track_line.append((float((box[0] + box[2]) / 2), float((box[1] + box[3]) / 2)))track_line.pop(0) if len(track_line) > 30 else None  # 限制轨迹长度# 计数对象if self.counting_region.contains(Point(track_line[-1])):  # 检查对象是否在计数区域内if track_id not in self.counting_list:  # 如果对象尚未计数self.counting_list.append(track_id)  # 添加到计数列表if box[0] < self.counting_region.centroid.x:  # 判断对象是进入还是离开self.out_counts += 1  # 离开计数增加else:self.in_counts += 1  # 进入计数增加def start_counting(self, im0, tracks):"""启动对象计数过程的主函数。Args:im0 (ndarray): 当前视频流的帧。tracks (list): 从对象跟踪过程中获得的轨迹列表。"""self.im0 = im0  # 存储当前图像if tracks[0].boxes.id is None:  # 如果没有检测到对象returnself.extract_and_process_tracks(tracks)  # 提取并处理轨迹

代码核心部分说明:
ObjectCounter类:该类用于管理对象计数的逻辑,包括初始化、设置参数、处理轨迹和计数等功能。
初始化方法:设置初始状态和计数参数。
set_args方法:配置计数器的参数,包括类别名称、计数区域和显示选项。
extract_and_process_tracks方法:提取轨迹信息并进行计数,判断对象是否在计数区域内,并更新计数。
start_counting方法:启动计数过程,处理每一帧图像和对应的轨迹信息。
这个程序文件定义了一个名为 ObjectCounter 的类,主要用于在实时视频流中管理物体的计数。该类利用了计算机视觉技术,结合了对象检测和跟踪的功能,以便在指定的区域内对物体进行计数。

在初始化方法 init 中,类的属性被设置为默认值。这些属性包括用于鼠标事件的标志、计数区域的信息、图像和注释的信息、物体计数的信息、跟踪历史等。具体来说,is_drawing 和 selected_point 用于处理鼠标绘制区域的事件,reg_pts 存储计数区域的点,counting_region 是一个多边形对象,表示计数区域的形状。

set_args 方法用于配置计数器的参数,包括类名、计数区域的点、区域颜色、线条厚度等。这个方法使得用户可以灵活地设置计数器的行为和外观。

mouse_event_for_region 方法处理鼠标事件,以便用户可以通过鼠标在视频流中绘制和调整计数区域。当用户按下鼠标左键时,程序会检查鼠标位置是否接近计数区域的某个点,如果是,则开始绘制。移动鼠标时,如果正在绘制,更新选定点的位置。松开鼠标左键时,停止绘制。

extract_and_process_tracks 方法是主要的处理逻辑。它从传入的跟踪数据中提取边界框、类别和跟踪ID,并使用 Annotator 类进行注释和绘制。该方法会检查每个物体的中心点是否在计数区域内,并根据物体的进入或离开更新计数。计数的结果会被存储在 in_counts 和 out_counts 中。

如果设置了 view_img 为真,程序会在窗口中显示当前帧和计数结果,同时允许用户通过鼠标交互来调整计数区域。窗口的关闭可以通过按下 ‘q’ 键来实现。

start_counting 方法是计数过程的主入口。它接收当前帧和跟踪数据,并调用处理函数进行物体计数。

最后,在文件的主程序部分,创建了 ObjectCounter 的实例,表明该类可以被直接运行。这个程序文件整体上提供了一个完整的框架,用于在视频流中实时计数物体,并允许用户动态调整计数区域。

11.5 ultralytics\cfg_init_.py
以下是代码中最核心的部分,并附上详细的中文注释:

def cfg2dict(cfg):
“”"
将配置对象转换为字典,无论它是文件路径、字符串还是SimpleNamespace对象。

参数:cfg (str | Path | dict | SimpleNamespace): 要转换为字典的配置对象。返回:cfg (dict): 配置对象的字典格式。
"""
if isinstance(cfg, (str, Path)):cfg = yaml_load(cfg)  # 从文件加载字典
elif isinstance(cfg, SimpleNamespace):cfg = vars(cfg)  # 转换为字典
return cfg

def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):
“”"
从文件或字典加载并合并配置数据。

参数:cfg (str | Path | Dict | SimpleNamespace): 配置数据。overrides (str | Dict | optional): 以文件名或字典形式的覆盖项。默认为None。返回:(SimpleNamespace): 训练参数命名空间。
"""
cfg = cfg2dict(cfg)# 合并覆盖项
if overrides:overrides = cfg2dict(overrides)if 'save_dir' not in cfg:overrides.pop('save_dir', None)  # 忽略特殊覆盖键check_dict_alignment(cfg, overrides)cfg = {**cfg, **overrides}  # 合并cfg和覆盖字典(优先使用覆盖项)# 特殊处理数字类型的项目/名称
for k in 'project', 'name':if k in cfg and isinstance(cfg[k], (int, float)):cfg[k] = str(cfg[k])
if cfg.get('name') == 'model':  # 将模型赋值给'name'参数cfg['name'] = cfg.get('model', '').split('.')[0]LOGGER.warning(f"WARNING ⚠️ 'name=model' 自动更新为 'name={cfg['name']}'.")# 类型和值检查
for k, v in cfg.items():if v is not None:  # None值可能来自可选参数if k in CFG_FLOAT_KEYS and not isinstance(v, (int, float)):raise TypeError(f"'{k}={v}' 的类型 {type(v).__name__} 无效。 "f"有效的 '{k}' 类型是 int(例如 '{k}=0')或 float(例如 '{k}=0.5')")elif k in CFG_FRACTION_KEYS:if not isinstance(v, (int, float)):raise TypeError(f"'{k}={v}' 的类型 {type(v).__name__} 无效。 "f"有效的 '{k}' 类型是 int(例如 '{k}=0')或 float(例如 '{k}=0.5')")if not (0.0 <= v <= 1.0):raise ValueError(f"'{k}={v}' 的值无效。 "f"有效的 '{k}' 值在 0.0 和 1.0 之间。")elif k in CFG_INT_KEYS and not isinstance(v, int):raise TypeError(f"'{k}={v}' 的类型 {type(v).__name__} 无效。 "f"'{k}' 必须是 int(例如 '{k}=8')")elif k in CFG_BOOL_KEYS and not isinstance(v, bool):raise TypeError(f"'{k}={v}' 的类型 {type(v).__name__} 无效。 "f"'{k}' 必须是 bool(例如 '{k}=True' 或 '{k}=False')")# 返回实例
return IterableSimpleNamespace(**cfg)

def entrypoint(debug=‘’):
“”"
该函数是ultralytics包的入口点,负责解析传递给包的命令行参数。

该函数允许:
- 以字符串列表的形式传递必需的YOLO参数
- 指定要执行的任务,例如'detect'、'segment'或'classify'
- 指定模式,例如'train'、'val'、'test'或'predict'
- 运行特殊模式,如'checks'
- 将覆盖项传递给包的配置它使用包的默认配置并使用传递的覆盖项初始化它。
然后调用具有组合配置的CLI函数。
"""
args = (debug.split(' ') if debug else sys.argv)[1:]
if not args:  # 没有传递参数LOGGER.info(CLI_HELP_MSG)return# 处理特殊命令
special = {'help': lambda: LOGGER.info(CLI_HELP_MSG),'checks': checks.collect_system_info,'version': lambda: LOGGER.info(__version__),'settings': lambda: handle_yolo_settings(args[1:]),'cfg': lambda: yaml_print(DEFAULT_CFG_PATH),'hub': lambda: handle_yolo_hub(args[1:]),'login': lambda: handle_yolo_hub(args),'copy-cfg': copy_default_cfg}# 其他参数处理逻辑...# 运行命令
getattr(model, mode)(**overrides)  # 使用模型的默认参数运行命令# 显示帮助信息
LOGGER.info(f'💡 了解更多信息请访问 https://docs.ultralytics.com/modes/{mode}')

代码核心部分说明:
cfg2dict: 该函数用于将不同类型的配置对象(如字符串、路径或SimpleNamespace)转换为字典格式,方便后续处理。
get_cfg: 该函数负责加载和合并配置数据,并进行类型和值的检查,确保配置的有效性。
entrypoint: 这是程序的入口点,负责解析命令行参数,处理特殊命令,并根据用户输入执行相应的YOLO任务。
通过这些核心部分,代码能够灵活地处理用户输入,配置模型,并执行不同的计算机视觉任务。

这个程序文件是Ultralytics YOLO(You Only Look Once)模型的配置和命令行接口实现,主要用于深度学习任务,如目标检测、图像分割、分类和姿态估计。文件中定义了一些常量、函数和处理命令行参数的逻辑。

首先,文件导入了一些必要的库和模块,包括上下文管理、文件操作、路径处理、类型注解等。接着,定义了一些有效的任务和模式,例如训练(train)、验证(val)、预测(predict)、导出(export)、跟踪(track)和基准测试(benchmark)。同时,文件中还定义了任务与数据集、模型和评估指标之间的映射关系。

CLI_HELP_MSG是一个多行字符串,提供了命令行接口的使用说明,包括如何使用不同的任务和模式进行操作,以及示例命令。这为用户提供了清晰的指导,帮助他们理解如何与YOLO模型进行交互。

接下来,文件定义了一些键,用于配置参数的类型检查,包括浮点数、整数、布尔值等。cfg2dict函数用于将配置对象转换为字典格式,以便后续处理。get_cfg函数则用于加载和合并配置数据,支持从文件、字典或SimpleNamespace对象中获取配置,并进行类型和值的检查。

get_save_dir函数根据传入的参数生成保存目录,_handle_deprecation函数处理过时的配置键,check_dict_alignment函数检查自定义配置与基础配置之间的键匹配情况。merge_equals_args函数用于合并命令行参数中的等号分隔的键值对。

handle_yolo_hub和handle_yolo_settings函数分别处理与Ultralytics HUB和YOLO设置相关的命令行接口。parse_key_value_pair函数解析单个键值对,smart_value函数将字符串转换为相应的类型。

entrypoint函数是程序的入口点,负责解析传递给包的命令行参数。它支持传递必需的YOLO参数、指定任务和模式、运行特殊模式以及传递配置覆盖。函数内部还定义了一些特殊命令的处理逻辑,如帮助信息、版本信息、设置管理等。

最后,copy_default_cfg函数用于复制默认配置文件,并在文件名后添加“_copy”后缀。整个文件的结构清晰,功能丰富,提供了灵活的配置和命令行操作方式,使得用户能够方便地使用YOLO模型进行各种深度学习任务。

12.系统整体结构(节选)
程序整体功能和构架概括
该程序是Ultralytics YOLO(You Only Look Once)项目的一部分,主要用于目标检测和相关计算机视觉任务。整体架构分为多个模块,每个模块负责特定的功能。以下是各个模块的功能概述:

模型定义:VanillaNet.py 文件实现了一个灵活的卷积神经网络(VanillaNet),用于图像处理任务。它支持多种配置,便于用户根据需求进行调整。

工具函数:utils.py 文件提供了一些实用的工具函数,用于处理边界框的调整和计算交并比(IoU),这些功能在目标检测中非常重要。

实验记录:comet.py 文件集成了Comet.ml,用于记录和可视化训练过程中的重要信息,包括实验参数、训练指标和图像预测等。

物体计数:object_counter.py 文件实现了一个实时物体计数器,允许用户在视频流中动态设置计数区域,并对进入和离开该区域的物体进行计数。

配置管理:init.py 文件处理配置和命令行接口,支持用户通过命令行参数灵活配置模型和任务,并提供了详细的帮助信息。

文件功能整理表
文件路径 功能描述
ultralytics/nn/backbone/VanillaNet.py 定义了VanillaNet模型的结构和前向传播逻辑,支持多种配置。
ultralytics/models/fastsam/utils.py 提供了边界框调整和交并比(IoU)计算的工具函数。
ultralytics/utils/callbacks/comet.py 集成Comet.ml进行实验记录和可视化,跟踪训练过程中的指标。
ultralytics/solutions/object_counter.py 实现了实时物体计数器,允许用户动态设置计数区域并进行计数。
ultralytics/cfg/init.py 处理配置和命令行接口,支持灵活的模型和任务配置。
这个表格总结了每个文件的主要功能,展示了Ultralytics YOLO项目的模块化设计和各个组件之间的协作。

13.图片、视频、摄像头图像分割Demo(去除WebUI)代码
在这个博客小节中,我们将讨论如何在不使用WebUI的情况下,实现图像分割模型的使用。本项目代码已经优化整合,方便用户将分割功能嵌入自己的项目中。 核心功能包括图片、视频、摄像头图像的分割,ROI区域的轮廓提取、类别分类、周长计算、面积计算、圆度计算以及颜色提取等。 这些功能提供了良好的二次开发基础。

核心代码解读
以下是主要代码片段,我们会为每一块代码进行详细的批注解释:

import random
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
from hashlib import md5
from model import Web_Detector
from chinese_name_list import Label_list

根据名称生成颜色

def generate_color_based_on_name(name):

计算多边形面积

def calculate_polygon_area(points):
return cv2.contourArea(points.astype(np.float32))

绘制中文标签

def draw_with_chinese(image, text, position, font_size=20, color=(255, 0, 0)):
image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(image_pil)
font = ImageFont.truetype(“simsun.ttc”, font_size, encoding=“unic”)
draw.text(position, text, font=font, fill=color)
return cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)

动态调整参数

def adjust_parameter(image_size, base_size=1000):
max_size = max(image_size)
return max_size / base_size

绘制检测结果

def draw_detections(image, info, alpha=0.2):
name, bbox, conf, cls_id, mask = info[‘class_name’], info[‘bbox’], info[‘score’], info[‘class_id’], info[‘mask’]
adjust_param = adjust_parameter(image.shape[:2])
spacing = int(20 * adjust_param)

if mask is None:x1, y1, x2, y2 = bboxaim_frame_area = (x2 - x1) * (y2 - y1)cv2.rectangle(image, (x1, y1), (x2, y2), color=(0, 0, 255), thickness=int(3 * adjust_param))image = draw_with_chinese(image, name, (x1, y1 - int(30 * adjust_param)), font_size=int(35 * adjust_param))y_offset = int(50 * adjust_param)  # 类别名称上方绘制,其下方留出空间
else:mask_points = np.concatenate(mask)aim_frame_area = calculate_polygon_area(mask_points)mask_color = generate_color_based_on_name(name)try:overlay = image.copy()cv2.fillPoly(overlay, [mask_points.astype(np.int32)], mask_color)image = cv2.addWeighted(overlay, 0.3, image, 0.7, 0)cv2.drawContours(image, [mask_points.astype(np.int32)], -1, (0, 0, 255), thickness=int(8 * adjust_param))# 计算面积、周长、圆度area = cv2.contourArea(mask_points.astype(np.int32))perimeter = cv2.arcLength(mask_points.astype(np.int32), True)......# 计算色彩mask = np.zeros(image.shape[:2], dtype=np.uint8)cv2.drawContours(mask, [mask_points.astype(np.int32)], -1, 255, -1)color_points = cv2.findNonZero(mask)......# 绘制类别名称x, y = np.min(mask_points, axis=0).astype(int)image = draw_with_chinese(image, name, (x, y - int(30 * adjust_param)), font_size=int(35 * adjust_param))y_offset = int(50 * adjust_param)# 绘制面积、周长、圆度和色彩值metrics = [("Area", area), ("Perimeter", perimeter), ("Circularity", circularity), ("Color", color_str)]for idx, (metric_name, metric_value) in enumerate(metrics):......return image, aim_frame_area

处理每帧图像

def process_frame(model, image):
pre_img = model.preprocess(image)
pred = model.predict(pre_img)
det = pred[0] if det is not None and len(det)
if det:
det_info = model.postprocess(pred)
for info in det_info:
image, _ = draw_detections(image, info)
return image

if name == “main”:
cls_name = Label_list
model = Web_Detector()
model.load_model(“./weights/yolov8s-seg.pt”)

# 摄像头实时处理
cap = cv2.VideoCapture(0)
while cap.isOpened():ret, frame = cap.read()if not ret:break......# 图片处理
image_path = './icon/OIP.jpg'
image = cv2.imread(image_path)
if image is not None:processed_image = process_frame(model, image)......# 视频处理
video_path = ''  # 输入视频的路径
cap = cv2.VideoCapture(video_path)
while cap.isOpened():ret, frame = cap.read()......

源码文件

在这里插入图片描述

源码获取

欢迎大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

http://www.dtcms.com/a/424991.html

相关文章:

  • 沈阳市建设工程质量监督局网站dede增加手机网站
  • 网站建设项目维护与评价书施工企业主要负责人包括
  • 邯郸网站建设品牌公司苏州建设交通
  • 四大网站wordpress怎样连接数据库连接
  • BMW agent图介绍
  • 空间链接制作网站免费的黄冈网站有哪些平台可以聊天呢
  • IOT_通讯控制器(无线通讯)
  • 百度站长平台工具WordPress建站详细过程
  • git的merge与rebase的区别与操作
  • 泉州制作网站开发怎么做网页个人简介
  • 男科医院网站模板营销型网站功能表
  • 里伯公布2025年上半年财报
  • 戴尔公司网站建设特点百度推广是什么
  • oa系统网站建设江西宜春网站建设报价
  • 网站域名如何使用深圳外贸业务员工资
  • b = [1 2 3;4 5 6;7 8 9]>> b(2,2)=[ ]??? Subscripted assignme
  • 网站建设合同要交印花吗物流公司哪家便宜又好
  • 建设网络道德教育网站不包括郑州网站开发招聘
  • 攻击asp网站个人网站建设需求说明书
  • Arduino Mixly 从入门到精通教程:环境搭建
  • port link-type { access | hybrid | trunk } 概念及题目
  • 网站设计需要什么证江苏城乡建设职业学院官方网站
  • wordpress去掉版权seo网站规划
  • DevOps简介
  • 免费推广网站入口2022包装设计模板
  • 前端做网站需要学什么软件动易网站管理
  • 潍坊手机网站建设公司哪些社交网站做外贸比较好
  • 做网站花了三万块做电影网站用什么源码
  • 昆明网站建设搜王道下拉江苏做网站xlec
  • Linux sudo命令相关知识总结