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

DINOv2 + yolov8 + opencv 检测卡车的可拉拽雨覆是否完全覆盖

最近是接了一个需求咨询图像处理类的,甲方要在卡车过磅的地方装一个摄像头用检测卡车的车斗雨覆是否完全, 让我大致理了下需求并对技术核心做下预研究

开发一套图像处理软件,能够实时监控经过的卡车并判断其车斗的雨覆状态。

系统需具备以下功能:

  1. 图像采集:通过高分辨率摄像头采集卡车经过时的图像。
  2. 图像处理:对采集的图像进行处理,识别车斗及雨覆的具体位置。
  3. 状态判断
    • 判断雨覆是否完全覆盖车斗。
    • 在雨覆未完全覆盖时,生成警报或提示信息。

例如这样的图片,检测上方雨覆是否完全遮盖住

需求分析

图像采集是视频流接收,确保摄像头支持所选协议,并具备高清分辨率(至少1080p)以提高图像识别的准确性。摄像头应具备良好的低光性能,以适应不同的环境光照条件。

  • 使用开源媒体框架(如 FFmpegGStreamer)来接收和处理视频流。
  • 实现视频流的解码,提取每一帧图像供后续处理。

所以在技术预研上直接从图片开始, 目测了下需要使用图像语义分割再在分割图像基础上再计算雨覆的遮盖率,会使用到的工具具体有

导入必要的库,用于深度学习(PyTorch)、图像处理(PIL、OpenCV)、可视化(Matplotlib)、以及 YOLOv8(Ultralytics)目标检测和 DINOv2(Transformers)语义分割。

  • PyTorch的作用
    • 提供核心深度学习功能,如 torch.nn 用于定义 DINOv2 分割模型(DINOv2ForSegmentation 类)。
    • 通过 torch.device 确定设备(CPU 或 CUDA),将模型和数据加载到 GPU(self.device 和 self.model.to(self.device))。
    • 处理张量操作(如 torch.softmax 在 postprocess 中生成概率分布)。
  • PIL 作用:用于图像处理,支持打开、转换、调整大小和增强图像。
    • 加载和处理图像文件(如 Image.open("trunk.jpg"))。
    • 转换图像格式(如 image.convert("RGB")),调整大小(如 mask.resize),并支持数据增强(如 ImageEnhance 进行亮度、对比度、色调和饱和度调整)。
    • 创建和保存掩码或结果图像(如 Image.fromarray 和 save 方法)。
  • cv2的作用
    • 处理颜色分割(如 color_based_segmentation 使用 HSV 颜色空间分割车斗和覆盖布)。
    • 进行后处理优化,包括形态学操作(dilate、erode、morphologyEx 在 enhance_segmentation 和 color_based_segmentation 中填补空洞、去除噪声)。
    • 边缘检测(Canny 在 enhance_segmentation 中捕捉车斗边缘)和轮廓检测(findContours 填补完整轮廓)。
  • Matplotlib作用:用于数据可视化和绘图,适合生成图形和保存图像。
    • 保存分割结果的图像(如 plt.imsave 在 visualize_and_extract_regions 中保存车斗和覆盖布到黑色背景的图片)。
    • 提供可视化支持,但当前代码未直接使用 Matplotlib 绘制图表,仅用于文件保存
  • Ultralytics(YOLOv8)的作用
    • 加载预训练的 yolov8n.pt 模型(YOLO("yolov8n.pt")),检测图像中的卡车(detect_truck 函数)。
    • 返回卡车的边界框(box.xyxy),用于裁剪图像区域供 DINOv2 语义分割,确保仅在 truck 区域内分割车斗和覆盖布。
    • 设置置信度阈值(conf=0.3)以平衡检测精度和召回率。

定义类别和参数(Constants and Parameters)

CLASS_NAMES = ["background", "truck_bed", "tarp"]AUGMENTATION_PARAMS = {"brightness_factor": (0.8, 1.2),"contrast_factor": (0.8, 1.2),"rotation_range": (-30, 30),"hue_shift": (-0.1, 0.1),"saturation_factor": (0.8, 1.2),
}YOLO_CLASSES = {6: "train",7: "truck",
}

  • 作用
    • CLASS_NAMES:定义语义分割的类别(背景、车斗、覆盖布),用于 DINOv2 模型的输出和后续处理。
    • AUGMENTATION_PARAMS:设置数据增强参数,模拟亮度、对比度、旋转、色调和饱和度的变化,提高模型对不同光照、角度和颜色的泛化能力。
    • YOLO_CLASSES:定义 YOLOv8 模型的类别映射,指定类别 ID(如 7 表示 "truck"),用于检测卡车。

自定义 DINOv2 分割模型(DINOv2ForSegmentation)

class DINOv2ForSegmentation(nn.Module):def __init__(self, num_classes=3, model_name="./dinov2_base/"):# 加载 DINOv2 主干网络并冻结参数self.backbone = ViTModel.from_pretrained(model_name)hidden_size = self.backbone.config.hidden_size# 添加分割头,适配 518x518 输入self.segmentation_head = nn.Sequential(nn.Conv2d(hidden_size, 256, kernel_size=1),nn.Upsample(scale_factor=14, mode='bilinear'),nn.Conv2d(256, num_classes, kernel_size=1))for param in self.backbone.parameters():param.requires_grad = Falsedef forward(self, pixel_values):# 从 DINOv2 提取特征并通过分割头生成分割结果outputs = self.backbone(pixel_values)last_hidden = outputs.last_hidden_statefeatures = last_hidden[:, 1:].permute(0, 2, 1).view(last_hidden.size(0), -1, 37, 37)logits = self.segmentation_head(features)return logits

作用

  • 定义基于 DINOv2 的语义分割模型,使用预训练的 ViT(Vision Transformer)作为主干网络,冻结其参数以减少计算量。
  • 添加自定义分割头(segmentation_head),将 37x37 的特征图上采样并生成 3 类的分割结果(背景、车斗、覆盖布)。
  • forward 方法处理输入图像(518x518),输出分割 logits。

分割管道(SegmentationPipeline)

class SegmentationPipeline:def __init__(self, num_classes=3):# 初始化 DINOv2 模型和特征提取器self.feature_extractor = ViTFeatureExtractor.from_pretrained("./dinov2_base", size={"height": 518, "width": 518})self.model = DINOv2ForSegmentation(num_classes)self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")self.model.to(self.device)self.model.eval()def augment_image(self, image):# 应用数据增强(亮度、对比度、旋转、色调、饱和度)image = ImageEnhance.Brightness(image).enhance(random.uniform(*AUGMENTATION_PARAMS["brightness_factor"]))image = ImageEnhance.Contrast(image).enhance(random.uniform(*AUGMENTATION_PARAMS["contrast_factor"]))image = ImageEnhance.Color(image).enhance(random.uniform(*AUGMENTATION_PARAMS["saturation_factor"]))angle = random.uniform(*AUGMENTATION_PARAMS["rotation_range"])image = image.rotate(angle, expand=True, fillcolor=(0, 0, 0))return imagedef preprocess(self, image):# 预处理图像:转换为 RGB,应用增强,调整到 518x518if image.mode != "RGB":image = image.convert("RGB")augmented_image = self.augment_image(image)inputs = self.feature_extractor(images=augmented_image, return_tensors="pt", size={"height": 518, "width": 518})return inputs.pixel_values.to(self.device)def postprocess(self, logits, original_size):# 后处理:softmax 转换为概率,取最大值生成掩码,调整回原图大小probs = torch.softmax(logits, dim=1)mask = torch.argmax(probs, dim=1).squeeze().cpu().numpy()mask = Image.fromarray(mask.astype(np.uint8)).resize(original_size, Image.NEAREST)return maskdef predict(self, image, truck_bbox=None):# 在 truck 边界框内或全图进行预测if truck_bbox:cropped_image = image.crop((max(0, truck_bbox[0] - 20), max(0, truck_bbox[1] - 20),min(image.size[0], truck_bbox[2] + 20), min(image.size[1], truck_bbox[3] + 20)))else:cropped_image = imageinputs = self.preprocess(cropped_image)with torch.no_grad():logits = self.model(inputs)probs = torch.softmax(logits, dim=1)mask = self.postprocess(logits, cropped_image.size)if truck_bbox:full_mask = Image.new("L", image.size, 0)full_mask.paste(mask, (max(0, truck_bbox[0] - 20), max(0, truck_bbox[1] - 20),min(image.size[0], truck_bbox[2] + 20), min(image.size[1], truck_bbox[3] + 20)))return full_maskreturn mask

作用

  • SegmentationPipeline 封装了 DINOv2 模型的预处理、预测和后处理逻辑。
  • augment_image:通过随机变换增强图像,模拟不同光照、角度和颜色,提高模型泛化能力。
  • preprocess:将输入图像转换为 RGB,应用增强,调整到 518x518,发送到 GPU/CPU。
  • postprocess:将模型输出转换为掩码,调整回原图大小。
  • predict:根据 YOLO 检测的 truck 边界框裁剪图像进行分割,支持扩展边界(padding=20)以捕捉边缘。

可视化和提取区域(visualize_and_extract_regions)

def visualize_and_extract_regions(original_image, mask, save_base_path="output", num_classes=3):# 创建黑色背景,提取车斗和覆盖布,保存到单独图片colormap = np.array([[0, 0, 0], [255, 0, 0], [0, 255, 0]]) mask_array = np.array(mask.convert("L")).resize(original_image.size, Image.NEAREST)black_background = np.zeros((*original_image.size, 3), dtype=np.uint8)for class_id, class_name in enumerate(CLASS_NAMES[1:], 1):class_mask = (mask_array == class_id).astype(np.uint8) * 255extracted_region = black_background.copy()for i in range(3):extracted_region[:, :, i] = black_background[:, :, i] * (1 - class_mask / 255) + colormap[class_id, i] * (class_mask / 255)Image.fromarray(extracted_region).save(f"{save_base_path}_{class_name}_on_black.png")mask.save(f"{save_base_path}_mask.png")color_based_mask = color_based_segmentation(original_image)if color_based_mask:visualize_color_based_mask_on_black(original_image, color_based_mask, save_base_path + "_color_based_on_black")

作用

  • 将车斗和覆盖布提取到黑色背景的单独图片,忽略背景。
  • 调整掩码尺寸匹配原图,确保尺寸一致。
  • 保存原始掩码和颜色增强后的掩码,用于检查和调试。

YOLOv8 检测卡车(detect_truck)

def detect_truck(image_path):# 使用 YOLOv8 检测卡车,返回边界框model = YOLO("yolov8n.pt")print('yolov8n load successfully~~~')results = model(image_path, conf=0.3)for result in results:for box in result.boxes:cls = int(box.cls[0])if YOLO_CLASSES.get(cls):print('detect out:', YOLO_CLASSES.get(cls))x1, y1, x2, y2 = box.xyxy[0].tolist()return (int(x1), int(y1), int(x2), int(y2))return None
    • 加载 YOLOv8 模型(yolov8n.pt),检测图像中的卡车(类别 "truck",ID 7)。
    • 设置置信度阈值(conf=0.3),返回卡车的边界框(x1, y1, x2, y2)。

    颜色分割(color_based_segmentation)

    def color_based_segmentation(image):# 使用颜色阈值分割车斗(红、蓝、黄)和覆盖布(绿、蓝)img = cv2.cvtColor(np.array(image.convert("RGB")), cv2.COLOR_RGB2BGR)hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)mask_truck = cv2.bitwise_or(cv2.bitwise_or(cv2.inRange(hsv, [0, 120, 70], [10, 255, 255]),cv2.inRange(hsv, [170, 120, 70], [180, 255, 255])),cv2.bitwise_or(cv2.inRange(hsv, [100, 120, 70], [130, 255, 255]),cv2.inRange(hsv, [20, 120, 70], [40, 255, 255])))mask_tarp = cv2.bitwise_or(cv2.inRange(hsv, [35, 40, 40], [85, 255, 255]),cv2.inRange(hsv, [100, 40, 40], [130, 255, 255]))combined_mask = np.zeros(hsv.shape[:2], dtype=np.uint8)combined_mask[mask_truck > 0] = 1combined_mask[mask_tarp > 0] = 2kernel = np.ones((5, 5), np.uint8)return Image.fromarray(cv2.morphologyEx(cv2.morphologyEx(combined_mask, cv2.MORPH_CLOSE, kernel),cv2.MORPH_OPEN, kernel))
    • 作用

      • 使用 HSV 颜色空间分割车斗(红、蓝、黄)和覆盖布(绿、蓝),提高对颜色变化的鲁棒性。
      • 应用形态学操作(闭运算和开运算)去除噪声并填补空洞,作为 DINOv2 的补充。
      颜色分割可视化(visualize_color_based_mask_on_black)
    def visualize_color_based_mask_on_black(original_image, mask, save_path):# 将颜色分割结果提取到黑色背景colormap = np.array([[0, 0, 0], [255, 0, 0], [0, 255, 0]])mask_array = np.array(mask)black_background = np.zeros((*mask_array.shape, 3), dtype=np.uint8)for class_id in [1, 2]:class_mask = (mask_array == class_id).astype(np.uint8) * 255for i in range(3):black_background[:, :, i] = black_background[:, :, i] * (1 - class_mask / 255) + colormap[class_id, i] * (class_mask / 255)Image.fromarray(black_background).save(save_path + ".png")
    • 作用:将颜色分割的车斗和覆盖布提取到黑色背景,生成单独的图像文件。

    测试卡车图片语义分割

    if __name__ == "__main__":# 初始化 pipelinenum_classes = 3  # 背景, 车斗, 覆盖布try:pipeline = SegmentationPipeline(num_classes=num_classes)# 加载原始图像image_path = "trunk.jpg"original_image = Image.open(image_path)# 使用YOLOv8检测卡车truck_bbox = detect_truck(image_path)if truck_bbox:print(f"Detected truck bounding box: {truck_bbox}")# 进行分割segmentation_mask = pipeline.predict(original_image, truck_bbox)# 提取并可视化车斗和覆盖布到黑色背景visualize_and_extract_regions(original_image=original_image,mask=segmentation_mask,save_base_path="segmentation_output",num_classes=num_classes)else:print("No truck detected, using full image for segmentation")except Exception as e:print(f"Error in main execution: {e}")

    运行~~

    分割后图像

    优化目标和当前问题

    • 当前问题:车斗边缘未完全分割,可能因 DINOv2 模型未训练捕捉细小边缘、YOLO 边界框未包含边缘、或后处理未充分扩展轮廓。
    • 优化:通过扩展 YOLO 边界框(padding)、增强边缘检测(Canny 和形态学操作)、结合颜色和形状信息,确保车斗完整轮廓被分割。

    经过修改和测试

    import torch
    import torch.nn as nn
    from transformers import ViTModel, ViTFeatureExtractor
    from PIL import Image, ImageEnhance
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    import os
    import cv2  # For color-based and shape-based post-processing
    import random
    from ultralytics import YOLO  # For YOLOv8# 定义类别:0 = 背景, 1 = 车斗, 2 = 覆盖布
    CLASS_NAMES = ["background", "truck_bed", "tarp"]# 数据增强参数
    AUGMENTATION_PARAMS = {"brightness_factor": (0.8, 1.2),  # 亮度变化范围"contrast_factor": (0.8, 1.2),    # 对比度变化范围"rotation_range": (-30, 30),      # 旋转角度范围(度)"hue_shift": (-0.1, 0.1),        # 色调变化范围"saturation_factor": (0.8, 1.2), # 饱和度变化范围
    }# YOLOv8 类别映射(假设 'truck' 是可识别的类别)
    YOLO_CLASSES = {6: "train",7: "truck",
    }# ======================
    # 自定义分割模型定义(适配518x518)
    # ======================
    class DINOv2ForSegmentation(nn.Module):def __init__(self, num_classes=3, model_name="./dinov2_base/"):super().__init__()# 加载 DINOv2 主干网络try:self.backbone = ViTModel.from_pretrained(model_name)except Exception as e:print(f"Error loading DINOv2 model: {e}")raisehidden_size = self.backbone.config.hidden_size# 分割头调整(适配518输入)self.segmentation_head = nn.Sequential(nn.Conv2d(hidden_size, 256, kernel_size=1),nn.Upsample(scale_factor=14, mode='bilinear'),  # 518/14=37nn.Conv2d(256, num_classes, kernel_size=1))# 冻结主干网络(可选解冻部分层以微调)for param in self.backbone.parameters():param.requires_grad = Falsedef forward(self, pixel_values):# 获取特征 [batch, 37x37+1, hidden_size]outputs = self.backbone(pixel_values)last_hidden = outputs.last_hidden_state# 转换特征形状 [batch, hidden_size, 37, 37]batch_size = last_hidden.size(0)features = last_hidden[:, 1:].permute(0, 2, 1)  # 移除CLS tokenfeatures = features.view(batch_size, -1, 37, 37)  # 518/14=37# 分割头logits = self.segmentation_head(features)return logits# ======================
    # 预处理与后处理工具
    # ======================
    class SegmentationPipeline:def __init__(self, num_classes=3):# 确保dinov2_base目录包含正确的preprocessor_config.jsontry:self.feature_extractor = ViTFeatureExtractor.from_pretrained("./dinov2_base",size={"height": 518, "width": 518}  # 关键修改)except Exception as e:print(f"Error loading feature extractor: {e}")raiseself.model = DINOv2ForSegmentation(num_classes)self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")self.model.to(self.device)self.model.eval()print(f"Model loaded on {self.device}")def augment_image(self, image):"""应用数据增强以提高泛化能力"""# 亮度enhancer = ImageEnhance.Brightness(image)brightness = random.uniform(*AUGMENTATION_PARAMS["brightness_factor"])image = enhancer.enhance(brightness)# 对比度enhancer = ImageEnhance.Contrast(image)contrast = random.uniform(*AUGMENTATION_PARAMS["contrast_factor"])image = enhancer.enhance(contrast)# 色调和饱和度(使用PIL的Color)enhancer = ImageEnhance.Color(image)saturation = random.uniform(*AUGMENTATION_PARAMS["saturation_factor"])image = enhancer.enhance(saturation)# 旋转(使用PIL的rotate,修正fillmode错误)angle = random.uniform(*AUGMENTATION_PARAMS["rotation_range"])image = image.rotate(angle, expand=True, fillcolor=(0, 0, 0))  # 黑色填充return imagedef preprocess(self, image):if not isinstance(image, Image.Image):raise ValueError("Input must be a PIL Image")if image.mode != "RGB":print(f"Converting image from {image.mode} to RGB")image = image.convert("RGB")# 应用数据增强augmented_image = self.augment_image(image)# 自动调整到518x518try:inputs = self.feature_extractor(images=augmented_image,return_tensors="pt",size={"height": 518, "width": 518})return inputs.pixel_values.to(self.device)except Exception as e:print(f"Error in preprocessing: {e}")raisedef postprocess(self, logits, original_size):probs = torch.softmax(logits, dim=1)mask = torch.argmax(probs, dim=1).squeeze().cpu().numpy()print(f"Mask shape: {mask.shape}, Unique values: {np.unique(mask)}")print(f"Probability distribution per class: {probs.mean(dim=(0, 2, 3))}")  # Debug class probabilitiesmask = Image.fromarray(mask.astype(np.uint8))return mask.resize(original_size, Image.NEAREST)def predict(self, image, truck_bbox=None):"""在指定的truck区域内进行预测,如果没有truck区域则使用整个图像"""if truck_bbox:# 裁剪图像到truck区域,扩展更大边界以包含边缘x1, y1, x2, y2 = truck_bboxpadding = 50  # 增加边界以捕捉完整边缘(从 20 增加到 50)cropped_image = image.crop((max(0, x1 - padding), max(0, y1 - padding),min(image.size[0], x2 + padding), min(image.size[1], y2 + padding)))else:cropped_image = image# 预处理inputs = self.preprocess(cropped_image)# 推理with torch.no_grad():logits = self.model(inputs)probs = torch.softmax(logits, dim=1)  # Compute probabilities hereprint(f"Logits shape: {logits.shape}")print(f"Logits max: {logits.max()}, min: {logits.min()}")print(f"Probabilities max: {probs.max()}, min: {probs.min()}")# 后处理mask = self.postprocess(logits, cropped_image.size)# 如果有truck区域,将mask扩展回原图大小if truck_bbox:full_mask = Image.new("L", image.size, 0)  # 背景为0adjusted_bbox = (max(0, x1 - padding), max(0, y1 - padding),min(image.size[0], x2 + padding), min(image.size[1], y2 + padding))full_mask.paste(mask, adjusted_bbox)return full_maskreturn mask# ======================
    # 使用示例
    # ======================
    def visualize_and_extract_regions(original_image, mask, save_base_path="output", num_classes=3):"""将车斗和覆盖布提取到黑色背景的单独图片上,不再叠加到原图:param original_image: PIL.Image 原始图片:param mask: PIL.Image 分割mask:param save_base_path: 保存路径基础名称:param num_classes: 分割类别数"""# 创建颜色映射 (RGB格式)colormap = []# 背景色为黑色(用于单独输出)colormap.append([0, 0, 0])  # Class 0: Background (black)# 车斗(红色)、覆盖布(绿色)colormap.append([255, 0, 0])  # Class 1: Truck bed (red)colormap.append([0, 255, 0])  # Class 2: Tarp (green)colormap = np.array(colormap, dtype=np.uint8)# 将mask转换为数组,确保尺寸匹配mask_array = np.array(mask.convert("L"))  # 确保mask是单通道original_array = np.array(original_image.convert("RGB"))height, width = original_array.shape[:2]# 调整mask尺寸以匹配原图(如果不匹配)if mask_array.shape != (height, width):mask_array = np.array(mask.resize((width, height), Image.NEAREST))# 提取并保存车斗和覆盖布到黑色背景的单独图片,只处理车斗和覆盖布black_background = np.zeros((height, width, 3), dtype=np.uint8)  # 黑色背景for class_id, class_name in enumerate(CLASS_NAMES[1:], 1):  # 跳过背景(0)class_mask = (mask_array == class_id).astype(np.uint8) * 255  # 二值掩码# 提取区域到黑色背景extracted_region = black_background.copy()for i in range(3):  # RGB通道extracted_region[:, :, i] = black_background[:, :, i] * (1 - class_mask / 255) + \colormap[class_id, i] * (class_mask / 255)# 保存提取的区域到黑色背景extracted_image = Image.fromarray(extracted_region.astype(np.uint8))extracted_image.save(f"{save_base_path}_{class_name}_on_black.png")print(f"Extracted {class_name} on black background saved to {save_base_path}_{class_name}_on_black.png")# 也可以保存原始mask以便检查mask.save(f"{save_base_path}_mask.png")print(f"Raw mask saved to {save_base_path}_mask.png")# 附加:尝试基于颜色后处理以改进结果color_based_mask = color_based_segmentation(original_image)if color_based_mask is not None:visualize_color_based_mask_on_black(original_image, color_based_mask, save_base_path + "_color_based_on_black")def detect_truck(image_path):"""使用YOLOv8检测卡车并返回边界框"""try:# 加载YOLOv8模型model = YOLO("yolov8n.pt")  # 确保yolov8n.pt在当前目录下# 进行预测print('yolov8n load successfully~~~')results = model(image_path, conf=0.3)  # confidence threshold 0.3#print('result:', results)for result in results:boxes = result.boxes  # 获取检测框for box in boxes:cls = int(box.cls[0])  # 类别IDprint('cls:', cls)if YOLO_CLASSES.get(cls):  # == "truck":print('detect out:', YOLO_CLASSES.get(cls))x1, y1, x2, y2 = box.xyxy[0].tolist()  # 边界框坐标return (int(x1), int(y1), int(x2), int(y2))  # 返回(x1, y1, x2, y2)return None  # 如果未检测到卡车except Exception as e:print(f"Error in YOLOv8 detection: {e}")return Nonedef color_based_segmentation(image):"""使用颜色阈值分割车斗(多种颜色)和覆盖布(多种颜色),提高泛化能力"""try:# 转换为OpenCV格式 (BGR)img = cv2.cvtColor(np.array(image.convert("RGB")), cv2.COLOR_RGB2BGR)# 定义更广泛的颜色范围(HSV空间更适合)hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)# 红色范围(车斗,可能为红色、蓝色、黄色等)lower_red1 = np.array([0, 120, 70])  # 红色范围1upper_red1 = np.array([10, 255, 255])lower_red2 = np.array([170, 120, 70])  # 红色范围2upper_red2 = np.array([180, 255, 255])lower_blue = np.array([100, 120, 70])  # 蓝色范围upper_blue = np.array([130, 255, 255])lower_yellow = np.array([20, 120, 70])  # 黄色范围upper_yellow = np.array([40, 255, 255])mask_red1 = cv2.inRange(hsv, lower_red1, upper_red1)mask_red2 = cv2.inRange(hsv, lower_red2, upper_red2)mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)mask_truck = cv2.bitwise_or(cv2.bitwise_or(mask_red1, mask_red2), cv2.bitwise_or(mask_blue, mask_yellow))# 绿色范围(覆盖布,可能为绿色、蓝色等)lower_green = np.array([35, 40, 40])upper_green = np.array([85, 255, 255])lower_blue_tarp = np.array([100, 40, 40])  # 蓝色覆盖布upper_blue_tarp = np.array([130, 255, 255])mask_green = cv2.inRange(hsv, lower_green, upper_green)mask_blue_tarp = cv2.inRange(hsv, lower_blue_tarp, upper_blue_tarp)mask_tarp = cv2.bitwise_or(mask_green, mask_blue_tarp)# 合并掩码:0=背景, 1=车斗, 2=覆盖布combined_mask = np.zeros((hsv.shape[0], hsv.shape[1]), dtype=np.uint8)combined_mask[mask_truck > 0] = 1  # 车斗combined_mask[mask_tarp > 0] = 2  # 覆盖布# 应用形态学操作去除噪声并填充小孔kernel = np.ones((5, 5), np.uint8)combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_CLOSE, kernel)combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel)return Image.fromarray(combined_mask)except Exception as e:print(f"Error in color-based segmentation: {e}")return Nonedef visualize_color_based_mask_on_black(original_image, mask, save_path):"""可视化基于颜色的分割结果到黑色背景"""colormap = np.array([[0, 0, 0],  # 背景 (黑)[255, 0, 0],  # 车斗 (红)[0, 255, 0]  # 覆盖布 (绿)], dtype=np.uint8)mask_array = np.array(mask)height, width = mask_array.shapeblack_background = np.zeros((height, width, 3), dtype=np.uint8)# 提取区域到黑色背景for class_id in [1, 2]:  # 只处理车斗和覆盖布class_mask = (mask_array == class_id).astype(np.uint8) * 255for i in range(3):  # RGB通道black_background[:, :, i] = black_background[:, :, i] * (1 - class_mask / 255) + \colormap[class_id, i] * (class_mask / 255)extracted_image = Image.fromarray(black_background.astype(np.uint8))extracted_image.save(save_path + ".png")print(f"Color-based visualization on black background saved to {save_path}.png")def enhance_segmentation(mask_array, truck_region, num_classes):"""增强分割结果以捕捉车斗的完整轮廓,处理边缘和颜色遮挡"""# 应用更强的形态学操作以填补空洞和捕捉边缘kernel_large = np.ones((20, 20), np.uint8)  # 增大内核以捕捉完整边缘(从 15 增加到 20)kernel_small = np.ones((3, 3), np.uint8)    # 用于细化边缘# 膨胀以捕捉完整轮廓dilated_mask = cv2.dilate(mask_array, kernel_large, iterations=4)  # 增加迭代次数以捕捉更多边缘# 腐蚀以去除噪声,保持边界eroded_mask = cv2.erode(dilated_mask, kernel_large, iterations=1)# 闭运算填补空洞closed_mask = cv2.morphologyEx(eroded_mask, cv2.MORPH_CLOSE, kernel_large)# 开运算去除小噪声opened_mask = cv2.morphologyEx(closed_mask, cv2.MORPH_OPEN, kernel_small)# 细化边缘:使用更敏感的 Canny 边缘检测edges = cv2.Canny((opened_mask == 1).astype(np.uint8) * 255, 30, 100)  # 降低阈值以捕捉更多细小边缘dilated_edges = cv2.dilate(edges, kernel_small, iterations=3)  # 增加膨胀以连接边缘# 使用颜色和形状信息进一步优化车斗区域hsv_truck = cv2.cvtColor(truck_region, cv2.COLOR_RGB2HSV)height, width = opened_mask.shape# 查找车斗和覆盖布的轮廓truck_bed_mask = (opened_mask == 1).astype(np.uint8) * 255tarp_mask = (opened_mask == 2).astype(np.uint8) * 255# 轮廓检测,填充完整轮廓contours_truck, _ = cv2.findContours(truck_bed_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)contours_tarp, _ = cv2.findContours(tarp_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 创建增强后的掩码enhanced_mask = np.zeros_like(opened_mask, dtype=np.uint8)# 填充车斗轮廓,确保完整性并结合边缘if contours_truck:# 找到最大的轮廓(假设车斗是最大的区域)largest_contour = max(contours_truck, key=cv2.contourArea)cv2.drawContours(enhanced_mask, [largest_contour], -1, 1, thickness=cv2.FILLED)# 结合边缘信息,填补细小边界enhanced_mask[dilated_edges > 0] = 1  # 将检测到的边缘区域标记为车斗else:# 如果没有检测到轮廓,使用膨胀后的区域enhanced_mask[opened_mask == 1] = 1# 填充覆盖布轮廓for contour in contours_tarp:cv2.drawContours(enhanced_mask, [contour], -1, 2, thickness=cv2.FILLED)# 确保掩码值在有效范围内enhanced_mask = np.clip(enhanced_mask, 0, num_classes - 1)# 额外处理:如果车斗区域有小断裂或边缘缺失,使用连通性分析填补num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(truck_bed_mask, connectivity=8)if num_labels > 1:  # 如果有多个连通区域largest_area = 0largest_label = 0for label in range(1, num_labels):  # 跳过背景(标签0)area = stats[label, cv2.CC_STAT_AREA]if area > largest_area:largest_area = arealargest_label = labelenhanced_mask[labels == largest_label] = 1  # 保留最大连通区域作为车斗# 再次细化边缘,确保完整性final_edges = cv2.Canny((enhanced_mask == 1).astype(np.uint8) * 255, 20, 80)  # 进一步降低阈值捕捉边缘enhanced_mask[final_edges > 0] = 1  # 填补边缘# 边界扩展:额外膨胀以确保边缘完整final_dilated = cv2.dilate((enhanced_mask == 1).astype(np.uint8) * 255, kernel_small, iterations=2)enhanced_mask[final_dilated > 0] = 1  # 扩展车斗边缘return enhanced_maskif __name__ == "__main__":# 初始化 pipelinenum_classes = 3  # 背景, 车斗, 覆盖布try:pipeline = SegmentationPipeline(num_classes=num_classes)# 加载原始图像image_path = "trunk.jpg"original_image = Image.open(image_path)# 使用YOLOv8检测卡车truck_bbox = detect_truck(image_path)if truck_bbox:print(f"Detected truck bounding box: {truck_bbox}")# 进行分割segmentation_mask = pipeline.predict(original_image, truck_bbox)# 提取并可视化车斗和覆盖布到黑色背景visualize_and_extract_regions(original_image=original_image,mask=segmentation_mask,save_base_path="segmentation_output",num_classes=num_classes)else:print("No truck detected, using full image for segmentation")except Exception as e:print(f"Error in main execution: {e}")
    • 扩展 YOLO 边界框(padding)
      • 在 predict 函数中,将 padding 从 20 增加到 50,确保 YOLO 检测的边界框包含车斗的完整边缘,减少因边界框过紧而丢失边缘的可能性。

    • 增强边缘检测(Canny 和形态学操作)
      • 增加额外膨胀步骤(final_dilated 使用 3x3 内核,迭代 2 次)以扩展车斗边缘,确保边缘完整。

      • 优化 Canny 边缘检测,降低阈值(从 30, 100 调整到 20, 80 再到 20, 80),确保捕捉更多细小边缘。

      • 增大形态学操作的内核大小(kernel_large 从 15x15 增加到 20x20),并增加膨胀迭代次数(从 3 增加到 4),更好地捕捉车斗边缘

    • 结合颜色和形状信息
      • 保留颜色分割(color_based_segmentation)和轮廓检测(findContours),结合最大连通区域和边缘信息,确保车斗的完整轮廓被分割,即使有光影变化或遮挡。

      • 使用连通性分析(connectedComponentsWithStats)保留最大连通区域,填补小断裂或边缘缺失。

    • 预期效果
      • 车斗的完整轮廓(包括边缘)将被标记为红色,输出到 segmentation_output_truck_bed_on_black.png,即使边缘细小或有光影变化。

      • 覆盖布(绿色)仍会被正确分割到 segmentation_output_tarp_on_black.png,但不会干扰车斗的完整性。

    调试和下一步

    • 运行优化后的代码,检查输出 segmentation_output_truck_bed_on_black.png 和 segmentation_output_enhanced_mask.png,确保车斗边缘被完整分割。
    • 如果车斗边缘仍不完整,尝试:
      • 进一步增加 padding(如 70 或更高)。
      • 调整 enhance_segmentation 中的 kernel_large(如 25x25)、迭代次数,或 Canny 阈值(试试 10, 60)。

    在语义分割的基础上,下面是判断车斗上方空间的范围何雨覆的位置

    分析当前分割结果

    • 车斗(红色):从图片看,车斗的轮廓已基本完整,但可能有细小噪声或不规则边缘。
    • 覆盖布(绿色):覆盖布分布在车斗顶部,但可能有间断或未完全覆盖的部分。
    • 目标
      1. 计算车斗的顶部投影面积(假设为车斗的完整轮廓面积)。
      2. 计算覆盖布的面积(绿色区域面积)。
      3. 比较覆盖布面积与车斗面积,判断覆盖率是否达到 80%。

    这里给出算法代码

    import cv2
    import numpy as np
    from PIL import Image# 加载图像
    image_path = "truck_seg.png"
    image = cv2.imread(image_path)# 转换为 RGB 格式(OpenCV 默认 BGR)
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 转换为 HSV 格式以便颜色分割
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 定义颜色范围(基于红色车斗和绿色雨覆)
    # 红色范围(车斗,可能为红色、蓝色、黄色等)
    lower_red1 = np.array([0, 120, 70])    # 红色范围1
    upper_red1 = np.array([10, 255, 255])
    lower_red2 = np.array([170, 120, 70])  # 红色范围2
    upper_red2 = np.array([180, 255, 255])
    lower_blue = np.array([100, 120, 70])  # 蓝色范围
    upper_blue = np.array([130, 255, 255])
    lower_yellow = np.array([20, 120, 70]) # 黄色范围
    upper_yellow = np.array([40, 255, 255])# 绿色范围(雨覆,可能为绿色、蓝色等)
    lower_green = np.array([35, 40, 40])
    upper_green = np.array([85, 255, 255])
    lower_blue_tarp = np.array([100, 40, 40])  # 蓝色雨覆
    upper_blue_tarp = np.array([130, 255, 255])# 颜色分割
    mask_red1 = cv2.inRange(hsv, lower_red1, upper_red1)
    mask_red2 = cv2.inRange(hsv, lower_red2, upper_red2)
    mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)
    mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)
    mask_truck = cv2.bitwise_or(cv2.bitwise_or(mask_red1, mask_red2), cv2.bitwise_or(mask_blue, mask_yellow))mask_green = cv2.inRange(hsv, lower_green, upper_green)
    mask_blue_tarp = cv2.inRange(hsv, lower_blue_tarp, upper_blue_tarp)
    mask_tarp = cv2.bitwise_or(mask_green, mask_blue_tarp)# 合并掩码:0=背景, 1=车斗, 2=雨覆
    combined_mask = np.zeros((hsv.shape[0], hsv.shape[1]), dtype=np.uint8)
    combined_mask[mask_truck > 0] = 1  # 车斗
    combined_mask[mask_tarp > 0] = 2   # 雨覆# 应用形态学操作去除噪声并填充空洞
    kernel = np.ones((5, 5), np.uint8)
    closed_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_CLOSE, kernel)
    opened_mask = cv2.morphologyEx(closed_mask, cv2.MORPH_OPEN, kernel)# 增强车斗轮廓,捕捉完整边缘
    truck_bed_mask = (opened_mask == 1).astype(np.uint8) * 255
    kernel_large = np.ones((20, 20), np.uint8)
    dilated_truck = cv2.dilate(truck_bed_mask, kernel_large, iterations=4)
    eroded_truck = cv2.erode(dilated_truck, kernel_large, iterations=1)
    closed_truck = cv2.morphologyEx(eroded_truck, cv2.MORPH_CLOSE, kernel_large)# 增强雨覆轮廓
    tarp_mask = (opened_mask == 2).astype(np.uint8) * 255
    dilated_tarp = cv2.dilate(tarp_mask, kernel_large, iterations=2)
    closed_tarp = cv2.morphologyEx(dilated_tarp, cv2.MORPH_CLOSE, kernel_large)# 更新增强后的掩码
    enhanced_mask = np.zeros_like(opened_mask, dtype=np.uint8)
    enhanced_mask[closed_truck > 0] = 1  # 车斗
    enhanced_mask[closed_tarp > 0] = 2   # 雨覆# 计算面积(像素数)
    truck_bed_area = np.sum(enhanced_mask == 1)  # 车斗面积
    tarp_area = np.sum(enhanced_mask == 2)       # 雨覆面积# 计算覆盖率
    if truck_bed_area > 0:coverage_ratio = (tarp_area / truck_bed_area) * 100  # 覆盖率(百分比)
    else:coverage_ratio = 0  # 如果车斗面积为0,覆盖率设为0# 打印面积和覆盖率
    print(f"Truck bed area (pixels): {truck_bed_area}")
    print(f"Tarp area (pixels): {tarp_area}")
    print(f"Tarp coverage ratio: {coverage_ratio:.2f}%")
    print(f"Coverage meets 80% requirement: {'Yes' if coverage_ratio >= 80 else 'No'}")# 可视化:提取车斗和雨覆到黑色背景
    height, width = enhanced_mask.shape
    black_background = np.zeros((height, width, 3), dtype=np.uint8)# 提取车斗(红色)
    truck_mask = (enhanced_mask == 1).astype(np.uint8) * 255
    black_background[truck_mask > 0] = [255, 0, 0]  # 红色# 提取雨覆(绿色)
    tarp_mask = (enhanced_mask == 2).astype(np.uint8) * 255
    black_background[tarp_mask > 0] = [0, 255, 0]  # 绿色# 保存结果
    cv2.imwrite("truck_bed_on_black.png", cv2.cvtColor(black_background, cv2.COLOR_RGB2BGR))
    print(f"Extracted truck bed on black background saved to truck_bed_on_black.png")
    cv2.imwrite("tarp_on_black.png", cv2.cvtColor(black_background, cv2.COLOR_RGB2BGR))
    print(f"Extracted tarp on black background saved to tarp_on_black.png")# 保存增强后的掩码以便检查
    cv2.imwrite("enhanced_mask.png", enhanced_mask)
    print(f"Enhanced mask saved to enhanced_mask.png")
    • 图像加载和颜色分割
      • 加载 truck_seg.png,转换为 HSV 颜色空间。

      • 使用预定义的红色(车斗)和绿色(雨覆)范围进行颜色分割,规则与之前一致,支持多种颜色变体(红、蓝、黄;绿、蓝)。

    • 形态学操作和轮廓增强
      • 应用闭运算(MORPH_CLOSE)填补空洞,开运算(MORPH_OPEN)去除噪声。
      • 增强车斗和雨覆轮廓,使用更大的内核(20x20)和更多迭代次数(车斗 4 次,雨覆 2 次)以捕捉完整边缘。
    • 面积计算
      • 使用 np.sum 统计车斗(值为 1)和雨覆(值为 2)的像素数,单位为像素。
      • 计算覆盖率:tarp_area / truck_bed_area * 100,判断是否 ≥ 80%。
    • 可视化输出
      • 将车斗(红色)和雨覆(绿色)提取到黑色背景,分别保存为 truck_bed_on_black.png 和 tarp_on_black.png。
      • 保存增强后的掩码 enhanced_mask.png 以便检查。

    经过检测覆盖率没有达到80%

    上面图像分割还需要再优化下,毕竟存在把非雨覆物体错误识别的地方,但整体思路可以分享出来供大家借鉴

    相关文章:

    DINOv2 + yolov8 + opencv 检测卡车的可拉拽雨覆是否完全覆盖

    最近是接了一个需求咨询图像处理类的,甲方要在卡车过磅的地方装一个摄像头用检测卡车的车斗雨覆是否完全, 让我大致理了下需求并对技术核心做下预研究 开发一套图像处理软件,能够实时监控经过的卡车并判断其车斗的雨覆状态。 系统需具备以下…...

    【嵌入式】RTOS安装和测试

    RTOS 安装 安装RTOS,可采用RT-Linux框架 [RT-Linux — 快速使用手册](2. RT-Linux — 快速使用手册—基于LubanCat-RK356x系列板卡 文档),apt没有安装包,更新ubuntu系统版本后仍然不行,后更新国内软件源仍然没有检测到安装包。后…...

    MySQL的存储引擎

    存储引擎的概念 存储引擎:负责将数据存储在物理存储设备(如磁盘)上的结构和机制。存储引擎决定了数据库如何管理、组织和访问数据。) 因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型…...

    瑞芯微RK安卓Android主板GPIO按键配置方法,触觉智能嵌入式开发

    触觉智能分享,瑞芯微RK安卓Android主板GPIO按键配置方法,方便大家更好利用空闲IO!由触觉智能Purple Pi OH鸿蒙开发板演示,搭载了瑞芯微RK3566四核处理器,树莓派卡片电脑设计,支持安卓Android、开源鸿蒙Open…...

    数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用

    数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用 人工智能与机器学习技术通过自动化、智能化的数据分析,显著提升了数据分类、威胁检测的精度与效率,尤其在处理非结构化数据、复杂…...

    跨平台公式兼容性大模型提示词模板(飞书 + CSDN + Microsoft Word)

    飞书云文档 CSDN MD编辑器 Microsoft Word 跨平台公式兼容方案: 一、背景痛点与解决方案 在技术文档创作中,数学公式的跨平台渲染一直存在三大痛点: 飞书云文档:原生KaTeX渲染与导出功能存在语法限制微软Word:Math…...

    Redis面试题----Redis 的持久化机制是什么?各自的优缺点?

    Redis 提供了两种主要的持久化机制,分别是 RDB(Redis Database)和 AOF(Append Only File),下面将详细介绍它们的原理、优缺点。 RDB(Redis Database) 原理 RDB 持久化是将 Redis 在某个时间点上的数据集快照以二进制文件的形式保存到磁盘上。可以通过手动执行 SAVE …...

    Leetcode-接雨水(单调栈)

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] …...

    [ComfyUI]官方已支持Skyreels混元图生视频,速度更快,效果更好(附工作流)

    一、介绍 昨天有提到官方已经支持了Skyreels,皆大欢喜,效果更好一些,还有GGUF量化版本,进一步降低了大家的显存消耗。 今天就来分享一下官方流怎么搭建,我体验下来感觉更稳了一些,生成速度也更快&#xf…...

    安宝特方案 | 电力行业的“智能之眼”,AR重新定义高效运维!

    引言: 电力行业正经历智能化变革,安宝特AR数字化工作流以四大核心优势,为电力企业打造全场景智慧运维方案! 四大颠覆性功能,直击行业痛点 1、高度自定义作业流程 支持图文指引、语音播报、AI实时识别(如…...

    游戏引擎学习第124天

    仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾/复习 今天是继续完善和调试多线程的任务队列。之前的几天,我们已经介绍了多线程的一些基础知识,包括如何创建工作队列以及如何在线程中处理任务。今天,重点是解决那些我们之前没有注意到…...

    微软推出Office免费版,限制诸多,只能编辑不能保存到本地

    易采游戏网2月25日独家消息:微软宣布推出一款免费的Office版本,允许用户进行基础文档编辑操作,但限制颇多,其中最引人关注的是用户无法将文件保存到本地。这一举措引发了广泛讨论,业界人士对其背后的商业策略和用户体验…...

    spring中的注解介绍

    本篇文章专门用来介绍spring中的各种注解。 1、RestController 1、含义 2、举例 3、使用场景 RestController 通常用于开发 RESTful API,适合返回 JSON 或 XML 数据的场景 4、总结 RestController 是 Spring 中用于简化 RESTful Web 服务开发的注解,它结…...

    修改`FSL Yocto Project Community BSP`用到的u-boot源码,使其能适配百问网(100ask)的开发板

    前言 在博文 https://blog.csdn.net/wenhao_ir/article/details/145547974 中,我们利用官方提供的BSP(FSL Yocto Project Community BSP)构建了写到SD卡中的完整镜像,然后启动后发现存在不少问题,首要的问题就是u-boot不能识别网卡,在这篇博文中,我们就找到FSL Yocto Pro…...

    DeepSeek开源周Day2:DeepEP - 专为 MoE 模型设计的超高效 GPU 通信库

    项目地址:https://github.com/deepseek-ai/DeepEP 开源日历:2025-02-24起 每日9AM(北京时间)更新,持续五天 (2/5)! ​ ​ 引言 在大模型训练中,混合专家模型(Mixture-of-Experts, MoE)因其动…...

    计算机毕业设计 ——jspssm506Springboot 的旧物置换网站

    作者:程序媛9688 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等。 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题)&#xf…...

    观成科技:海莲花“PerfSpyRAT”木马加密通信分析

    1.概述 在2024年9月中旬至10月,东南亚APT组织“海莲花”通过GitHub发布开源安全工具项目,针对网络安全人员发起了定向攻击。通过对相关攻击活动进行分析,可以将其与一些海莲花的样本关联起来。这些样本的通信数据结构与海莲花此前使用的攻击…...

    在使用 npm link 进行本地 npm 包调试时,是否需要删除项目中已安装的依赖包取决于你的调试场景和依赖管理方式

    1. 默认情况下不需要删除已安装的包 npm link 的工作原理&#xff1a; 当你在项目中运行 npm link <package-name> 时&#xff0c;npm 会创建一个符号链接&#xff08;symlink&#xff09;&#xff0c;将项目的 node_modules/<package-name> 指向全局的软链包&am…...

    Springboot快速接入豆包大模型

    背景 突然接到上面的通知&#xff0c;想要在系统里面接入各大模型的能力&#xff0c;我这边随机选了个豆包&#xff0c;然后快速对接了一下&#xff0c;很顺利&#xff0c;一把过&#xff0c;现在文档的快速入门还是很ok的&#xff0c;在此记录一下过程&#xff0c;给宝子们参考…...

    w803|联盛德|WM IoT SDK2.X测试|window11|TOML 文件|外设|TFT_LCD|测试任务|(5):TFT_LCD_LVGL示例

    TFT_LCD_LVGL 功能概述 此应用程序是使用 WM IoT SDK 进行 LVGL 功能的示例。它演示了如何初始化 TFT LCD 设备&#xff0c;并创建 LVGL DEMO Task 进行 LVGL 模块的初始化&#xff0c;并展示 LVGL 原生的不同 Demo 场景, 例如&#xff1a; Widgets, Music Player, Benchmark…...

    java23种设计模式-观察者模式

    观察者模式&#xff08;Observer Pattern&#xff09;学习笔记 编程相关书籍分享&#xff1a;https://blog.csdn.net/weixin_47763579/article/details/145855793 DeepSeek使用技巧pdf资料分享&#xff1a;https://blog.csdn.net/weixin_47763579/article/details/145884039 1.…...

    【MySQL 一 数据库基础】深入解析 MySQL 的索引(3)

    索引 索引操作 自动创建 当我们为一张表加主键约束(Primary key)&#xff0c;外键约束(Foreign Key)&#xff0c;唯一约束(Unique)时&#xff0c;MySQL会为对应的的列自动创建一个索引&#xff1b;如果表不指定任何约束时&#xff0c;MySQL会自动为每一列生成一个索引并用ROW_I…...

    本地部署 deepseek-r1 1.5B方法-ubuntu20.04 python3.10 pycharm虚拟环境

    1. 环境安装 ubuntu20.04 python3.10 pycharm虚拟环境 2.拉取代码 虚拟环境下安装vllm&#xff1a; pip install vllm ubuntu命令窗口安装 sudo apt install git-lfs 初始化 Git LFS 安装 Git LFS 后&#xff0c;你需要虚拟环境命令窗口初始化它&#xff1a;git lfs i…...

    【Qt】为程序增加闪退crash报告日志

    背景 随着软件代码量的增加&#xff0c;软件崩溃闪退的肯能行越来越大&#xff0c;其中一些是难以复现的&#xff0c;比如访问了访问了非法地址、被操作系统杀死等。 为此&#xff0c;在软件出现闪退情况时&#xff0c;尽可能多的记录闪退发生时信息&#xff0c;对排查闪退原…...

    Visual Studio打开文件后,中文变乱码的解决方案

    文件加载 使用Unicode&#xff08;UTF-8&#xff09;编码加载文件 C:\WorkSpace\Assets\Scripts\UI\View\ExecuteComplateView.cs时&#xff0c;有些字节已用Unicode替换字符替换。保存该文件将不会保留原始文件内容。...

    某住宅小区地下车库安科瑞的新能源汽车充电桩的配电设计与应用方案 安科瑞 耿笠

    摘要&#xff1a;纯电动商用车的工作环境存在路况复杂、工况恶劣等情况&#xff0c;导致整车电气设备的磨损速率加快&#xff0c;造成电气设备绝缘电阻持续下降&#xff0c;如不及时处理&#xff0c;可能存在安全隐患或引发重大安全事故。文章从绝缘故障检测原理出发&#xff0…...

    eclogy后台运维笔记(写的很乱,只限个人观看)

    组织权限&#xff1a; 矩阵管理 这个很重要&#xff0c;比如进行流程操作者的选择时&#xff0c;我们进行需要选择财务部的出纳&#xff0c;会计&#xff0c;总经理。我们不能去直接选定一个人&#xff0c;万一这个人离职了&#xff0c;那所有的流程都要手动修改&#xff0c;…...

    结构型模式 - 适配器模式 (Adapter Pattern)

    结构型模式 - 适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户希望的另一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 类适配器&#xff0c;适用于要适配的类是一个接口&#xf…...

    [2/11]C#性能优化-不要使用空析构函数-每个细节都有示例代码

    前言 在C#开发中&#xff0c;性能优化是提升系统响应速度和资源利用率的关键环节。 当然&#xff0c;同样是所有程序的关键环节。 通过遵循下述建议&#xff0c;可以有效地减少不必要的对象创建&#xff0c;从而减轻GC的负担&#xff0c;提高应用程序的整体性能。记住&#xf…...

    0-基于强化学习的图Transformer算法求解车辆路径问题(2023)

    文章目录 Abstract1 Introduction2. Related Work2.1 引言2.2.基于RNN的VRP解决方案2.3.基于GNN的VRP解决方案2.4.基于Transformer的车辆路径问题求解方法3 边嵌入注意力模型3.1 编码器3.1.1 边嵌入多头注意力3.1.2. 前馈网络(FFN)、批量归一化和残差连接3.2 解码器3.2.1 解码…...

    Linux:互斥

    目录 一、互斥概念 二、互斥的使用函数 三、互斥的底层原理 一、互斥概念 互斥&#xff0c;全称是线程互斥&#xff0c;互斥是一套解决方案&#xff0c;用来保护临界资源。一般在多线程的代码中&#xff0c;要使用互斥这套解决方案来保护临界资源。 主要从代码的角度理解互斥…...

    单例模式——c++

    一个类&#xff0c;只能有1个对象 (对象在堆空间) 再次创建该对象&#xff0c;直接引用之前的对象 so构造函数不能随意调用 so构造函数私有 so对象不能构造 如何调用私有化的构造函数: 公开接口调用构造函数 调用构造函数&#xff1a;singleTon instance&#xff1b; 但…...

    C++之string类的模拟实现(超详细)

    们学习东西&#xff0c;先学习如果使用它&#xff0c;然后再学习如何实现它 文章目录 目录 1. 命名空间以及头文件 2.string类的成员变量 3.string类的成员函数 3.1 构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 赋值运算符重载 3.5 c_str函数 3.6 size函数 3.7 clea…...

    【Git 学习笔记_27】DIY 实战篇:利用 DeepSeek 实现 GitHub 的 GPG 密钥创建与配置

    文章目录 1 前言2 准备工作3 具体配置过程3.1. 本地生成 GPG 密钥3.2. 导出 GPG 密钥3.3. 将密钥配置到 Git 中3.4. 测试提交 4 问题排查记录5 小结与复盘 1 前言 昨天在更新我的第二个 Vim 专栏《Mastering Vim (2nd Ed.)》时遇到一个经典的 Git 操作问题&#xff1a;如何在 …...

    【原创工具】同文件夹PDF文件合并 By怜渠客

    【原创工具】同文件夹PDF文件合并 By怜渠客 原贴&#xff1a;可批量合并多个文件夹内的pdf工具 - 吾爱破解 - 52pojie.cn 他这个存在一些问题&#xff0c;并非是软件内自主实现的PDF合并&#xff0c;而是调用的pdftk这一工具&#xff0c;但楼主并没有提供pdftk&#xff0c;而…...

    kafka-leader -1问题解决

    一. 问题&#xff1a; 在 Kafka 中&#xff0c;leader -1 通常表示分区的领导者副本尚未被选举出来&#xff0c;或者在获取领导者信息时出现了问题。以下是可能导致出现 kafka leader -1 的一些常见原因及相关分析&#xff1a; 1. 副本同步问题&#xff1a; 在 Kafka 集群中&…...

    图像融合+语义

    图像配准&#xff0b;融合语义方法总结 1.Joint framework of image registration and fusion RFNet: Unsupervised Network for Mutually Reinforcing Multi-modal Image Registration and Fusion(2022CVPR) Unsupervised misaligned infrared and visible image fusion via…...

    AI人工智能机器学习之监督学习和集成学习

    1、概要 本篇学习AI人工智能机器监督学习框架下的集成学习&#xff0c;以鸢尾花iris数据集、随机森林模型和梯度提升为示例&#xff0c;从代码层面测试和讲述监督学习和集成学习能。 2、监督学习和集成学习 - 简介 监督学习和集成学习是机器学习领域中的两个重要概念。 监督…...

    通过返回的key值匹配字典中的value值

    需求 页面中上面搜索项有获取字典枚举接口&#xff0c;table表格中也有根据key匹配字典中的value 方案一 需要做到的要求 这里上面下拉列表是一个组件获取的字典&#xff0c;下面也是通过字典匹配&#xff0c;所以尽量统一封装一个函数&#xff0c;每个组件保证最少变动tabl…...

    30 分钟从零开始入门 CSS

    HTML CSS JS 30分钟从零开始入门拿下 HTML_html教程-CSDN博客 30 分钟从零开始入门 CSS-CSDN博客 JavaScript 指南&#xff1a;从入门到实战开发-CSDN博客 前言 最近也是在复习&#xff0c;把之前没写的博客补起来&#xff0c;之前给大家介绍了 html&#xff0c;现在是 CSS 咯…...

    矩阵的奇异值(SVD)分解和线性变换

    矩阵的奇异值&#xff08;SVD&#xff09;分解和线性变换 SVD定义 奇异值分解&#xff08;Singular Value Decomposition&#xff0c;简称 SVD&#xff09;是一种重要的线性代数工具&#xff0c;能够将任意矩阵 ( A ∈ R m n \mathbf{A} \in \mathbb{R}^{m \times n} A∈Rmn…...

    Kubernetes与Docker:区别与优劣总结

    在云原生技术栈中&#xff0c;Docker和Kubernetes是两大核心工具&#xff0c;但它们的功能定位和使用场景截然不同。本文将从技术原理、架构设计、功能特性及适用场景等角度&#xff0c;深入分析两者的区别与优劣&#xff0c;并结合实际应用场景说明如何协同使用。 一、核心技术…...

    表单验证和正则表达式

    表单验证 表单&#xff1a;收集用户信息&#xff0c;并把信息发送给服务器程序进行处理 what 验证数据的格式&#xff0c;将符合标准数据格式要求的数据&#xff0c;发送给后台。 对用户的输入做格式校验&#xff0c;确保能够发送到后台服务器的数据一定是正确的。降低服务器…...

    汽车免拆诊断案例 | 保时捷车发动机偶发熄火故障 2 例

    案例1 2008款保时捷卡宴车行驶中发动机偶发熄火 故障现象  一辆2008款保时捷卡宴车&#xff0c;搭载4.8 L 自然吸气发动机&#xff0c;累计行驶里程约为21万km。车主反映&#xff0c;该车行驶中发动机偶发熄火&#xff1b;重新起动&#xff0c;发动机能够起动着机&#xff…...

    mongodb【实用教程】

    MongoDB 是一个开源的文档型数据库管理系统 下载安装 Windows 系统 https://blog.csdn.net/weixin_41192489/article/details/126777309 GUI工具 【推荐】MongoDB Compass https://www.mongodb.com/zh-cn/docs/compass/current/ Robo 3T https://blog.csdn.net/weixin_4119248…...

    Javaweb后端数据库多表关系一对多,外键,一对一

    多表关系 一对多 多的表里&#xff0c;要有一表里的主键 外键 多的表上&#xff0c;添加外键 一对一 多对多 案例...

    React(10)

    项目实践--创建项目 在store的modules中创建相关的子仓库暴露到仓库index文件中 导入creatSlice和axios 创建仓库 和数据的异步修改方法 // 编写store // 导入createSlice和axios import { createSlice } from "reduxjs/toolkit"; import axios from "axios&…...

    JAVA实战开源项目:靓车汽车销售网站(Vue+SpringBoot) 附源码

    本文项目编号 T 093 &#xff0c;文末自助获取源码 \color{red}{T093&#xff0c;文末自助获取源码} T093&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

    【大语言模型】【整合版】DeepSeek 模型提示词学习笔记(散装的可以看我之前的学习笔记,这里只是归纳与总结了一下思路,内容和之前发的差不多)

    以下是个人笔记的正文内容: 原文在FlowUs知识库上&#xff0c;如下截图。里面内容和这里一样&#xff0c;知识排版好看一点 一、什么是 DeepSeek 1. DeepSeek 简介 DeepSeek 是一家专注于通用人工智能&#xff08;AGI&#xff09;的中国科技公司&#xff0c;主攻大模型研发与…...

    网络安全扫描--基础篇

    前言 1、了解互联网安全领域中日趋重要的扫描技术 2、了解在不同网络场景下扫描技术手段 3、熟悉linux下系统内核防护策略并能大件一个有效的系统防护体系 4、增强工作安全意识&#xff0c;并能有效的实践于工作场景中 目录 1、熟悉主机扫描工具&#xff08;fping&#xff0c;…...