CV - 目标检测

物体检测

目标检测和图片分类的区别:

图像分类(Image Classification)

目的:图像分类的目的是识别出图像中主要物体的类别。它试图回答“图像是什么?”的问题。
输出:通常输出是一个标签或一组概率值,表示图像属于各个预定义类别的可能性。例如,对于一张包含猫的图片,分类器可能会输出“猫”这个标签。
应用场景:适用于只需要了解图像整体内容的场景,如识别照片中的动物种类、区分不同的风景类型等。

目标检测(Object Detection)

目的:目标检测不仅需要识别图像中所有感兴趣物体的类别,还需要确定每个物体在图像中的具体位置。它试图回答“图像中有什么?它们在哪里?”的问题。
输出:除了给出物体的类别外,还会输出物体所在的边界框(bounding box),即用矩形框标记出每个物体的位置。例如,在自动驾驶场景下,系统不仅要能识别出行人、车辆等物体,还要精确地定位它们的位置以便做出安全决策。
应用场景:适合于需要知道图像内特定对象位置的情况,比如视频监控、自动驾驶汽车、医学影像分析等领域。

边缘框

  • 一个边缘框可以通过 4 个数字定义
    • (左上 x,左上 y,右下 x,右下 y)
    • (左上 x,左上 y,宽,高)
      在这里插入图片描述

目标检测数据集

  • 每行表示一个物体
    • 图片文件名,物体类别,边缘框
  • COCO (cocodataset.org)
    • 80 物体,330K 图片,1.5M 物体

总结

  • 物体检测识别图片里的多个物体的类别和位置
  • 位置通常用边缘框表示。

边缘框实现

%matplotlib inline
import torch
from d2l import torch as d2ld2l.set_figsize()
img = d2l.plt.imread('../img/catdog.jpg')
d2l.plt.imshow(img);

在这里插入图片描述
定义在这两种表示法之间进行转换的函数

#@save
def box_corner_to_center(boxes):"""从(左上,右下)转换到(中间,宽度,高度)"""x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]cx = (x1 + x2) / 2cy = (y1 + y2) / 2w = x2 - x1h = y2 - y1boxes = torch.stack((cx, cy, w, h), axis=-1)return boxes#@save
def box_center_to_corner(boxes):"""从(中间,宽度,高度)转换到(左上,右下)"""cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]x1 = cx - 0.5 * wy1 = cy - 0.5 * hx2 = cx + 0.5 * wy2 = cy + 0.5 * hboxes = torch.stack((x1, y1, x2, y2), axis=-1)return boxes

定义图像中狗和猫的边界框

# bbox是边界框的英文缩写
dog_bbox, cat_bbox = [60.0, 45.0, 378.0, 516.0], [400.0, 112.0, 655.0, 493.0]boxes = torch.tensor((dog_bbox, cat_bbox))
box_center_to_corner(box_corner_to_center(boxes)) == boxes

在这里插入图片描述
将边界框在图中画出

#@save
def bbox_to_rect(bbox, color):# 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式:# ((左上x,左上y),宽,高)return d2l.plt.Rectangle(xy=(bbox[0], bbox[1]), width=bbox[2]-bbox[0], height=bbox[3]-bbox[1],fill=False, edgecolor=color, linewidth=2)fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'));

在这里插入图片描述

数据集

李沐老师收集并标记了一个小型数据集,下面首先是下载该数据集:

%matplotlib inline
import os
import pandas as pd
import torch
import torchvision
from d2l import torch as d2l#@save
d2l.DATA_HUB['banana-detection'] = (d2l.DATA_URL + 'banana-detection.zip','5de26c8fce5ccdea9f91267273464dc968d20d72')

读取香蕉检测数据集

#@save
def read_data_bananas(is_train=True):"""读取香蕉检测数据集中的图像和标签"""data_dir = d2l.download_extract('banana-detection')csv_fname = os.path.join(data_dir, 'bananas_train' if is_trainelse 'bananas_val', 'label.csv')csv_data = pd.read_csv(csv_fname)csv_data = csv_data.set_index('img_name')images, targets = [], []for img_name, target in csv_data.iterrows():images.append(torchvision.io.read_image(os.path.join(data_dir, 'bananas_train' if is_train else'bananas_val', 'images', f'{img_name}')))# 这里的target包含(类别,左上角x,左上角y,右下角x,右下角y),# 其中所有图像都具有相同的香蕉类(索引为0)targets.append(list(target))return images, torch.tensor(targets).unsqueeze(1) / 256

创建一个自定义 Dataseet 实例:

#@save
class BananasDataset(torch.utils.data.Dataset):"""一个用于加载香蕉检测数据集的自定义数据集"""def __init__(self, is_train):self.features, self.labels = read_data_bananas(is_train)print('read ' + str(len(self.features)) + (f' training examples' ifis_train else f' validation examples'))def __getitem__(self, idx):return (self.features[idx].float(), self.labels[idx])def __len__(self):return len(self.features)

为训练集和测试集返回两个数据加载器实例

#@save
def load_data_bananas(batch_size):"""加载香蕉检测数据集"""train_iter = torch.utils.data.DataLoader(BananasDataset(is_train=True),batch_size, shuffle=True)val_iter = torch.utils.data.DataLoader(BananasDataset(is_train=False),batch_size)return train_iter, val_iter

读取一个小批量,并打印其中的图像和标签的形状

batch_size, edge_size = 32, 256
train_iter, _ = load_data_bananas(batch_size)
batch = next(iter(train_iter))
batch[0].shape, batch[1].shape

在这里插入图片描述
演示:

imgs = (batch[0][0:10].permute(0, 2, 3, 1)) / 255
axes = d2l.show_images(imgs, 2, 5, scale=2)
for ax, label in zip(axes, batch[1][0:10]):d2l.show_bboxes(ax, [label[0][1:5] * edge_size], colors=['w'])

在这里插入图片描述

QA 思考

Q1:如果在工业检测中数据集非常小(近百张),除了进行数据增强外,还有什么更好的方法吗?
A1:迁移学习:找一个非常好的,在一个比较大的目标检测数据集上训练的比较好的模型,然后拿过来进行微调。近百张其实也不算小的了,只是说模型训练出来不是很好。数据增强的话,对图像进行处理,对应的框也必须要相应的变化一下,这是比较麻烦的点。

后记

自己实现了一遍,然后也是使用的李沐老师在课件中提供的狗猫图片:

import torch
from matplotlib import pyplot as plt
from PIL import Imagedef set_image_display_size():plt.figure(figsize=(8, 6))def load_image(img_path):return Image.open(img_path)def show_single_image(img):plt.imshow(img)plt.axis('on')  # 显示坐标轴plt.show()def box_corner_to_center(boxes):x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]cx = (x1 + x2) / 2cy = (y1 + y2) / 2w = x2 - x1h = y2 - y1boxes = torch.stack((cx, cy, w, h), axis=-1)return boxesdef box_center_to_corner(boxes):# 这里向左和向上都是减小的cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]x1 = cx - 0.5 * wy1 = cy - 0.5 * hx2 = cx + 0.5 * wy2 = cy + 0.5 * hboxes = torch.stack((x1, y1, x2, y2), axis=-1)return boxesdef bbox_to_rect(bbox, color):# 将边界框(左上x, 左上y, 右下x, 右下y)格式转换成matplotlib格式:# ((左上x, 左上y), 宽, 高)return plt.Rectangle(xy=(bbox[0], bbox[1]), width=bbox[2] - bbox[0], height=bbox[3] - bbox[1],fill=False, edgecolor=color, linewidth=2)if __name__ == "__main__":# 设置图像显示大小set_image_display_size()# 加载图像img_path = '../image/catdog.jpg'  # 确保路径正确img = load_image(img_path)show_single_image(img)# dog, cat 边界框dog_bbox, cat_bbox = [60.0, 45.0, 378.0, 516.0], [400.0, 112.0, 655.0, 493.0]# 转换为张量并测试转换函数是否正确boxes = torch.tensor((dog_bbox, cat_bbox))converted_boxes = box_center_to_corner(box_corner_to_center(boxes))# torch.allclose,判断两个张量是否在一定容差范围内相等。print("转换是否一致:", torch.allclose(converted_boxes, boxes))# 显示图像并绘制边界框,imshow 将 img 显示在画布上fig = plt.imshow(img)# add_patch 是 matplotlib 中用于在坐标轴上添加图形元素(如矩形、圆形等)的函数fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))  # 狗的边界框fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))  # 猫的边界框plt.show()

我在colab上跑了一下下面的代码,发现可以,下载不了的可能需要一点 “魔法”

import hashlib
import os
import tarfile
import zipfile
import pandas as pd
import requests
import torch
import torchvisionfrom matplotlib import pyplot as plt"""这段代码本身并没有包含训练过程。它只是加载了已经标注好的香蕉检测数据集,并可视化了图像及其对应的边界框。这些边界框信息是预先标注好的(存储在 CSV 文件中),而不是通过模型训练得到的。read_data_bananas 函数读取数据集中的图像和标签:图像存储在文件夹中(如 bananas_train/images/)。标签存储在 CSV 文件中(如 bananas_train/label.csv)。每个标签包括图像名称、目标类别(香蕉类别的索引为 0)、以及边界框坐标。zip 结构类似如下:banana-detection/├── bananas_train/│   ├── images/│   │   ├── image1.jpg│   │   ├── image2.jpg│   │   └── ...│   └── label.csv  # 包含每张图像的标注信息(即边界框和类别)└── bananas_val/├── images/│   ├── image1.jpg│   ├── image2.jpg│   └── ...└── label.csv
"""
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'DATA_HUB['banana-detection'] = (DATA_URL + 'banana-detection.zip','5de26c8fce5ccdea9f91267273464dc968d20d72')def download(name, cache_dir=os.path.join('..', 'data')):"""下载一个DATA_HUB中的文件,返回本地文件名"""# assert 条件, 错误信息assert name in DATA_HUB, f"{name} 不存在于 {DATA_HUB}""""url:文件的下载地址。 http://d2l-data.s3-accelerate.amazonaws.com/banana-detection.zipsha1_hash:文件内容的 SHA-1 校验值,用于验证文件完整性。5de26c8fce5ccdea9f91267273464dc968d20d72"""url, sha1_hash = DATA_HUB[name]"""递归创建目录:包括所有必要的父目录。避免重复创建导致的错误:如果目录已经存在,不会抛出异常。"""os.makedirs(cache_dir, exist_ok=True)"""url.split('/')[-1]:提取 URL 路径的最后一部分(通常是文件名)。os.path.join(cache_dir, ...):将缓存目录和文件名组合成完整的本地文件路径。"""fname = os.path.join(cache_dir, url.split('/')[-1])  # fname = ../data/banana-detection.zipif os.path.exists(fname):  # 文件存在,进入校验流程# 创建一个 SHA-1 哈希对象,用于计算文件的哈希值。sha1 = hashlib.sha1()# 以二进制模式读取文件with open(fname, 'rb') as f:while True:# 每次读取 1MB 数据(1048576 字节),更新哈希对象。data = f.read(1048576)# 为空,退出循环if not data:break# 将读取的数据块逐步添加到哈希计算中sha1.update(data)"""计算哈希值:调用 sha1.hexdigest() 获取最终的 SHA-1 哈希值(40 个字符的十六进制字符串)。校验哈希值:将计算得到的哈希值与预期的哈希值 sha1_hash 进行比较。如果两者相等,说明文件完整且未被篡改,直接返回文件路径(命中缓存)。否则,继续执行下载逻辑。"""if sha1.hexdigest() == sha1_hash:return fname  # 命中缓存print(f'正在从{url}下载{fname}...')"""使用 requests.get 方法发送 HTTP 请求,从远程服务器下载文件。参数说明:stream=True:以流式方式下载文件,避免一次性加载整个文件到内存中。verify=True:启用 SSL 证书验证,确保安全连接。"""r = requests.get(url, stream=True, verify=True)"""打开本地文件 fname,以二进制写入模式('wb')创建或覆盖文件。将下载的内容 r.content 写入文件。下载完成后,关闭文件。"""with open(fname, 'wb') as f:f.write(r.content)return fnamedef download_extract(name, folder=None):"""下载并解压zip/tar文件"""fname = download(name)  # 下载文件的完整路径"""os.path.dirname(fname):提取文件所在的目录路径(即父目录)。例如,如果 fname 是 '../data/example.zip',则 base_dir 是 '../data'。os.path.splitext(fname):将文件路径拆分为文件名和扩展名。例如,如果 fname 是 '../data/example.zip',则 data_dir 是 '../data/example',ext 是 '.zip'。"""base_dir = os.path.dirname(fname)data_dir, ext = os.path.splitext(fname)if ext == '.zip':fp = zipfile.ZipFile(fname, 'r')elif ext in ('.tar', '.gz'):fp = tarfile.open(fname, 'r')else:assert False, '只有zip/tar/gz 文件可以被解压缩'# 解压文件到指定的目录 base_dirfp.extractall(base_dir)"""如果 folder 参数存在:返回 os.path.join(base_dir, folder),即解压后目录下的指定子目录。如果 folder 参数不存在:返回 data_dir,即解压后的默认目录。"""return os.path.join(base_dir, folder) if folder else data_dirdef read_data_bananas(is_train=True):"""读取香蕉检测数据集中的图像和标签"""data_dir = download_extract('banana-detection')"""根据 is_train 参数,确定加载训练集还是验证集的标注文件:如果 is_train=True,加载 'bananas_train/label.csv'。如果 is_train=False,加载 'bananas_val/label.csv'。使用 pandas 库的 read_csv 方法读取 CSV 文件内容。将 img_name 列设置为索引列(方便后续按图像名称访问数据)。"""csv_fname = os.path.join(data_dir, 'bananas_train' if is_trainelse 'bananas_val', 'label.csv')  # for example: ../data/banana-detection/banana_train/label.csvcsv_data = pd.read_csv(csv_fname)  # 读取 csv 文件# 将 img_name 列设置为索引列csv_data = csv_data.set_index('img_name')"""images:用于存储读取的图像数据。targets:用于存储每张图像对应的标注信息。"""images, targets = [], []"""img_name:当前行的索引值(即图像名称)。target:当前行的数据(即标注信息)。"""for img_name, target in csv_data.iterrows():images.append(torchvision.io.read_image(os.path.join(data_dir, 'bananas_train' if is_train else'bananas_val', 'images', f'{img_name}')))# 这里的target包含(类别,左上角x,左上角y,右下角x,右下角y),# 其中所有图像都具有相同的香蕉类(索引为0)targets.append(list(target))"""images:图像数据列表。torch.tensor(targets).unsqueeze(1) / 256:将 targets 转换为 PyTorch 张量。使用 unsqueeze(1) 在维度 1 上增加一个维度,使其形状变为 (N, 1, 5),其中 N 是样本数量,5 是每个标注信息的长度。所有边界框坐标除以 256,进行归一化处理(假设图像大小为 256x256)。"""return images, torch.tensor(targets).unsqueeze(1) / 256class BananasDataset(torch.utils.data.Dataset):"""一个用于加载香蕉检测数据集的自定义数据集"""def __init__(self, is_train):self.features, self.labels = read_data_bananas(is_train)print('read ' + str(len(self.features)) + (f' training examples' ifis_train else f' validation examples'))# such as : read 1000 training examplesdef __getitem__(self, idx):return self.features[idx].float(), self.labels[idx]def __len__(self):return len(self.features)def load_data_bananas(batch_size):"""加载香蕉检测数据集"""train_iter = torch.utils.data.DataLoader(BananasDataset(is_train=True),batch_size, shuffle=True)val_iter = torch.utils.data.DataLoader(BananasDataset(is_train=False),batch_size)return train_iter, val_iterdef show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):figsize = (num_cols * scale, num_rows * scale)"""_:表示整个图形对象(这里用下划线忽略)axes:表示所有子图的数组"""_, axes = plt.subplots(num_rows, num_cols, figsize=figsize)axes = axes.flatten()for i, (ax, img) in enumerate(zip(axes, imgs)):if torch.is_tensor(img):ax.imshow(img.numpy())else:ax.imshow(img)ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axesdef bbox_to_rect(bbox, color):"""将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式:((左上x,左上y),宽,高)"""return plt.Rectangle(xy=(bbox[0], bbox[1]), width=bbox[2] - bbox[0], height=bbox[3] - bbox[1],fill=False, edgecolor=color, linewidth=2)# 定义一个名为 numpy 的函数,它能够将 PyTorch 张量转换为 NumPy 数组,并且自动处理张量的梯度信息
numpy = lambda x, *args, **kwargs: x.detach().numpy(*args, **kwargs)def show_bboxes(axes, bboxes, labels=None, colors=None):"""显示所有边界框""""""功能:将输入对象转换为列表形式。如果 obj 是 None,返回默认值 default_values。如果 obj 不是列表或元组,则将其包装成单元素列表。否则,直接返回 obj。作用:确保 labels 和 colors 参数始终是列表形式,以便后续迭代操作。"""def _make_list(obj, default_values=None):if obj is None:obj = default_valueselif not isinstance(obj, (list, tuple)):obj = [obj]return obj"""将 labels 转换为列表形式。如果未提供标签,则返回空列表。将 colors 转换为列表形式。如果未提供颜色,则使用默认颜色列表 ['b', 'g', 'r', 'm', 'c'](蓝色、绿色、红色、洋红色、青色)。"""labels = _make_list(labels)colors = _make_list(colors, ['b', 'g', 'r', 'm', 'c'])"""遍历 bboxes 列表中的每个边界框 bbox。根据索引 i,从 colors 列表中循环选择颜色(防止颜色不足时重复使用)。调用 bbox_to_rect 函数,将边界框坐标转换为 Matplotlib 的矩形对象。假设 bbox_to_rect 是一个已定义的函数,用于将边界框坐标转换为 matplotlib.patches.Rectangle 对象。numpy(bbox):将边界框数据转换为 NumPy 数组(假设 bbox 是 PyTorch 张量)。使用 axes.add_patch(rect) 将矩形添加到绘图区域中。"""for i, bbox in enumerate(bboxes):color = colors[i % len(colors)]rect = bbox_to_rect(numpy(bbox), color)axes.add_patch(rect)"""检查是否提供了标签,并且当前索引 i 在标签范围内。根据边界框颜色选择标签文字的颜色:如果边界框颜色为白色('w'),标签文字颜色为黑色('k')。否则,标签文字颜色为白色('w')。使用 axes.text 方法,在边界框的左上角位置添加标签文本。rect.xy[0] 和 rect.xy[1]:矩形左上角的 x 和 y 坐标。va='center' 和 ha='center':设置文本垂直和水平居中对齐。fontsize=9:设置字体大小为 9。color=text_color:设置文本颜色。bbox=dict(facecolor=color, lw=0):为文本添加背景框,背景颜色与边界框一致,边框宽度为 0。"""if labels and len(labels) > i:text_color = 'k' if color == 'w' else 'w'axes.text(rect.xy[0], rect.xy[1], labels[i],va='center', ha='center', fontsize=9, color=text_color,bbox=dict(facecolor=color, lw=0))if __name__ == "__main__":batch_size, edge_size = 32, 256train_iter, _ = load_data_bananas(batch_size)"""使用 iter(train_iter) 创建一个迭代器对象。调用 next() 获取迭代器的第一个批次的数据。"""batch = next(iter(train_iter))"""torch.Size([32, 3, 256, 256]):表示 32 张 RGB 图像,每张图像大小为 256x256。torch.Size([32, num_boxes, 5]):表示每张图像有 num_boxes 个边界框,每个边界框包含 5 个值(类别 + 坐标)。    """print(batch[0].shape, batch[1].shape)"""功能:batch[0][0:10]:从 batch[0] 中提取前 10 张图像。.permute(0, 2, 3, 1):调整张量的维度顺序,将 (N, C, H, W) 转换为 (N, H, W, C),即从 PyTorch 的默认格式转换为适合显示的格式。/ 255:将像素值归一化到 [0, 1] 范围(假设原始像素值范围是 [0, 255])。结果:imgs 是一个形状为 (10, 256, 256, 3) 的张量,表示 10 张归一化的 RGB 图像。"""imgs = (batch[0][0:10].permute(0, 2, 3, 1)) / 255axes = show_images(imgs, 2, 5, scale=2)for ax, label in zip(axes, batch[1][0:10]):"""label[0][1:5]:提取第一个边界框的坐标信息([x_min, y_min, x_max, y_max])。* edge_size:将归一化的坐标值还原为原始像素坐标。show_bboxes(ax, ...):在子图 ax 上绘制边界框,颜色为白色 ('w')。"""show_bboxes(ax, [label[0][1:5] * edge_size], colors=['w'])plt.show()
"""
归一化是为了模型训练:确保输入数据在合理的范围内,加速收敛并提高稳定性。
还原是为了可视化:将数据转换回原始范围,以便人类可以直观地理解图像和标注信息。
"""

在这里插入图片描述

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

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

相关文章

高并发秒杀系统设计:关键技术解析与典型陷阱规避

电商、在线票务等众多互联网业务场景中,高并发秒杀活动屡见不鲜。这类活动往往在短时间内会涌入海量的用户请求,对系统架构的性能、稳定性和可用性提出了极高的挑战。曾经,高并发秒杀架构设计让许多开发者望而生畏,然而&#xff0…

蓝桥杯--结束

冲刺题单 基础 一、简单模拟(循环数组日期进制) (一)日期模拟 知识点 1.把月份写为数组,二月默认为28天。 2.写一个判断闰年的方法,然后循环年份的时候判断并更新二月的天数 3.对于星期数的计算&#…

13、nRF52xx蓝牙学习(GPIOTE组件方式的任务配置)

下面再来探讨下驱动库如何实现任务的配置,驱动库的实现步骤应该和寄存器方式对应,关 键点就是如何调用驱动库的函数。 本例里同样的对比寄存器方式编写两路的 GPOITE 任务输出,一路配置为输出翻转,一路设 置为输出低电平。和 …

Java的基本语法(1)

一、运算符和表达式 举例说明什么是运算符,什么是表达式: int a 1; int b 2; int c a b; 在这个例子当中,是运算符,并且是算术运算符 ab是表达式,因为是运算符,所以ab是算术表达式 1.1算术运算符 …

C++学习之密码学知识

目录 1.文档介绍 2.知识点概述 3.项目准备 4.序列化介绍 5.项目中基础组件介绍 6.基础模块在项目中作用 7.项目中其他模块介绍 8.加密三要素 9.对称加密和非堆成加密 10.对称和非对称加密特点 11.堆成加密算法des 12.des对称加密算法 13.对称加密算法aes 14.知识点…

安装vllm

ubuntu 22.04, RTX3080, cuda 12.1, cudnn 8.9.7,cuda和cudnn的安装参考:https://blog.csdn.net/m0_52111823/article/details/147154526?spm1001.2014.3001.5501。 查看版本对应关系,下载12.1对应的whl包,https://github.com/vl…

【WPF】自定义控件:ShellEditControl-同列单元格编辑支持文本框、下拉框和弹窗

需要实现表格同一列,单元格可以使用文本框直接输入编辑、下拉框选择和弹窗,文本框只能输入数字,弹窗中的数据是若干位的二进制值。 本文提供了两种实现单元格编辑状态下,不同编辑控件的方法: 1、DataTrigger控制控件的…

Gson、Fastjson 和 Jackson 对比解析

目录 1. Gson (Google) 基本介绍: 核心功能: 特点: 使用场景: 2. Fastjson (Alibaba) 基本介绍: 核心功能: 特点: 使用场景: 3. Jackson 基本介绍: 核心功能…

浅谈微信视频号推荐算法

这次可能会稍微有点干货,但保证不晦涩~ 一、算法推荐的本质:猜你喜欢 vs 社交绑架​ 视频号的推荐系统本质上在做两件事: ​预测你的兴趣​:通过你的浏览、点赞、评论、分享等行为,分析你的偏好。​满足社交需求​&…

halcon模板匹配(一)create_shape_model_xld

目录 一、提取刹车盘孔洞轮廓二、形状模板的创建-设置-训练-查找三、找到亮的圆孔四、获得匹配结果五、使用use_polarity进行模板匹配六、计算四个圆对应的矩形框七、创建四个圆对应的模板并查找一、提取刹车盘孔洞轮廓 小技巧总结,使用boundary 函数提取区域边界,在边界范围…

day26图像处理OpenCV

文章目录 一、OpenCV1.介绍2.下载3.图像的表示4.图像的基本操作4.1图片读取或创建4.1.1读取4.1.2创建 4.2创建窗口4.3显示图片4.3.1设置读取的图片4.3.2设置显示多久4.3.3释放 4.4.保存图片4.5图片切片(剪裁)4.6图片大小调节 5.在图像中绘值5.1绘制直线5…

零基础开始学习鸿蒙开发-智能家居APP离线版介绍

目录 1.我的小屋 2.查找设备 3.个人主页 前言 好久不发博文了,最近都忙于面试,忙于找工作,这段时间终于找到工作了。我对鸿蒙开发的激情依然没有减退,前几天做了一个鸿蒙的APP,现在给大家分享一下! 具体…

C++的*了又*

先看下面一段代码 class HeapWord {friend class VMStructs;private:char *i; };主函数 #include "HeapWord.hpp" int main() {HeapWord *heapword new HeapWord();HeapWord *p new HeapWord();HeapWord **p1 new HeapWord *();heapword 3;*(HeapWord **)p he…

yolov8在windows系统的C++版本的onnxruntime部署方法

1.各个软件的的环境需要保持在统一的版本。 onnxruntime需要和cuda的版本对应上,版本号:onnxruntime-win-x64-gpu-1.18.1 ,链接: NVIDIA - CUDA | onnxruntime cuda:本机显卡支持的版本,cuda11.7,链接:CUDA Toolkit Archive | NVIDIA Developer cudnn:需要对应到cud…

js chrome 插件,下载微博视频

修改说明: 代码资源,免积分下载 起因, 目的: 最初是想下载微博上的NBA视频,因为在看网页上看视频很不方便,快进一次是10秒,而本地 VLC 播放器,快进一次是5秒。另外我还想做点视频剪辑。 对比…

【vue3】@click函数传动态变量参数

根据java的学习&#xff0c;摸索了一下vue3 函数传参的方式。以此作为记录。有更好的其它方式&#xff0c;可以评论区补充。 <script> const tmpref(); </script><button click"tmpFunction(传递参数:tmp)">按钮</button> // 直接【字符串…

jmeter 集成ZAP进行接口测试中的安全扫描 实现方案

以下是将 JMeter 集成 ZAP(OWASP Zed Attack Proxy)进行接口测试中安全扫描的实现方案: 1. 环境准备 JMeter 安装:从 JMeter 官方网站(https://jmeter.apache.org/download_jmeter.cgi)下载并安装 JMeter,确保其版本稳定。ZAP 安装:从 ZAP 官方网站(https://www.zapr…

全能格式转换器v16.3.0.159绿色便携版

前言 全能格式转换器具有音视频格式转换、合并视频、压缩视频、录制视频、下载视频、DVD刻录等功能。以超快的转换速度及强大的功能在国外名声大噪&#xff0c;转换速度是市面同类产品的30倍&#xff0c;操作简便&#xff0c;支持158种视频格式无损转换&#xff0c;批量转换高…

【基于开源insightface的人脸检测,人脸识别初步测试】

简介 InsightFace是一个基于深度学习的开源人脸识别项目,由蚂蚁金服的深度学习团队开发。该项目提供了人脸检测、人脸特征提取、人脸识别等功能,支持多种操作系统和深度学习框架。本文将详细介绍如何在Ubuntu系统上安装和实战InsightFace项目。 目前github有非常多的人脸识…

设计一个简单的权限管理系统

针对大规模服务器集群的权限管理系统设计&#xff0c;需结合 角色分层、最小权限原则 和 动态权限控制 来实现安全高效的权限管理。以下是分阶段设计方案&#xff1a; 一、核心设计思路 基于角色的访问控制&#xff08;RBAC&#xff09; 定义角色层级&#xff08;如董事长 >…