YOLOv1代码复现1:辅助功能实现

YOLOv1代码复现1:辅助功能实现

前言

​ 在经历了Faster-RCNN代码解读的摧残后,下决心要搞点简单的,于是便有了本系列的博客。如果你苦于没有博客详细告诉你如何自己去实现YOLOv1,那么可以看看本系列的博客,也许可以帮助你。

​ 另外,当完成所有代码后,会将代码放在GitHub上。

目标

​ 最主要的目标肯定是能够跑通整个代码,并且我希望可以详细的告诉大家如何参考博客自己去实现,因此,文章也会记录我自己遇到的错误和调试过程。

本系列计划完成的内容与已完成的内容:

​ 本系列计划六篇,如下:

  • 第一篇:辅助功能实现(本文)
  • 第二篇:数据加载器构建(等待完成)
  • 第三篇:网络框架构建(等待完成)
  • 第四篇:损失函数构建(等待完成)
  • 第五篇:预测函数构建(等待完成)
  • 第六篇:总结(等待完成)

1. 数据集下载:

​ 决定采用VOC2012的数据集,下载地址为:

http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar

​ 下载完,解压,最好把它改为我一样的文件结构:

在这里插入图片描述

​ 关于这个数据集的介绍,可以看我这篇博客,传送门。

​ 另外,大家需要在VOC2012文件夹下,建立一个名为pascal_voc_classes.json的文件,用于存储类别名称和数字的对应关系(该文件内容如下):

{
    "aeroplane": 1,
    "bicycle": 2,
    "bird": 3,
    "boat": 4,
    "bottle": 5,
    "bus": 6,
    "car": 7,
    "cat": 8,
    "chair": 9,
    "cow": 10,
    "diningtable": 11,
    "dog": 12,
    "horse": 13,
    "motorbike": 14,
    "person": 15,
    "pottedplant": 16,
    "sheep": 17,
    "sofa": 18,
    "train": 19,
    "tvmonitor": 20
}

2. 我的目录结构介绍:

​ 众所周知,拷贝别人使用的一大弊端就是需要对一些参数进行修改,特别是文件路径相关的参数。因此,这里我说明一下我的目录结构,方便大家后期自己实现或者修改代码的时候知道修改什么地方。

​ 由于我的很多程序都要用到数据文件夹,因此我把数据文件夹单独存放了的,而没有放在我的yolov1项目下。我的目录结构如下:

根目录
	data ---- 存放数据集的文件夹
		VOC2012	---- VOC2012数据集文件夹
			Annotations
			ImageSets
			JPEGImages
			SegmentationClass
			SegmentationObject
	YOLOv1-pytorch ---- 项目文件夹
		network_file ---- 存放网络架构的文件夹
		utils ---- 存放辅助功能的文件夹

3. 画图函数的实现:

​ 我们首先需要实现的功能:能够根据已给出的信息在图像画出框和类别信息。具体效果如下:

在这里插入图片描述

​ 这个函数还是很好实现的,因为边界框的坐标信息、类别信息、概率值都是已知的,我们要做的就是把它用上。

​ 实现画图的python库,主要有两个,一是cv库,二是PIL库。这里先用PIL库来实现吧。

3.1 导入所需的库:

​ 这里主要用的是PIL库的Image、ImageDraw、ImageFont、ImageColor几个方法,因此导入:

from PIL.Image import Image
import PIL.ImageDraw as ImageDraw
import PIL.ImageFont as ImageFont
from PIL import ImageColor
import numpy as np

​ 在实现函数之前,定义一个全局变量STANDARD_COLORS,用于存放那些标准的颜色值信息,到时候需要用颜色,直接从里面随机抽取一个即可:

# 标准颜色
STANDARD_COLORS = [
    'AliceBlue', 'Chartreuse', 'Aqua', 'Aquamarine', 'Azure', 'Beige', 'Bisque',
    'BlanchedAlmond', 'BlueViolet', 'BurlyWood', 'CadetBlue', 'AntiqueWhite',
    'Chocolate', 'Coral', 'CornflowerBlue', 'Cornsilk', 'Crimson', 'Cyan',
    'DarkCyan', 'DarkGoldenRod', 'DarkGrey', 'DarkKhaki', 'DarkOrange',
    'DarkOrchid', 'DarkSalmon', 'DarkSeaGreen', 'DarkTurquoise', 'DarkViolet',
    'DeepPink', 'DeepSkyBlue', 'DodgerBlue', 'FireBrick', 'FloralWhite',
    'ForestGreen', 'Fuchsia', 'Gainsboro', 'GhostWhite', 'Gold', 'GoldenRod',
    'Salmon', 'Tan', 'HoneyDew', 'HotPink', 'IndianRed', 'Ivory', 'Khaki',
    'Lavender', 'LavenderBlush', 'LawnGreen', 'LemonChiffon', 'LightBlue',
    'LightCoral', 'LightCyan', 'LightGoldenRodYellow', 'LightGray', 'LightGrey',
    'LightGreen', 'LightPink', 'LightSalmon', 'LightSeaGreen', 'LightSkyBlue',
    'LightSlateGray', 'LightSlateGrey', 'LightSteelBlue', 'LightYellow', 'Lime',
    'LimeGreen', 'Linen', 'Magenta', 'MediumAquaMarine', 'MediumOrchid',
    'MediumPurple', 'MediumSeaGreen', 'MediumSlateBlue', 'MediumSpringGreen',
    'MediumTurquoise', 'MediumVioletRed', 'MintCream', 'MistyRose', 'Moccasin',
    'NavajoWhite', 'OldLace', 'Olive', 'OliveDrab', 'Orange', 'OrangeRed',
    'Orchid', 'PaleGoldenRod', 'PaleGreen', 'PaleTurquoise', 'PaleVioletRed',
    'PapayaWhip', 'PeachPuff', 'Peru', 'Pink', 'Plum', 'PowderBlue', 'Purple',
    'Red', 'RosyBrown', 'RoyalBlue', 'SaddleBrown', 'Green', 'SandyBrown',
    'SeaGreen', 'SeaShell', 'Sienna', 'Silver', 'SkyBlue', 'SlateBlue',
    'SlateGray', 'SlateGrey', 'Snow', 'SpringGreen', 'SteelBlue', 'GreenYellow',
    'Teal', 'Thistle', 'Tomato', 'Turquoise', 'Violet', 'Wheat', 'White',
    'WhiteSmoke', 'Yellow', 'YellowGreen'
]

3.2 draw_obj函数实现:

​ 该函数的作用:将目标边界框信息,类别信息绘制在图片上

参数讲解:

​ 传入的参数:

参数意义
image需要绘制的图片
boxes目标边界框信息
格式为:[[left, top, right, bottom],…]
classes目标类别信息
scores目标概率信息
category_index类别与名称字典
box_thresh过滤的概率阈值
line_thickness边界框宽度
font字体类型
font_size字体大小
draw_boxes_on_image是否将边界框画在图像上
默认为True

​ 这里,需要说明一下其中的几个关键参数,方便大家理解:

  • boxes、classes、scores

​ 这三个参数分布是一张图片的所有边界框、类别、概率值,因为一张图片可能并不只有一个对象,因此这三个参数的值都是类似[[...],[...],......]这样列表里面嵌套一个列表的形式。

  • category_index

​ 因为我们知道,计算机是没有办法直接识别诸如person/bike/car这样的自然语言的,因此需要把这些类别值转为数字值,就像上面创建的json文件一样,这里使用一个字典来存储相关值。

  • box_thresh

​ 这个参数的作用就是过滤掉那些低概率的值,如果一个框预测概率过低,其实画出来也没啥意义,因此需要进行过滤,不过如果你不想过滤,直接设置为0即可。

返回值:

​ 返回的是PIL Image对象,这个对象可以自带矩形边界框、类别文字等信息,然后可以使用matplotlib中的方法将图像显示出来。

函数实现:

​ 首先,需要对现有的值进行过滤,过滤方法采用numpy.greater方法,其返回过滤后剩下的值的索引,然后利用这个索引去筛选值:

# 过滤掉低概率的目标
idxs = np.greater(scores, box_thresh)
# 需要同时处理boxes、classes、scores、masks
boxes = boxes[idxs]
classes = classes[idxs]
scores = scores[idxs]

​ 如果全部过滤掉了,那么直接结束该方法:

# 如果boxes长度为0,表示所有的框都过滤了,就不需要画了
if len(boxes) == 0:
    return image

​ 接着,根据类别个数,从标注颜色列表中抽取对应颜色,只是获取的颜色需要用ImageColor,getrgb方法获取rgb值:

# 从定义的颜色列表中抽取颜色
# ImageColor.getrgb 获取颜色的rgb值
colors = [ImageColor.getrgb(STANDARD_COLORS[cls % len(STANDARD_COLORS)]) for cls in classes]

​ 判断是否需要画边界框,并用ImageDraw.Draw创建绘制对象:

# 如果需要画边界框
if draw_boxes_on_image:
    # 创建画图对象
    draw = ImageDraw.Draw(image)

​ 然后,由于一张图对象可能不只一个,因此需要遍历boxes等参数,进行画图:

# 如果需要画边界框
if draw_boxes_on_image:
    # 创建画图对象
    draw = ImageDraw.Draw(image)
    # 开始迭代绘图
    for box, cls, score, color in zip(boxes, classes, scores, colors):
        # 边界框的坐标:左上角x、y + 右下角x、y
        left, top, right, bottom = box
        # 绘制目标边界框,逆时针画图
        draw.line([(left, top), (left, bottom), (right, bottom),
                   (right, top), (left, top)], width=line_thickness, fill=color)
        # 绘制类别和概率信息
        draw_text(draw, box.tolist(), int(cls), float(score), category_index, color, font, font_size)

​ 其中,填写文字的函数,我们单独实现。

3.3 draw_text函数实现:

​ 该函数的作用:在draw_obj函数的基础上绘制图像上的文字。

参数讲解:

​ 参数种类和draw_obj函数相差不大,只是注意该函数的参数不像draw_obj函数一样,是多个值了(之前boxes参数为[[....],[....],...]),即一个参数仅有一个对象的值(这里box参数为[.....])。

​ 另外,draw_text第一个参数,是已经绘制了矩形的图像对象,所以接下来的任务就是在该对象的基础上绘制文字内容。

返回值:

​ 返回一个完整的绘制完成的图像对象。

实现:

​ 利用之前导入的ImageFont方法创建字体对象,当然,如果你的电脑没有指定的字体,那么就使用默认字体:

# 创建字体对象,如果创建失败(比如目前指定的字体你没有),就使用默认的字体
try:
    font = ImageFont.truetype(font, font_size)
except IOError:
    font = ImageFont.load_default()

​ 接着,获取box的坐标、并将1、2这样的数字信息转为如preson\bike的类别信息,并将形如0.2、0.3的概率值转为百分数形式:

# 获取坐标
left, top, right, bottom = box
# 将数字的类别转为真实的类别信息,并加上概率值构成“ person 99% ”这样的字符串
display_str = f"{category_index[str(cls)]}: {int(100 * score)}%"

​ 然后,需要设置字体的高度,使用font.getsize方法可以获取输入字符的大小,那么将要填写的一句话全输入给该方法,然后获取所有字符的最大值即可:

# 设置字体的高度
# font.getsize获取输入文字中每个字符的大小
display_str_heights = [font.getsize(ds)[1] for ds in display_str]
display_str_height = (1 + 2 * 0.05) * max(display_str_heights)

接下来是一个难点:文字需要设置它的坐标。这里,看下图分析坐标获取思路:

在这里插入图片描述

​ 上图是正常的情况,即边界框最上面的坐标与文字高度不重叠,意味着可以正常放下文字内容。但是也有不正常的情况:

在这里插入图片描述

​ 如上图所示,填写的文字没有办法放在边界框的上面,此时需要进行一定的修正,采取的方法是把文字放入边界框内容

​ 基于此,可以编写代码:

# 如果文字的高度没有超过图像最高点
if top > display_str_height:
    # 设置文字的坐标
    # 这里减法, 注意坐标轴的朝向
    text_top = top - display_str_height
    text_bottom = top
else:
    # 如果超过了,就设置文字的坐标为边界框的下面
    text_top = bottom
    text_bottom = bottom + display_str_height

​ 最后,就是绘制文字了。这里,一个字符一个字符的绘制,是因为需要为每个字符添加一个矩形框背景,这样不同字符组合在一起,将变为一个大的矩形框了:

# 开始画
# 一个字符一个字符的画
for ds in display_str:
    # 获取文字的宽和高
    text_width, text_height = font.getsize(ds)
    # 设置每个字符的偏离距离
    margin = np.ceil(0.05 * text_width)
    # 画一个矩形
    draw.rectangle([(left, text_top),
                    (left + text_width + 2 * margin, text_bottom)], fill=color)
    # 画文字
    draw.text((left + margin, text_top),
              ds,
              fill='black',
              font=font)
    left += text_width

4. 效果展示:

​ 由于我们还没有实现其它的代码,所以这里用一个简单的方法来检测代码是否可以正确运行。

​ 首先,需要导入之前没有导入过的库:

# 导入调试需要的库
from matplotlib import pyplot as plt
import json
from PIL import Image

​ 接着,需要读取我们的json文件,并转为字典:

# 读取类别json文件,并转为字典值
category_index = {}
try:
    # 路劲需要改为自己的
    json_file = open('../../data/VOC2012/pascal_voc_classes.json', 'r')
    class_dict = json.load(json_file)
    category_index = {str(v): str(k) for k, v in class_dict.items()}
except Exception as e:
    print(e)
    exit(-1)

​ 这个字典的值形如下表,即为类别和数字值的对应关系:

{
	'person' : 15
	'bike' : 2
}

​ 接着,我们可以调用我们的函数了,不过我们只能手动传入对应参数了:

# 开始绘制
# 打开一张图片,需要修改为自己的路径
img = Image.open('../../data/VOC2012/JPEGImages/2007_000027.jpg')
plot_img = draw_objs(img,
                     np.array([[174,101,349,351]]), # 传入该图像对应的注解信息
                     np.array([15]),
                     np.array([1]),
                     category_index=category_index,
                     box_thresh=0.5,
                     line_thickness=3,
                     font='arial.ttf',
                     font_size=20)
plt.imshow(plot_img)
plt.show()

​ 说明一下,上面的参数值都是如何填写的:先任意选择一张图片,然后找到其对应的注解文件;接着,任意选择一个对象,找到其类别名称和坐标值即可。由于我们采用的真实图像的值,即类别概率肯定为1.

在这里插入图片描述

从上面传入的参数,也可以直观的理解各个参数的含义和形式。

​ 运行上述代码结果如下:

在这里插入图片描述

5. 完整代码:

# author: baiCai
# 本文件拷贝别人的,用于画框图,删除了一些自己用不到的内容
from PIL.Image import Image
import PIL.ImageDraw as ImageDraw
import PIL.ImageFont as ImageFont
from PIL import ImageColor
import numpy as np

# 标准颜色
STANDARD_COLORS = [
    'AliceBlue', 'Chartreuse', 'Aqua', 'Aquamarine', 'Azure', 'Beige', 'Bisque',
    'BlanchedAlmond', 'BlueViolet', 'BurlyWood', 'CadetBlue', 'AntiqueWhite',
    'Chocolate', 'Coral', 'CornflowerBlue', 'Cornsilk', 'Crimson', 'Cyan',
    'DarkCyan', 'DarkGoldenRod', 'DarkGrey', 'DarkKhaki', 'DarkOrange',
    'DarkOrchid', 'DarkSalmon', 'DarkSeaGreen', 'DarkTurquoise', 'DarkViolet',
    'DeepPink', 'DeepSkyBlue', 'DodgerBlue', 'FireBrick', 'FloralWhite',
    'ForestGreen', 'Fuchsia', 'Gainsboro', 'GhostWhite', 'Gold', 'GoldenRod',
    'Salmon', 'Tan', 'HoneyDew', 'HotPink', 'IndianRed', 'Ivory', 'Khaki',
    'Lavender', 'LavenderBlush', 'LawnGreen', 'LemonChiffon', 'LightBlue',
    'LightCoral', 'LightCyan', 'LightGoldenRodYellow', 'LightGray', 'LightGrey',
    'LightGreen', 'LightPink', 'LightSalmon', 'LightSeaGreen', 'LightSkyBlue',
    'LightSlateGray', 'LightSlateGrey', 'LightSteelBlue', 'LightYellow', 'Lime',
    'LimeGreen', 'Linen', 'Magenta', 'MediumAquaMarine', 'MediumOrchid',
    'MediumPurple', 'MediumSeaGreen', 'MediumSlateBlue', 'MediumSpringGreen',
    'MediumTurquoise', 'MediumVioletRed', 'MintCream', 'MistyRose', 'Moccasin',
    'NavajoWhite', 'OldLace', 'Olive', 'OliveDrab', 'Orange', 'OrangeRed',
    'Orchid', 'PaleGoldenRod', 'PaleGreen', 'PaleTurquoise', 'PaleVioletRed',
    'PapayaWhip', 'PeachPuff', 'Peru', 'Pink', 'Plum', 'PowderBlue', 'Purple',
    'Red', 'RosyBrown', 'RoyalBlue', 'SaddleBrown', 'Green', 'SandyBrown',
    'SeaGreen', 'SeaShell', 'Sienna', 'Silver', 'SkyBlue', 'SlateBlue',
    'SlateGray', 'SlateGrey', 'Snow', 'SpringGreen', 'SteelBlue', 'GreenYellow',
    'Teal', 'Thistle', 'Tomato', 'Turquoise', 'Violet', 'Wheat', 'White',
    'WhiteSmoke', 'Yellow', 'YellowGreen'
]


def draw_text(draw,box,cls,score,category_index,color,font='arial.ttf',font_size=24):
    """
    将目标边界框和类别信息绘制到图片上
    参数:
        draw : 画图对象,可以使用画直线等等方法
        box : 一个边界框,里面有坐标信息
        cls : 对象的类别,为int值,需要使用category_index转为字符串值
        score : 对象的类别概率值
        category_index : 不同的索引对应的类别信息
        color : 使用的颜色
        font :字体
        font_size : 字大小
    """
    # 创建字体对象,如果创建失败(比如目前指定的字体你没有),就使用默认的字体
    try:
        font = ImageFont.truetype(font, font_size)
    except IOError:
        font = ImageFont.load_default()

    # 获取坐标
    left, top, right, bottom = box
    # 将数字的类别转为真实的类别信息,并加上概率值构成“ person 99% ”这样的字符串
    display_str = f"{category_index[str(cls)]}: {int(100 * score)}%"
    # 设置字体的高度
    # font.getsize获取输入文字中每个字符的大小
    display_str_heights = [font.getsize(ds)[1] for ds in display_str]
    display_str_height = (1 + 2 * 0.05) * max(display_str_heights)

    # 如果文字的高度没有超过图像最高点
    if top > display_str_height:
        # 设置文字的坐标
        # 这里减法, 注意坐标轴的朝向
        text_top = top - display_str_height
        text_bottom = top
    else:
        # 如果超过了,就设置文字的坐标为边界框的下面
        text_top = bottom
        text_bottom = bottom + display_str_height

    # 开始画
    # 一个字符一个字符的画
    for ds in display_str:
        # 获取文字的宽和高
        text_width, text_height = font.getsize(ds)
        # 设置每个字符的偏离距离
        margin = np.ceil(0.05 * text_width)
        # 画一个矩形
        draw.rectangle([(left, text_top),
                        (left + text_width + 2 * margin, text_bottom)], fill=color)
        # 画文字
        draw.text((left + margin, text_top),
                  ds,
                  fill='black',
                  font=font)
        left += text_width


def draw_objs(image,boxes=None,classes=None,scores=None,category_index=None,box_thresh=0.1,line_thickness=8,font='arial.ttf',font_size=24,draw_boxes_on_image=True):
    """
    将目标边界框信息,类别信息绘制在图片上
    Args:
        image: 需要绘制的图片
        boxes: 目标边界框信息
        classes: 目标类别信息
        scores: 目标概率信息
        category_index: 类别与名称字典
        box_thresh: 过滤的概率阈值
        line_thickness: 边界框宽度
        font: 字体类型
        font_size: 字体大小
        draw_boxes_on_image:是否将边界框画在图像上,默认为True
    Returns:

    """
    # 过滤掉低概率的目标
    idxs = np.greater(scores, box_thresh)
    # 需要同时处理boxes、classes、scores、masks
    boxes = boxes[idxs]
    classes = classes[idxs]
    scores = scores[idxs]

    # 如果boxes长度为0,表示所有的框都过滤了,就不需要画了
    if len(boxes) == 0:
        return image

    # 从定义的颜色列表中抽取颜色
    # ImageColor.getrgb 获取颜色的rgb值
    colors = [ImageColor.getrgb(STANDARD_COLORS[cls % len(STANDARD_COLORS)]) for cls in classes]

    # 如果需要画边界框
    if draw_boxes_on_image:
        # 创建画图对象
        draw = ImageDraw.Draw(image)
        # 开始迭代绘图
        for box, cls, score, color in zip(boxes, classes, scores, colors):
            # 边界框的坐标
            left, top, right, bottom = box
            # 绘制目标边界框,顺时针画图
            draw.line([(left, top), (left, bottom), (right, bottom),
                       (right, top), (left, top)], width=line_thickness, fill=color)
            # 绘制类别和概率信息
            draw_text(draw, box.tolist(), int(cls), float(score), category_index, color, font, font_size)


    return image

if __name__ == '__main__':
    # 导入调试需要的库
    from matplotlib import pyplot as plt
    import json
    from PIL import Image
    # 读取类别json文件,并转为字典值
    category_index = {}
    try:
        json_file = open('../../data/VOC2012/pascal_voc_classes.json', 'r')
        class_dict = json.load(json_file)
        category_index = {str(v): str(k) for k, v in class_dict.items()}
    except Exception as e:
        print(e)
        exit(-1)
    # 开始绘制
    # 打开一张图片,需要修改为自己的路径
    img = Image.open('../../data/VOC2012/JPEGImages/2007_000027.jpg')
    plot_img = draw_objs(img,
                         np.array([[174,101,349,351]]), # 传入该图像对应的注解信息
                         np.array([15]),
                         np.array([1]),
                         category_index=category_index,
                         box_thresh=0.5,
                         line_thickness=3,
                         font='arial.ttf',
                         font_size=20)
    plt.imshow(plot_img)
    plt.show()

6. 总结:

​ 这里,我们不仅仅实现了画图的函数,还定义了传入参数的形式,也为后期构建数据加载等文件定下了返回值的基调。所谓,千里之路始于足下,顺着思路往下写,迟早也会把YOLOv1搞定的^_^。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大屏开发需要知道哪些知识

大屏 大屏是什么呢?再我前几年刚接触这个词得时候很新颖,全名叫态势感知大屏,大屏得特点是炫酷、好看,给用户满满得科技感。 听一位前辈说当年再招标会上,再都用exel、word做界面图表文档得时候,有一家公司…

打包后dist包中app.**.js文件暴露大量接口信息,webpack-obfuscator对打包后的js代码混淆加密

问题描述 打包后dist包中app.**.js文件暴露大量接口信息,而webpack-obfuscator可以对打包后的js代码混淆加密 版本信息 webpack: 4.x.x node: 14.18.0 webpack4环境下使用webpack-obfuscator不能使用最新版本 我的下载版本是: npm install --save-de…

玩转ChatGPT:论文翻译润色

一、写在前面 首先还是让小Chat推销下自己: 嘿!你是否在写论文的过程中感到头疼,无从下手?你是否在担心自己的语言表达不够专业、不够流畅,影响了论文的质量?不要担心,ChatGPT的润色服务可以帮…

Redis 持久化八股文

目录 Redis的持久化机制 持久化方式对比 RDB RDB 持久化 RDB 的优缺点 优点 缺点 RDB 快照时运行修改数据吗 RDB 快照时修改数据过程 写时复制技术 RDB 的执行频率 增量快照 AOF 如何开启AOF AOF 为什么要采用后写日志呢? 后写日志的弊端 AOF 的优…

pdf转成word | ppt | jpg图片,免费一键转换教程

我不允许真的还有人不知道如何免费将pdf转成 ppt、word 或者 jpg图片! 职场小伙伴是不是会经常遇到pdf怎么转成word,pdf怎么转成word,pdf怎么jpg图片等问题?别再为pdf转化格式难、而且还要付费而发愁了!这份pdf免费一…

Python OpenCV3 计算机视觉秘籍:6~9

原文:OpenCV 3 Computer Vision with Python Cookbook 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 计算机视觉 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 当别人说你没有底线的时候&…

IDAPython入门基础语法

文章目录 参考文章IDAPython简介常用函数获取界面地址的函数数值获取函数数值判断函数patch操作函数去除花指令实例 参考文章 IDAPython入门教程 基于IDA7.5_Python3 第一讲 简介与地址获取 IDAPython简介 IDAPython拥有强大的功能,在使用IDA分析程序时非常有用,可以简化许多…

QT 插件通信接口调用 CTK开发(四)

CTK 为支持生物医学图像计算的公共开发包,其全称为 Common Toolkit。为医学成像提供一组统一的基本功能;促进代码和数据的交互及结合;避免重复开发;在工具包(医学成像)范围内不断扩展到新任务,而不会增加现有任务的负担;整合并适应成功的解决方案。 本专栏文章较为全面…

信息安全复习三:古典密码之设计好的密码算法

一.章节梗概 讨论以下算法,理解怎么设计好的密码算法的关键问题 1.Caesar cipher 2.单字母表密码 3.Playfairmima 4.维吉尼亚密码 5.自动生成密码 二.Caesar cipher 2.1 穷举攻击 穷举攻击定义:尝试所有密钥直到有一个合法密钥能够把密文还原成明文&…

Docker私有仓库Harbor搭建及使用

文章目录 一、Harbor简介二、Harbor仓库部署三、Harbor仓库使用 一、Harbor简介 官网地址:https://github.com/goharbor/harbor Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等…

如何在Web上实现激光点云数据在线浏览和展示?

无人机激光雷达测量是一项综合性较强的应用系统,具有数据精度高、层次细节丰富、全天候作业等优势,能够精确测量三维现实世界,为各个行业提供了丰富有效的数据信息。但无人机激光雷达测量产生的点云数据需要占用大量的存储空间,甚…

SpringSecurity之权限模块设计

目录 前言 实现思路 代码结构 使用说明 前言 前面我们了解了关于微服务权限设计方案以及J W T的相关介绍,今天我们来聊一下,如何避免自己重复的写相同的代码,一次代码实现,即可完美复制到任何项目中实现权限相关的功能。 实现…

RK3568平台开发系列讲解(驱动基础篇)SMP(Symmetrical Multi-Processing)

🚀返回专栏总目录 文章目录 一、linux SMP 和 AMP二、linux SMP的启动流程三、CPU的描述:cpumask四、CPU之间的关系沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 SMP(Symmetrical Multi-Processing)。 一、linux SMP 和 AMP 目前支持多核处理器的实时操…

CxImage学习使用1:环境搭建

目录 前言 一、CxImage相关介绍 二、编译源码 三、将CxImage使用到自己的工程中 前言 CxImage是一个可以用于MFC 的C图像处理类库类,它可以打开,保存,显示,转换各种常见格式的图像文件,比如BMP, JPEG, GIF, PNG, TI…

300元的蓝牙耳机什么牌子好?300内无线蓝牙耳机推荐

感受过无线的自在舒适后,越来越多的小伙伴爱上了蓝牙耳机白天出街更潇洒,目前市面上蓝牙耳机琳琅满目可选择性较多价格从几十、几百元到数千元不等然而蓝牙耳机的安全性、舒适性如何?连接稳吗?下面整理了几款300元价位的耳机分享给…

【CSDN周赛】第46期题解

👨‍💻个人主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 本文章收录于专栏 【CSDN周赛】 本篇文章目录 🌏一、吃吃吃🌸题目描述🌸题解 🌏二、n …

Java核心技术 卷1-总结-12

Java核心技术 卷1-总结-12 具体的集合链表数组列表 具体的集合 下表中除了以 Map结尾的类之外, 其他类都实现了 Collection 接口,而以 Map结尾的类实现了 Map 接口。 集合类型描述ArrayList一种可以动态增长和缩减的索引序列LinkedList一种可以在任何位…

MySQL高级篇——索引的创建与设计原则

导航: 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 一、索引的分类与使用 1.1 索引的分类 1.1.1. 普通索引 1.1.2. 唯一性索引 1.1.3. 主键索引(唯一非空) 1.1.4…

百度ai智能写作工具-百度ai自动写文章

百度AI智能写作工具:让创作更快捷、高效! 在当今竞争激烈的文化创意市场中,创作一篇高质量的文章需要投入大量时间和精力。然而,有了百度AI智能写作工具,创作变得更快捷、高效了。 百度AI智能写作工具采用最先进的人…