人脸检测算法——SCRFD

SCRFD算法核心解析

1. 算法定义与背景

SCRFD(Sample and Computation Redistribution for Efficient Face Detection)由Jia Guo等人于2021年在arXiv提出,是一种高效、高精度的人脸检测算法,其核心创新在于:

  • 双重重分配策略
    • 样本重分配(SR) :动态增强关键训练阶段的样本数据。
    • 计算重分配(CR) :通过神经架构搜索(NAS)优化骨干网络(Backbone)、颈部(Neck)和头部(Head)的计算负载。
  • 轻量化设计:支持从0.5GF到34GF的多规格模型,兼顾移动端与高性能设备。

2. 技术架构与创新
架构组成

  • 骨干网络(Backbone)
    • 基于ResNet变体(如CSPDarknet),通过残差连接解决深层网络训练难题。
    • 支持量化(FP16/INT8)降低计算量。
  • 颈部(Neck)
    • 采用 特征金字塔网络(FPN) 实现多尺度特征融合,增强小目标检测。
    • 引入PANet优化特征传递路径。
  • 头部(Head)
    • 基于FCOS(Focal Loss)实现无锚框检测,简化输出层。
    • 采用八参数回归直接预测边界框坐标。
核心创新机制
  • 计算重分配搜索算法
    • 训练阶段:通过NAS动态分配Backbone/Neck/Head的计算比例,最大化资源利用率。
    • 硬件加速
      • 存内计算:权重映射至硬件加速单元,减少数据传输。
      • 异构加速:支持GPU/TPU/NPU多平台部署。
      • 量化优化:FP16/INT8量化降低推理延迟。
3. 性能基准
WIDER FACE数据集表现
模型Easy AP (%)Medium AP (%)Hard AP (%)推理延迟 (ms)
SCRFD-34GF96.0694.9285.2911.7 (V100)
RetinaFace-R5094.9291.9064.1721.7 (V100)
数据来源:
  • 效率优势
    • SCRFD-34GF比RetinaFace-R50快 47%(11.7ms vs 21.7ms)。
    • SCRFD-0.5GF比RetinaFace-MobileNet0.25快 45.57%
跨设备优化
  • 边缘设备适配
    • 深度可分离卷积(如MobileNet)降低参数量。
    • 模型压缩:剪枝/蒸馏技术减少冗余计算。
  • 部署实践
    • NVIDIA Jetson系列:支持120 FPS实时推理。
    • 内存优化:Memssqueezer架构提升缓存命中率。

4. 与RetinaFace的深度对比
技术差异
维度SCRFDRetinaFace
检测机制无锚框(FCOS)基于锚框
计算分配动态重分配(CR策略)固定计算结构
硬件适配支持FP16/INT8量化依赖ResNet/MobileNet骨干
小目标检测FPN+多尺度融合优化传统特征金字塔
实战性能
  • 精度:SCRFD在Hard AP上领先RetinaFace 21.12%(85.29% vs 64.17%)。
  • 资源效率:SCRFD-34GF计算量仅为竞品TinaFace的 20%
  • 局限性:批量处理时RetinaFace可能更快。

5. 实现与应用
开源生态
  • 代码仓库:`https://github.com/deepinsight/insightface/tree/master/detection/scrfd。
  • 训练流程
    1. 数据加载:WIDER FACE/MS1M数据集。
    2. NAS搜索:优化Backbone/Neck/Head计算比例。
    3. 量化训练:FP16/INT8转换提升推理速度。
  • 部署示例
    # FastDeploy示例[[223]]
    from fastdeploy.vision import SCRFD
    model = SCRFD("scrfd_10g_fp32.onnx")
    results = model.predict(image)
    
论文资源
  • 核心文献
    Sample and Computation Redistribution for Efficient Face Detection(arXiv:2105.04714, 2021)。
  • 扩展研究
    后续改进融入Transformer架构及遥感检测。

结论

SCRFD通过三重革新——动态计算分配无锚框检测量化硬件适配——解决了人脸检测在精度与效率间的矛盾。其在WIDER FACE上85.29%的Hard AP及11.7ms的V100推理延迟,显著优于传统方案(如RetinaFace)。未来方向包括:

  1. 与Transformer架构结合强化遮挡处理。
  2. 自适应计算分配支持动态场景。
  3. 跨平台编译优化进一步压缩延迟。

代码:

class ONNXRuntimeModel:"""一个通用的ONNX模型推理封装类"""def __init__(self, onnx_path):# 使用ONNX Runtime的CUDA执行器providers = ['CUDAExecutionProvider', 'CPUExecutionProvider']self.session = ort.InferenceSession(onnx_path, providers=providers)self.input_name = self.session.get_inputs()[0].nameself.output_names = [output.name for output in self.session.get_outputs()]def __call__(self, input_tensor):# ONNX Runtime 需要 numpy array 作为输入input_feed = {self.input_name: input_tensor.cpu().numpy()}outputs = self.session.run(self.output_names, input_feed)return outputsclass SCRFD():def __init__(self, onnxmodel, confThreshold=0.5, nmsThreshold=0.5):self.inpWidth = 640self.inpHeight = 640self.confThreshold = confThresholdself.nmsThreshold = nmsThresholdself.session = ort.InferenceSession(onnxmodel, providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])self.keep_ratio = Trueself.fmc = 3self._feat_stride_fpn = [8, 16, 32]self._num_anchors = 2def resize_image(self, srcimg):padh, padw, newh, neww = 0, 0, self.inpHeight, self.inpWidthif self.keep_ratio and srcimg.shape[0] != srcimg.shape[1]:hw_scale = srcimg.shape[0] / srcimg.shape[1]if hw_scale > 1:newh, neww = self.inpHeight, int(self.inpWidth / hw_scale)img = cv2.resize(srcimg, (neww, newh), interpolation=cv2.INTER_AREA)padw = int((self.inpWidth - neww) * 0.5)img = cv2.copyMakeBorder(img, 0, 0, padw, self.inpWidth - neww - padw, cv2.BORDER_CONSTANT,value=0)  # add borderelse:newh, neww = int(self.inpHeight * hw_scale) + 1, self.inpWidthimg = cv2.resize(srcimg, (neww, newh), interpolation=cv2.INTER_AREA)padh = int((self.inpHeight - newh) * 0.5)img = cv2.copyMakeBorder(img, padh, self.inpHeight - newh - padh, 0, 0, cv2.BORDER_CONSTANT, value=0)else:img = cv2.resize(srcimg, (self.inpWidth, self.inpHeight), interpolation=cv2.INTER_AREA)return img, newh, neww, padh, padwdef distance2bbox(self, points, distance, max_shape=None):x1 = points[:, 0] - distance[:, 0]y1 = points[:, 1] - distance[:, 1]x2 = points[:, 0] + distance[:, 2]y2 = points[:, 1] + distance[:, 3]if max_shape is not None:x1 = x1.clamp(min=0, max=max_shape[1])y1 = y1.clamp(min=0, max=max_shape[0])x2 = x2.clamp(min=0, max=max_shape[1])y2 = y2.clamp(min=0, max=max_shape[0])return np.stack([x1, y1, x2, y2], axis=-1)def distance2kps(self, points, distance, max_shape=None):preds = []for i in range(0, distance.shape[1], 2):px = points[:, i % 2] + distance[:, i]py = points[:, i % 2 + 1] + distance[:, i + 1]if max_shape is not None:px = px.clamp(min=0, max=max_shape[1])py = py.clamp(min=0, max=max_shape[0])preds.append(px)preds.append(py)return np.stack(preds, axis=-1)def detect(self, srcimg):img, newh, neww, padh, padw = self.resize_image(srcimg)blob = cv2.dnn.blobFromImage(img, 1.0 / 128, (self.inpWidth, self.inpHeight), (127.5, 127.5, 127.5), swapRB=True)blob = np.ascontiguousarray(blob)# onnxruntime输入通常是NCHWort_inputs = {self.session.get_inputs()[0].name: blob}ort_outs = self.session.run(None, ort_inputs)outs = ort_outs  # 结构与原OpenCV DNN输出一致# 后续逻辑保持不变scores_list, bboxes_list, kpss_list = [], [], []for idx, stride in enumerate(self._feat_stride_fpn):scores = outs[idx][0]bbox_preds = outs[idx + self.fmc * 1][0] * stridekps_preds = outs[idx + self.fmc * 2][0] * strideheight = blob.shape[2] // stridewidth = blob.shape[3] // strideanchor_centers = np.stack(np.mgrid[:height, :width][::-1], axis=-1).astype(np.float32)anchor_centers = (anchor_centers * stride).reshape((-1, 2))if self._num_anchors > 1:anchor_centers = np.stack([anchor_centers] * self._num_anchors, axis=1).reshape((-1, 2))pos_inds = np.where(scores >= self.confThreshold)[0]bboxes = self.distance2bbox(anchor_centers, bbox_preds)pos_scores = scores[pos_inds]pos_bboxes = bboxes[pos_inds]scores_list.append(pos_scores)bboxes_list.append(pos_bboxes)kpss = self.distance2kps(anchor_centers, kps_preds)kpss = kpss.reshape((kpss.shape[0], -1, 2))pos_kpss = kpss[pos_inds]kpss_list.append(pos_kpss)scores = np.vstack(scores_list).ravel()bboxes = np.vstack(bboxes_list)kpss = np.vstack(kpss_list)bboxes[:, 2:4] = bboxes[:, 2:4] - bboxes[:, 0:2]ratioh, ratiow = srcimg.shape[0] / newh, srcimg.shape[1] / newwbboxes[:, 0] = (bboxes[:, 0] - padw) * ratiowbboxes[:, 1] = (bboxes[:, 1] - padh) * ratiohbboxes[:, 2] = bboxes[:, 2] * ratiowbboxes[:, 3] = bboxes[:, 3] * ratiohkpss[:, :, 0] = (kpss[:, :, 0] - padw) * ratiowkpss[:, :, 1] = (kpss[:, :, 1] - padh) * ratioh# NMS# 可用PyTorch或onnxruntime自带的NMS,也可以保留cv2.dnn.NMSBoxesif len(bboxes) == 0:return []bboxes_xyxy = np.stack([bboxes[:,0], bboxes[:,1], bboxes[:,0]+bboxes[:,2], bboxes[:,1]+bboxes[:,3]], axis=1)keep = torch.ops.torchvision.nms(torch.tensor(bboxes_xyxy, dtype=torch.float32), torch.tensor(scores, dtype=torch.float32), self.nmsThreshold)detections = []for i in keep:i = i.item()x1, y1 = int(bboxes[i, 0]), int(bboxes[i, 1])x2, y2 = int(bboxes[i, 0] + bboxes[i, 2]), int(bboxes[i, 1] + bboxes[i, 3])box = [x1, y1, x2, y2]score = float(scores[i])kps = kpss[i]detections.append([box, score, kps])return detections

这段代码实现了一个功能完整的人脸检测器。它使用了名为 SCRFD 的先进人脸检测模型,并通过 ONNX Runtime 库来运行这个模型,从而可以在不同的硬件(CPU或GPU)上高效执行。

代码的核心目标是:输入一张图片,输出图片中所有检测到的人脸信息,包括位置(边界框)、置信度分数和五官关键点


1. 整体结构概览

这个 SCRFD 类可以看作一个“黑盒子”。你只需要关心两件事:

  1. 初始化 (__init__): 告诉它你的模型文件在哪里,以及你对检测结果的要求(置信度、重叠框合并的阈值)。

  2. 检测 (detect): 给它一张图片,它会返回检测结果。

所有复杂的中间步骤,比如图像预处理、模型推理、结果后处理,都被封装在了类的内部方法中。


2. __init__ 构造函数:初始化检测器

class SCRFD():def __init__(self, onnxmodel, confThreshold=0.5, nmsThreshold=0.5):# 1. 设置模型输入尺寸self.inpWidth = 640self.inpHeight = 640# 2. 设置阈值self.confThreshold = confThreshold  # 置信度阈值self.nmsThreshold = nmsThreshold    # NMS阈值# 3. 加载ONNX模型self.session = ort.InferenceSession(onnxmodel, providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])# 4. 设置模型相关参数self.keep_ratio = Trueself.fmc = 3  # Feature Map Count, 每个输出头(score/bbox/kps)有3个特征图self._feat_stride_fpn = [8, 16, 32] # FPN的步长self._num_anchors = 2 # 每个位置的锚点数量

逐行解释:

  1. self.inpWidth, self.inpHeight: 定义了模型需要的标准输入图像尺寸为 640x640 像素。任何输入图片都会被调整到这个尺寸。

  2. self.confThreshold: 置信度阈值。模型会对每个可能的人脸位置给出一个分数(0到1之间),表示“这里是人脸”的可信度。只有分数高于这个阈值(默认0.5)的才会被认为是有效检测。

  3. self.nmsThreshold: 非极大值抑制 (NMS) 阈值。模型可能会对同一个脸输出多个高度重叠的边界框。NMS算法会移除多余的框,只保留最好的一个。这个阈值决定了两个框重叠到什么程度才算“多余”。

  4. self.session = ort.InferenceSession(...): 这是核心部分。它使用 onnxruntime 库加载你提供的 .onnx 模型文件。providers 参数指定了推理后端,'CUDAExecutionProvider' 表示优先使用NVIDIA GPU(如果可用),否则回退到 'CPUExecutionProvider' 使用CPU。

  5. self.keep_ratio: 一个布尔标志,决定在调整图像大小时是否保持原始图像的宽高比。True 表示保持,这可以防止人脸变形,提高检测精度。

  6. self.fmc, _feat_stride_fpn, _num_anchors: 这些是与SCRFD模型架构紧密相关的超参数。

    • _feat_stride_fpn = [8, 16, 32]: SCRFD使用了特征金字塔网络(FPN),它在不同大小的特征图上进行预测。步长(stride)为8的特征图用来检测小人脸,16的检测中等大小人脸,32的检测大人脸。

    • _num_anchors = 2: 在特征图的每个位置,模型会预设2个不同尺寸的“锚点框”(anchor),并基于这些锚点框进行预测。


3. resize_image 方法:图像预处理

def resize_image(self, srcimg):# ... (代码)

这个函数负责将你输入的任意尺寸的原始图像 (srcimg) 转换成模型需要的 640x640 格式。

  • 如果 self.keep_ratio 为 True (默认):

    1. 计算原始图像的宽高比。

    2. 将图像等比例缩放,使其最长边等于640。

    3. 为了补足到 640x640,在较短的那一边上下或左右填充黑边 (cv2.copyMakeBorder)。

    4. 返回处理后的图像 (img) 以及填充的尺寸信息 (padh, padw),这些信息在后续恢复坐标时至关重要。

  • 如果 self.keep_ratio 为 False:

    • 它会粗暴地将图像直接拉伸或压缩到 640x640,这可能会导致人脸变形。


4. distance2bbox 和 distance2kps 方法:解码模型输出

def distance2bbox(self, points, distance, max_shape=None):# ... (代码)
def distance2kps(self, points, distance, max_shape=None):# ... (代码)

SCRFD模型的一个特点是,它不直接预测边界框的坐标 (x1, y1, x2, y2)。相反,它预测的是:

  • 对于每个“锚点”,其中心到真实人脸边界框四条边的距离。

  • 对于每个“锚点”,其中心到真实人脸每个关键点的位移。

这两个函数就是用来做逆运算的,将模型输出的“距离/位移”解码成我们能理解的“坐标”。

  • distance2bbox: 输入锚点中心坐标 (points) 和模型预测的4个距离值 (distance),计算出最终的边界框坐标 [x1, y1, x2, y2]。

  • distance2kps: 输入锚点中心坐标 (points) 和模型预测的关键点位移 (distance),计算出最终的5个关键点坐标 [x_eye1, y_eye1, x_eye2, y_eye2, ...]。


5. detect 方法:核心检测流程

这是整个类的“主心骨”,它串联起了所有步骤。

def detect(self, srcimg):# 步骤1: 图像预处理img, newh, neww, padh, padw = self.resize_image(srcimg)blob = cv2.dnn.blobFromImage(img, 1.0 / 128, (self.inpWidth, self.inpHeight), (127.5, 127.5, 127.5), swapRB=True)# 步骤2: 模型推理ort_inputs = {self.session.get_inputs()[0].name: blob}ort_outs = self.session.run(None, ort_inputs)# 步骤3: 结果后处理与解码# ... (循环处理不同stride的输出)for idx, stride in enumerate(self._feat_stride_fpn):# 从模型输出中提取 score, bbox, kps# 创建锚点网格# 筛选出分数 > confThreshold 的结果# 使用 distance2bbox 和 distance2kps 解码# ...# 步骤4: 整合与坐标还原# ... (合并所有stride的结果)# 将坐标从 640x640 的填充图映射回原始图像# 步骤5: 非极大值抑制 (NMS)# ...keep = torch.ops.torchvision.nms(...) # 使用PyTorch的NMS# 步骤6: 格式化输出# ...# 将最终保留下来的结果整理成 [box, score, kps] 的格式并返回return detections

详细流程分解:

  1. 图像预处理:

    • 调用 resize_image 将图片调整为带黑边填充的 640x640 图像。

    • cv2.dnn.blobFromImage: 这是非常关键的一步。它将图像转换为一个“Blob”,也就是模型需要的4D张量格式 (N, C, H, W)。同时,它还做了两件事:

      • 归一化: 1.0 / 128 和 (127.5, 127.5, 127.5) 将像素值从 [0, 255] 范围转换到 [-1, 1] 范围。

      • 通道转换: swapRB=True 将OpenCV默认的BGR顺序转换为模型需要的RGB顺序。

  2. 模型推理:

    • 将 blob 作为输入,调用 self.session.run 执行模型推理,得到模型的原始输出 ort_outs。ort_outs 是一个包含多个Numpy数组的列表,分别对应人脸分数、边界框距离和关键点位移。

  3. 结果后处理与解码:

    • 这是一个循环,分别处理来自步长8、16、32的三个特征图的预测结果。

    • 对于每个特征图:

      • 它首先生成该特征图上所有的锚点中心坐标 (anchor_centers)。

      • 然后,它用 self.confThreshold 过滤掉所有置信度低的结果。

      • 最后,对保留下来的高置信度结果,调用 distance2bbox 和 distance2kps 将其解码为实际的边界框和关键点坐标。

  4. 整合与坐标还原:

    • 将三个特征图解码出的所有结果(框、分数、关键点)合并在一起。

    • 坐标还原:这是至关重要的一步。因为之前的预测都是基于640x640的填充图像,现在需要利用 resize_image 返回的 ratioh, ratiow, padh, padw,通过数学计算,将坐标映射回原始输入图像的尺寸和位置。

  5. 非极大值抑制 (NMS):

    • 此时,我们可能有很多重叠的框。torch.ops.torchvision.nms 函数会根据 self.nmsThreshold 剔除冗余的检测框,只为每个真实人脸保留一个得分最高的框。

  6. 格式化输出:

    • 遍历NMS后保留下来的结果索引 keep。

    • 将每个检测结果整理成一个包含 [边界框, 分数, 关键点] 的列表。

    • 返回这个包含所有检测结果的列表。


总结

这个 SCRFD 类是一个高度封装、流程清晰的人脸检测器。其工作流可以总结为:

输入原图 -> 预处理(缩放/填充/归一化) -> 模型推理 -> 解码(将模型输出转为坐标) -> 坐标还原(映射回原图) -> NMS(去重) -> 输出最终结果

你只需要准备好一个 scrfd_..._.onnx 模型文件(已发布在我的资源),然后像下面这样使用它:

import cv2
import numpy as np
import onnxruntime as ort
import torch # NMS需要torch# 假设你的 SCRFD 类代码保存在 scrfd.py 文件中# 1. 初始化检测器
model_path = "scrfd_2.5g_kps.onnx" # 你的模型路径
face_detector = SCRFD(onnxmodel=model_path, confThreshold=0.5, nmsThreshold=0.5)# 2. 读取图片
image = cv2.imread("your_image.jpg")# 3. 执行检测
detections = face_detector.detect(image)# 4. 可视化结果
if detections:print(f"检测到 {len(detections)} 张人脸。")for box, score, kps in detections:x1, y1, x2, y2 = box# 画框cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)# 画关键点for i in range(kps.shape[0]):cv2.circle(image, (int(kps[i, 0]), int(kps[i, 1])), 2, (0, 0, 255), -1)# 显示结果
cv2.imshow("Detected Faces", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91640.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3+ts+elementui-表格根据相同值合并

代码<div style"height: auto; overflow: auto"><el-table ref"dataTableRef" v-loading"loading" :data"pageData" highlight-current-row borderselection-change"handleSelectionChange" :span-method"obj…

UI前端与数字孪生融合案例:智慧城市的智慧停车引导系统

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;停车难的 “城市痛点” 与数字孪生的破局之道当司机在商圈绕圈 30 分钟仍…

java+vue+SpringBoot集团门户网站(程序+数据库+报告+部署教程+答辩指导)

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿ppt部署教程代码讲解代码时间修改工具 技术实现 开发语言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot数据库&#xff1a;mysql 开发工具 JDK版本&#xff1a;JDK1.8 数…

【Docker基础】Docker-compose从入门到精通:安装指南与核心命令全解析

目录 前言 1 Docker-compose核心概念解析 1.1 什么是Docker-compose&#xff1f; 1.2 典型应用场景 2 Docker-compose离线安装详解 2.1 离线安装背景与优势 2.2 详细安装步骤 步骤1&#xff1a;获取离线安装包 步骤2&#xff1a;文件部署与权限设置 步骤3&#xff1a…

面试150 被围绕的区域

思路 使用DFS&#xff0c;将所有与边界相连的’O’都修改为‘#’,然后遍历数组&#xff0c;如果是遇到’#‘修改为’O’,如果是’O’修改为’X’。 class Solution:def solve(self, board: List[List[str]]) -> None:"""Do not return anything, modify boar…

(数据结构)线性表(上):SeqList 顺序表

线性表&#xff08;上&#xff09;&#xff1a;Seqlist 顺序表基本了解线性表顺序表静态顺序表动态顺序表编写动态顺序表项目结构基础结构初始化尾插头插尾删头删查找指定位置pos之前插入数据删除指定位置pos的数据销毁完整代码SeqLIst.hSeqLIst.ctest.c算法题移除元素删除有序…

WebStorm vs VSCode:前端圈的「豆腐脑甜咸之争」

目录 一、初识两位主角&#xff1a;老司机与新势力 二、开箱体验&#xff1a;是「拎包入住」还是「毛坯房改造」 三、智能提示&#xff1a;是「知心秘书」还是「百度搜索」 四、调试功能&#xff1a;是「CT 扫描仪」还是「听诊器」 五、性能表现&#xff1a;是「重型坦克」…

C#将类属性保存到Ini文件方法(利用拓展方法,反射方式获取到分组名和属性名称属性值)

前言&#xff1a;最近学习C#高级课程&#xff0c;里面学到了利用反射和可以得到属性的特性、属性名、属性值&#xff0c;还有拓展方法&#xff0c;一直想将学到的东西利用起来&#xff0c;刚好今天在研究PropertyGrid控件时&#xff0c;想方便一点保存属性值到配置文件&#xf…

kafka 单机部署指南(KRaft 版本)

目录环境准备JDK安装下载jdkjdk安装kafka 部署kafka 下载kafka 版本号结构解析kafka 安装下载和解压安装包配置 KRaft 模式格式化存储目录启动kafkaKafka 配置为 systemd 服务注意事项调整 JVM 内存参数Kafka KRaft 版本&#xff08;即 Kafka 3.0 及更高版本&#xff09;使用 K…

websocket案例 599足球比分

目标地址:aHR0cHM6Ly93d3cuNTk5LmNvbS9saXZlLw接口:打开控制台 点websocket 刷新页面 显示分析:不写理论了关于websocket 几乎发包位置都是下方图片 不管抖音还是快手 等平台这里在进行 new WebSocket 后 是要必须走一步的 也就是 new WebSocket().onopen() 也就是onopen 进行向…

【后端】Linux系统发布.NetCore项目

目录 1.设置全球化不变模式 1.发布到文件 3. 配置为服务 3.1.添加服务 3.2.添加执行权限 3.3.启动服务 4.访问 1.设置全球化不变模式 双击所需项目&#xff0c;设置全球化不变模式 <!-- 设置全球化不变模式 --><RuntimeHostConfigurationOption>System.Globa…

CMU-15445(2024fall)——PROJECT#0

题目介绍 这是题目原文。 注意&#xff1a;在拉取项目的时候需要注意拉取2024fall的Tag&#xff0c;本人血泪教训&#xff01; 本题是关于HyperLogLog的具体实现&#xff0c;其介绍可以看这个视频进行了解。简单来说HyperLogLog可以在一个非常小的固定内存下&#xff08;一般…

使用微信免费的图像处理接口,来开发图片智能裁剪和二维码/条码识别功能,爽歪歪

大家好&#xff0c;我是小悟。 1、图片智能裁剪 我们先来了解一下图片智能裁剪。图片智能裁剪聚焦于数字图像的智能化处理。AI技术的引入彻底改变了传统依赖人工框选的裁剪模式。 通过深度学习模型自动识别图像主体&#xff08;人物、商品等&#xff09;&#xff0c;能在极短时…

【代码随想录】+ leetcode hot100:栈与队列算法专题总结、单调栈

大家好&#xff0c;我是此林。 今天分享的是【代码随想录】栈与队列算法专题总结&#xff0c;分享刷算法的心得体会。 1. 用栈实现队列、用队列实现栈 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09;…

《5分钟开发订单微服务!飞算JavaAI实战:IDEA插件安装→空指针修复→K8s部署全流程》

目录 40倍提升开发效能的秘密武器 一、为什么选择飞算JavaAI&#xff1f;​编辑 二、IDEA插件安装三步曲&#xff08;极简版&#xff09; 步骤1&#xff1a;安装插件&#xff08;30秒完成&#xff09; 步骤2&#xff1a;账号登录&#xff08;2种方式任选&#xff09; 方式…

SQL注入基础尝试

进入网址&#xff0c;测试正常回显和出错画面http://1bcf75af-6e69-4f78-ac71-849fb8cde1b5.node5.buuoj.cn/Less-2/? id1用特殊符号判断注入点判断其类型类型为数字型&#xff0c;order by判断列数当数字为4时候报错而3不报错&#xff0c;由此推断列数为3&#xff0c;接着测试…

[Dify] -进阶4-在 Dify 中实现 PDF 文档问答功能全流程

随着业务需求增加,AI 应用常遇到让模型“读懂”PDF并回答问题的场景。借助 Dify 的 RAG(Retrieval‑Augmented Generation)能力,我们可以构建一个“ChatPDF”式的互动问答机器人。本文详细讲解从环境搭建、PDF 上传、文本抽取、向量检索到问答部署的完整流程。 一、技术栈与…

【EPLAN 2.9】许可证xx成功却显示红色叉,无法启动

问题现象&#xff1a; 无法启动。 原因&#xff1a;通过mstsc远程桌面连接会占用显卡&#xff0c;导致调用显卡的软件无法成功。参考&#xff1a;Windows自带远程桌面(mstsc)在远程时无法启动&#xff08;打开&#xff09;某些应用&#xff08;软件&#xff09;的解决办法 编写…

Oracle ADG 一键自动化搭建脚本

前言在 Oracle 数据库高可用架构中&#xff0c;Active Data Guard (ADG) 是保障数据安全和业务连续性的核心方案。然而传统 ADG 搭建涉及数十项复杂配置&#xff08;监听、TNSNAMES、参数文件、密码文件、日志传输、应用服务等&#xff09;&#xff0c;步骤繁琐且易错&#xff…

某邮生活旋转验证码识别

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 本文识别已同步上线至OCR识别网站: http://yxlocr.nat300.top/ocr/other/30 旋转验证码数据集如下: 看起来很像顶象的,都有着绿边干扰,那其实思路也能简单了,…