测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)

news2024/11/24 17:31:36

文章目录

  • 一、任务描述
  • 二、指标分析
    • 2.1 TP/FP/FN/TN
    • 2.2 精准率
    • 2.3 召回率
  • 三、接口处理
  • 四、数据集处理
  • 五、开始计算指标
  • 五、实用工具
    • 5.1 移动文件
    • 5.2 可视化JSON标签
    • 5.3 可视化TXT标签

一、任务描述

通过给定的算法接口,对算法的输出(置信度、检测框、告警、类别等)进行数据处理,结合原标签完成TP、FP、FN、TN、准确率、召回率的指标测试。

二、指标分析

2.1 TP/FP/FN/TN

TP(True Positives,真正例):表示模型正确预测为正类的样本数量,也就是将正例正确分类为正例的数量。

FP(False Positives,假正例):表示模型错误预测为正类的样本数量,也就是将负例错误分类为正例的数量。

FN(False Negatives,假负例):表示模型错误预测为负类的样本数量,也就是将正例错误分类为负例的数量。

TN(True Negatives,真负例):表示模型正确预测为负类的样本数量,也就是将负例正确分类为负例的数量。

2.2 精准率

精准率是指模型在所有被预测为正例的样本中,真正为正例的比例。它的计算公式是:Precision = TP / (TP + FP)。精准率衡量了模型的预测中有多少是真正的正例,是一个关于假正例的指标。

2.3 召回率

召回率是指模型在所有实际正例中,成功预测为正例的比例。它的计算公式是:Recall = TP / (TP + FN)。召回率衡量了模型对于所有正例的识别能力,是一个关于假负例的指标。

三、接口处理

import os, base64, json, time, requests

def get_all_file(path):
    result_list = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if os.path.basename(file).__contains__(".jpg"):
                result_list.append(os.path.join(root, file))
    return result_list

def pic2base64(img_path):
    if os.path.exists(img_path):
        encoded_base64 = base64.b64encode(open(img_path, 'rb').read()).decode()
        return encoded_base64
    else:
        os.error("图片不存在,请检查图片路径:{}".format(img_path))

def write_content_to_json(content, json_file_path):
    with open(json_file_path, 'w+', encoding='utf-8') as f:
        f.write(json.dumps(content, indent=4, ensure_ascii=False))

if __name__ == "__main__":
    result = {}
    fish_pic_path = r"D:\datasets\test_mission\fishing_test_data"
    url_fish = "http://***.***.***.*:端口号/能力接口"
    pic_list = get_all_file(fish_pic_path)
    for pic in pic_list:
        image_base64 = pic2base64(pic)
        payload = {
            "seqid": "test1",
            "timestamp": int(time.time()),
            "image": image_base64
            # "image": rf';base64,{image_base64}\"alt=\"\">'
        }
        res = requests.post(url_fish, json=payload)
        json_res = res.json()
        print(json_res)
        if 'code' in json_res and json_res['code'] == 6000:
            result[os.path.basename(pic)] = json_res['data']
    write_content_to_json(result, 'result/fish_result.json')

将所有的结果保存为JSON文档,如下:
在这里插入图片描述

四、数据集处理

数据集统一处理成:
在这里插入图片描述

数据集如果是JSON格式,通过下面的代码转换为TXT格式

import os
import numpy as np
import json
from glob import glob
import cv2
from sklearn.model_selection import train_test_split
from shutil import copyfile
import argparse

obj_classes = []


# Labelme坐标到YOLO V5坐标的转换
def convert(size, box):
    dw = 1. / (size[0])
    dh = 1. / (size[1])
    x = (box[0] + box[1]) / 2.0 - 1
    y = (box[2] + box[3]) / 2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)

def create(yolo_labels_dir):
    if not os.path.exists(yolo_labels_dir):
        os.makedirs(yolo_labels_dir)

# 样本转换
def convertToYolo5(fileList, output_dir, labelImg_path, unify_path):
    # 创建指定样本的父目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 创建指定样本的images和labels子目录
    yolo_images_dir = '{}/images/'.format(output_dir)
    yolo_labels_dir = '{}/labels/'.format(output_dir)

    create(yolo_images_dir)
    create(yolo_labels_dir)
    create(unify_path)

    # 一个样本图片一个样本图片地转换
    for num,json_file_ in enumerate(fileList):
        # print('fileList',fileList)
        # 1. 生成YOLO样本图片
        # 构建json图片文件的全路径名
        imagePath = labelImg_path + '/' + json_file_ + ".jpg"
        print('name',imagePath, json_file_)
        # print('labelme_path', labelme_path)
        # 构建Yolo图片文件的全路径名
        yolo_image_file_path = yolo_images_dir + "{}.jpg".format(json_file_)
        print('yolo_image_file_path', yolo_image_file_path)

        # copy样本图片
        copyfile(imagePath, yolo_image_file_path)

        # 2. 生成YOLO样本标签
        # 构建json标签文件的全路径名

        labelme_path_ = labelImg_path.split('image')[0]

        json_filename = labelme_path_ + 'json'+'\\' + json_file_ + ".json"

        # 构建Yolo标签文件的全路径名
        yolo_label_file_path = yolo_labels_dir + "{}.txt".format(json_file_)
        txt_label_file_path = unify_path + "/{}.txt".format(json_file_)

        # 创建新的Yolo标签文件
        yolo_label_file = open(yolo_label_file_path, 'w')
        txt_label_file = open(txt_label_file_path, 'w')

        # 获取当前图片的Json标签文件
        json_obj = json.load(open(json_filename, "r", encoding="utf-8"))

        # 获取当前图片的长度、宽度信息
        height = json_obj['imageHeight']
        width = json_obj['imageWidth']

        # 依次读取json文件中所有目标的shapes信息
        for shape in json_obj["shapes"]:
            # 获取shape中的物体分类信息
            label = shape["label"]
            if label not in ['car_red','car_orange','car_green','car_blue','car_black','car_white','car_purple','car_grey','car_silvery','car grey','car orange','car black','car','car blue','car purple','car white','car silvery','car green','car_yellow','car red']:
                if label == 'Fengtain' or label == 'FengTain' or label == 'FengtTian' or label == 'Fengtian':
                    label = 'FengTian'
                if (label not in obj_classes):
                    obj_classes.append(label)

                # 获取shape中的物体坐标信息
                if (shape["shape_type"] == 'rectangle'):
                    points = np.array(shape["points"])
                    xmin = min(points[:, 0]) if min(points[:, 0]) > 0 else 0
                    xmax = max(points[:, 0]) if max(points[:, 0]) > 0 else 0
                    ymin = min(points[:, 1]) if min(points[:, 1]) > 0 else 0
                    ymax = max(points[:, 1]) if max(points[:, 1]) > 0 else 0

                    # 对坐标信息进行合法性检查
                    if xmax <= xmin:
                        pass
                    elif ymax <= ymin:
                        pass
                    else:
                        # Labelme坐标转换成YOLO V5坐标
                        bbox_labelme_float = (float(xmin), float(xmax), float(ymin), float(ymax))
                        bbox_yolo_normalized = convert((width, height), bbox_labelme_float)

                        # 把分类标签转换成分类id
                        class_id = obj_classes.index(label)

                        # 生成YOLO V5的标签文件
                        yolo_label_file.write(str(class_id) + " " + " ".join([str(a) for a in bbox_yolo_normalized]) + '\n')

                        # 保存为统一的位置
                        txt_label_file.write(str(class_id) + " " + " ".join([str(a) for a in bbox_yolo_normalized]) + '\n')

        yolo_label_file.close()
        txt_label_file.close()

def check_output_directory(output=""):
    # 创建保存输出图片的目录
    save_path = output + '/'
    is_exists = os.path.exists(save_path)

    if is_exists:
        print('Warning: path of %s already exist, please remove it firstly by manual' % save_path)
        # shutil.rmtree(save_path)  # 避免误删除已有的文件
        return ""

    # print('create output path %s' % save_path)
    os.makedirs(save_path)

    return save_path


def create_yolo_dataset_cfg(output_dir='', label_class=[]):
    # 创建文件
    data_cfg_file = open(output_dir + '/data.yaml', 'w')

    # 创建文件内容
    data_cfg_file.write('train:  ../train/images\n')
    data_cfg_file.write("val:    ../valid/images\n")
    data_cfg_file.write("test:   ../test/images\n")
    data_cfg_file.write("\n")
    data_cfg_file.write("# Classes\n")
    data_cfg_file.write("nc: %s\n" % len(label_class))
    data_cfg_file.write('names: ')
    i = 0
    for label in label_class:
        if (i == 0):
            data_cfg_file.write("[")
        else:
            data_cfg_file.write(", ")
            if (i % 10 == 0):
                data_cfg_file.write("\n        ")
        i += 1
        data_cfg_file.write("'" + label + "'")
    data_cfg_file.write(']  # class names')
    data_cfg_file.close()
    # 关闭文件


def labelImg2yolo(input='', output='', unify_path=""):
    outputdir_root = output + '/'
    labelImg_path = input
    print(labelImg_path)
    labelImg_path_imagepath = labelImg_path + '\\' + 'image'
    print(labelImg_path_imagepath)
    json_path = labelImg_path+'\\'+'json'
    print(json_path)

    print("*"*100)

    # 1.获取input目录中所有的json标签文件全路径名
    files = glob(json_path + "/*.json")
    print(files)

    # 2.获取所有标签文件的短文件名称
    files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]
    print(files)

    # 3. 按比例随机切分数据集,获取训练集样本
    train_files, valid_test_files = train_test_split(files, test_size=0.2, random_state=55)

    # 4. 按比例随机切分数据集,获取验证集和测试集样本
    valid_files, test_files = train_test_split(valid_test_files, test_size=0.1, random_state=55)

    # 5. 构建YOLO数据集目录
    train_path = outputdir_root + '/train'
    valid_path = outputdir_root + '/valid'
    test_path = outputdir_root + '/test'

    # 6. 生成YOLO 训练、验证、测试数据集:图片+标签
    convertToYolo5(train_files, train_path, labelImg_path_imagepath, unify_path)
    convertToYolo5(valid_files, valid_path, labelImg_path_imagepath, unify_path)
    convertToYolo5(test_files, test_path, labelImg_path_imagepath, unify_path)
    print("*"*100)
    # 7. 创建YOLO数据集配置文件
    create_yolo_dataset_cfg(output, obj_classes)
    labelme_path = input

    print("Classes:", obj_classes)
    print('Finished, output path =', outputdir_root)

    return 0


def parse_opt():
    # define argparse object
    parser = argparse.ArgumentParser()

    # input 包含两个文件夹, image和json,分别存放了对应的文件
    parser.add_argument('--input', type=str, default=r'F:\python\mission\fish_power_test\data\test',help='The input LabelImg directory')
    # output 存放保存的yolov5的训练数据,分为train、val、test三个文件,里面分别存放了对应的images和labels,在train目录下还存放了yolov5加载数据集的yaml文件(见data.yaml)
    parser.add_argument('--output', type=str,default=r'F:\python\mission\fish_power_test\data\test/yolo_txt', help='The output YOLO V5 directory')
    # 统一存放
    parser.add_argument('--unify_path', type=str,default=r'F:\python\mission\fish_power_test\data\test/txt', help='The output txt directory')

    # parse arges from command line
    opt = parser.parse_args()
    print("input  =", opt.input)
    print("output =", opt.output)
    print("unify_path =", opt.unify_path)
    # return opt
    return opt


def main(opt):
    labelImg2yolo(**vars(opt))


if __name__ == '__main__':
    opt = parse_opt()
    main(opt)

然后通过下面的代码将源标签的txt文档进行总结

# 将txt标签对应的原始的label和boxs写入到txt文档中
import cv2
import os

# 读取txt文件信息
def read_list(txt_path):
    pos = []
    with open(txt_path, 'r') as file_to_read:
        while True:
            lines = file_to_read.readline()  # 整行读取数据
            if not lines:
                break
            # 将整行数据分割处理,如果分割符是空格,括号里就不用传入参数,如果是逗号, 则传入‘,'字符。
            p_tmp = [float(i) for i in lines.split(' ')]
            pos.append(p_tmp)  # 添加新读取的数据
            pass
    return pos

def draw_box_in_single_image(image_path, txt_path, image_name):
    # 读取图像
    image = cv2.imread(image_path)
    pos = read_list(txt_path)
    reses = []
    reses.append(image_name)
    for i in range(len(pos)):
        label = classes[int(str(int(pos[i][0])))]
        print('label is '+label)

        # 将中心坐标、宽度和高度转换为 xywh 格式
        x_center = int(pos[i][1] * image.shape[1])
        y_center = int(pos[i][2] * image.shape[0])
        width = int(pos[i][3] * image.shape[1])
        height = int(pos[i][4] * image.shape[0])

        x_min = x_center - width // 2
        y_min = y_center - height // 2

        # 绘制矩形框
        cv2.rectangle(image, (x_min, y_min), (x_min + width, y_min + height), colores[int(str(int(pos[i][0])))], 2)
        cv2.putText(image, label, (x_min, y_min - 2), 0, 1, colores[int(str(int(pos[i][0])))], thickness=2, lineType=cv2.LINE_AA)

        res = [label, x_min, y_min, width, height]

        reses.append(res)
    # cv2.imshow("images", image)
    # cv2.waitKey(0)
    return reses

if __name__ == '__main__':
    f =  open('result/ori_data.txt', 'w+')
    img_folder = "data/test/image"
    img_list = [f for f in os.listdir(img_folder) if f.endswith('.jpg')]
    img_list.sort()

    label_folder =  "data/test/txt"
    label_list = [f for f in os.listdir(label_folder) if f.endswith('.txt')]
    label_list.sort()

    classes = {0: "fishing", 1: "no_fishing"}
    colores = [(0, 0, 255), (255, 0, 255)]

    for i in range(len(img_list)):
        image_path = os.path.join(img_folder, img_list[i])
        txt_path = os.path.join(label_folder, label_list[i])
        reses = draw_box_in_single_image(image_path, txt_path, img_list[i])
        print(reses)
        f.write(str(reses))
        f.write("\n")
    f.close()

五、开始计算指标

处理之后就可以得到检测后的fish_result.json和ori_data.txt。然后根据这两个文件来计算即可。

部分重要代码放在这里面:链接
在这里插入图片描述

五、实用工具

5.1 移动文件

import os
import shutil

# 源文件夹和目标文件夹的路径
source_folder = 'fishing_test_data'
destination_folder = 'test/image'

# 确保目标文件夹存在,如果不存在就创建它
if not os.path.exists(destination_folder):
    os.makedirs(destination_folder)

# 遍历源文件夹中的文件
for filename in os.listdir(source_folder):
    # 检查文件扩展名是否为图片格式,可以根据需要添加其他格式
    if filename.endswith(('.jpg', '.png', '.jpeg')):
        # 构建源文件的完整路径和目标文件的完整路径
        source_file_path = os.path.join(source_folder, filename)
        destination_file_path = os.path.join(destination_folder, filename)

        # 移动文件
        shutil.move(source_file_path, destination_file_path)
        print(f'Moved: {filename} to {destination_folder}')

5.2 可视化JSON标签

# -*- coding: utf-8 -*-
import cv2
import os
import json
import shutil
import numpy as np
from pathlib import Path
from glob import glob

id2cls = {0: 'fishing', 1: "no_fishing"}
cls2id = {'fishing': 0,  "no_fishing": 1}
id2color = {"fishing": (0, 255, 0), "no_fishing": (0, 255, 255)}


# 支持中文路径
def cv_imread(filePath):
    cv_img = cv2.imdecode(np.fromfile(filePath, dtype=np.uint8), flags=cv2.IMREAD_COLOR)
    return cv_img


def get_labelme_info(label_file):
    anno = json.load(open(label_file, "r", encoding="utf-8"))
    shapes = anno['shapes']
    image_path = os.path.basename(anno['imagePath'])
    labels = []
    for s in shapes:
        pts = s['points']
        x1, y1 = pts[0]
        x2, y2 = pts[1]
        color = id2color[s["label"]]
        labels.append([color, x1, y1, x2, y2])
    return labels, image_path


def vis_labelme(labelme_label_dir, save_dir='res/'):
    labelme_label_dir = str(Path(labelme_label_dir)) + '/'
    save_dir = str(Path(save_dir)) + '/'
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    json_files = glob(labelme_label_dir + '*.json')
    for ijf, jf in enumerate(json_files):
        print(ijf + 1, '/', len(json_files), jf)
        filename = os.path.basename(jf).rsplit('.', 1)[0]
        labels, image_path = get_labelme_info(jf)
        image = cv_imread(labelme_label_dir + image_path)
        for label in labels:
            color = label[0]
            x1, y1, x2, y2 = label[1:]
            x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
            cv2.rectangle(image, (x1, y1), (x2, y2), color, 3)
        # 显示图片
        # cv2.imshow(filename, image)
        # cv2.waitKey(0)
        # 支持中文路径,保存图片
        cv2.imencode(os.path.splitext(image_path)[-1], image)[1].tofile(save_dir + image_path)
    print('Completed!')


if __name__ == '__main__':
    root_dir = r'D:\Python\money\data\test'
    save_dir = r'D:\Python\money\data\test/t'
    vis_labelme(root_dir, save_dir)

5.3 可视化TXT标签

import cv2
import os

# 读取txt文件信息
def read_list(txt_path):
    pos = []
    with open(txt_path, 'r') as file_to_read:
        while True:
            lines = file_to_read.readline()  # 整行读取数据
            if not lines:
                break
            # 将整行数据分割处理,如果分割符是空格,括号里就不用传入参数,如果是逗号, 则传入‘,'字符。
            p_tmp = [float(i) for i in lines.split(' ')]
            pos.append(p_tmp)  # 添加新读取的数据
            # Efield.append(E_tmp)
            pass
    return pos

# txt转换为box
def convert(size, box):
    xmin = (box[1] - box[3] / 2.) * size[1]
    xmax = (box[1] + box[3] / 2.) * size[1]
    ymin = (box[2] - box[4] / 2.) * size[0]
    ymax = (box[2] + box[4] / 2.) * size[0]
    box = (int(xmin), int(ymin), int(xmax), int(ymax))
    return box

def draw_box_in_single_image(image_path, txt_path):
    # 读取图像
    image = cv2.imread(image_path)
    pos = read_list(txt_path)

    for i in range(len(pos)):
        label = classes[int(str(int(pos[i][0])))]
        print('label is '+label)
        box = convert(image.shape, pos[i])
        image = cv2.rectangle(image,(box[0], box[1]),(box[2],box[3]),colores[int(str(int(pos[i][0])))],2)
        cv2.putText(image, label,(box[0],box[1]-2), 0, 1, colores[int(str(int(pos[i][0])))], thickness=2, lineType=cv2.LINE_AA)

    cv2.imshow("images", image)
    cv2.waitKey(0)

if __name__ == '__main__':

    img_folder = r"F:\python\mission\fish_power_test\data\test\yolo_txt\train\images"
    img_list = os.listdir(img_folder)
    img_list.sort()

    label_folder = r"F:\python\mission\fish_power_test\data\test\yolo_txt\train/labels"
    label_list = os.listdir(label_folder)
    label_list.sort()

    classes = {0: "fishing", 1: "no_fishing"}
    colores = [(0,0,255),(255,0,255)]

    for i in range(len(img_list)):
        image_path = img_folder + "\\" + img_list[i]
        txt_path = label_folder + "\\" + label_list[i]
        draw_box_in_single_image(image_path, txt_path)

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

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

相关文章

【教学类-38-02】20230724京剧脸谱2.0——竖版(小彩图 大面具)(Python 彩图彩照转素描线描稿)

结果展示 背景需求&#xff1a; 前文体运用Python颜色提取功能&#xff0c;将“京剧脸谱”彩色图片转化为线描图案。 【教学类-38】20230724京剧脸谱1.0——横版“彩图线图等大”&#xff08;Python 彩图彩照转素描线描稿&#xff09;_reasonsummer的博客-CSDN博客 存在问题&…

大语言模型之十二 SentencePiece扩充LLama2中文词汇

大语言模型的发展潜力已经毋庸置疑了&#xff0c;如何让中文大语言模型更适合中小公司使用这是一道难题。在模型的选择上我们倾向于选择国外的LLama或者BLoom之类的&#xff0c;而不是百川之类的中文大模型&#xff0c;原因在于从基建到框架到数据国外的开源资料非常多&#xf…

背诵不等于理解,深度解析大模型背后的知识储存与提取

自然语言模型的背诵 (memorization) 并不等于理解。即使模型能完整记住所有数据&#xff0c;也可能无法通过微调 (finetune) 提取这些知识&#xff0c;无法回答简单的问题。 随着模型规模的增大&#xff0c;人们开始探索大模型是如何掌握大量知识的。一种观点认为这归功于 “无…

国庆共68条评论《乡村振兴战略下传统村落文化旅游旅游设计》许少辉八一新书

国庆共68条评论《乡村振兴战略下传统村落文化旅游旅游设计》许少辉八一新书 国庆共68条评论《乡村振兴战略下传统村落文化旅游旅游设计》许少辉八一新书

【STM32】IAP升级03关闭总中断,检测栈顶指针

IAP升级方法 IAP升级时需要关闭总中断 TM32在使用时有时需要禁用全局中断&#xff0c;比如MCU在升级过程中需禁用外部中断&#xff0c;防止升级过程中外部中断触发导致升级失败。 ARM MDK中提供了如下两个接口来禁用和开启总中断&#xff1a; __disable_irq(); // 关闭总中…

函数指针详解和简单使用

概念 函数指针&#xff1a;首先它是一个指针&#xff0c;一个指向函数的指针&#xff0c;在内存空间中存放的是函数的地址&#xff1b; 引入 #include <stdio.h>void test() {printf("hehe\n"); } int main() {printf("%p\n", test);printf(&quo…

基于 SpringBoot+Vue 的大学生租房网站

1 简介 本大学生租房系统使用简洁的框架结构&#xff0c;专门用于用户浏览首页&#xff0c;房屋信息&#xff0c;房屋评价&#xff0c;公告资讯&#xff0c;个人中心&#xff0c;后台管理&#xff0c;意见反馈等信息&#xff0c;对个人信息进行修改等&#xff0c;以及系统管理…

基于Java的大学生就业招聘系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

Java基础---第十篇

系列文章目录 文章目录 系列文章目录一、说说Java 中 IO 流二、 Java IO与 NIO的区别(补充)三、java反射的作用于原理一、说说Java 中 IO 流 Java 中 IO 流分为几种? 按照流的流向分,可以分为输入流和输出流; 按照操作单元划分,可以划分为字节流和字符流; 按照流的角色…

【笔试强训day02】倒置字符串 排序子序列

​&#x1f47b;内容专栏&#xff1a; 笔试强训集锦 &#x1f428;本文概括&#xff1a;C笔试强训day02。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.10.1 二、day02 1.倒置字符串 题目描述&#xff1a; 将一句话的单词进行倒置&…

工厂模式和单例模式

目录 一.设计模式 二.工厂模式和单例模式 &#x1f41e;单例模式 1.饿汉模式 2.懒汉模式 &#xff08;1&#xff09;问题一&#xff1a;大量对象的创建 &#xff08;2&#xff09;问题二&#xff1a;加锁导致阻塞等待 &#xff08;3&#xff09;问题三&#xff1a;指令…

MySql进阶篇---006:存储引擎,索引,SQL优化,视图、存储过程、变量、流程控制、游标、存储函数、触发器

1. 存储引擎 1.1 MySQL体系结构 1).连接层 最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念&#xff0c;为通过认证…

【面试经典150 | 矩阵】螺旋矩阵

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;模拟方法二&#xff1a;按层模拟 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于…

04. Springboot集成Mybatis-flex(二)

1、前言 上一篇文章《Springboot集成Mybatis-flex&#xff08;一&#xff09;》提到Mybatis Flex和Spring Boot的初步集成和基础使用。今天我们再来探索Mybatis Flex其他特性的使用。 2、数据填充 数据填充指的是&#xff0c;当 Entity 数据被插入 或者 更新的时候&#xff…

Ghostscript 字体处理深究: 解决字体缺失问题

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Hello World!1分钟配置好你的Go环境

目录 一、简介为什么选择Golang&#xff1f;Golang与其他语言的对比核心特性应用场景社区和生态系统性能标准企业级应用 二、环境要求操作系统WindowsLinux/UnixmacOS 硬件需求其他依赖软件异常情况和处理方法 三、下载和安装GolangWindows系统使用官方安装包使用Chocolatey&am…

使用CreateProcess崩溃:处未处理的异常: 0xC0000005: 写入位置 0x00415652 时发生访问冲突

问题代码 if (!CreateProcess(NULL,L"pela.exe",NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)){return 0;}如果CreateProcess的第二个参数字符串是常量或者是储存在堆中的就会被写保护&#xff0c;崩溃。如果字符串定义到栈或者全局变量就不存在此问题了。 正确的…

初级篇—第二章SELECT查询语句

文章目录 什么是SQLSQL 分类SQL语言的规则与规范阿里巴巴MySQL命名规范数据导入指令 显示表结构 DESC基本的SELECT语句SELECTSELECT ... FROM列的别名 AS去除重复行 DISTINCT空值参与运算着重号查询常数过滤数据 WHERE练习 运算符算术运算符加减符号乘除符号取模符号 符号比较运…

SNERT预备队招新CTF体验赛-Misc(SWCTF)

目录 1、最简单的隐写 2、旋转我 3、is_here 4、zip伪加密 5、压缩包密码爆破 6、我就藏在照片里 7、所以我放弃了bk 8、套娃 9、来自银河的信号 10、Track_Me 11、勇师傅的奇思妙想 1、最简单的隐写 下载附件后&#xff0c;图片格式并不支持打开 根据题目提示&…

Window 安装多个版本的 java 并按需切换

1、按需下载对应版本的 java 官网链接&#xff1a;Java Downloads | Oracle 2、执行安装程序&#xff0c;根据安装向导一步一步走就行&#xff0c;每个版本安装在不同的目录下。 3、配置环境变量 a&#xff09;为每个版本 java 新建不同名称的 JAVA_HOME 系统变量&#xff0…