基于Yolov5的二维码QR码识别

news2025/1/15 16:41:27

1.QR code介绍

一个 QR 码可以分为两个部分:功能图形和编码区域。

 

 

数据集 大小10,85张

 1.1 通过split_train_val.py得到trainval.txt、val.txt、test.txt  

# coding:utf-8
 
import os
import random
import argparse
 
parser = argparse.ArgumentParser()
#xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
#数据集的划分,地址选择自己数据下的ImageSets/Main
parser.add_argument('--txt_path', default='ImageSets/Main', type=str, help='output txt label path')
opt = parser.parse_args()
 
trainval_percent = 0.9
train_percent = 0.8
xmlfilepath = opt.xml_path
txtsavepath = opt.txt_path
total_xml = os.listdir(xmlfilepath)
if not os.path.exists(txtsavepath):
    os.makedirs(txtsavepath)
 
num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)
 
file_trainval = open(txtsavepath + '/trainval.txt', 'w')
file_test = open(txtsavepath + '/test.txt', 'w')
file_train = open(txtsavepath + '/train.txt', 'w')
file_val = open(txtsavepath + '/val.txt', 'w')
 
for i in list_index:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        file_trainval.write(name)
        if i in train:
            file_train.write(name)
        else:
            file_val.write(name)
    else:
        file_test.write(name)
 
file_trainval.close()
file_train.close()
file_val.close()
file_test.close()

1.2 通过voc_label.py得到适合yolov5训练需要的

# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import os
from os import getcwd
 
sets = ['train', 'val']
classes = ["QR"]   # 改成自己的类别
abs_path = os.getcwd()
print(abs_path)
 
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 convert_annotation(image_id):
    in_file = open('Annotations/%s.xml' % (image_id), encoding='UTF-8')
    out_file = open('labels/%s.txt' % (image_id), 'w')
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        #difficult = obj.find('Difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
             float(xmlbox.find('ymax').text))
        b1, b2, b3, b4 = b
        # 标注越界修正
        if b2 > w:
            b2 = w
        if b4 > h:
            b4 = h
        b = (b1, b2, b3, b4)
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
 
wd = getcwd()
for image_set in sets:
    if not os.path.exists('labels/'):
        os.makedirs('labels/')
    image_ids = open('ImageSets/Main/%s.txt' % (image_set)).read().strip().split()
    list_file = open('%s.txt' % (image_set), 'w')
    for image_id in image_ids:
        list_file.write(abs_path + '/images/%s.jpg\n' % (image_id))
        convert_annotation(image_id)
    list_file.close()

 2.基于yolov5的QR码检测

2.1配置 QR.yaml

# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: data/QR/train.txt # 16551 images
val: data/QR/val.txt  # 4952 images

# number of classes
nc: 1

# class names
names: ['QR']

2.2 修改yolov5s_QR.yaml

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# Parameters
nc: 1  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)

   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

2.3 训练QR码检测模型

parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=ROOT / 'weights/yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='model.yaml path')
    parser.add_argument('--data', type=str, default=ROOT / 'data/QR.yaml', help='dataset.yaml path')
    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch-low.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=100, help='total training epochs')
    parser.add_argument('--batch-size', type=int, default=8, help='total batch size for all GPUs, -1 for autobatch')
    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
    parser.add_argument('--noval', action='store_true', help='only validate final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable AutoAnchor')
    parser.add_argument('--noplots', action='store_true', help='save no plot files')
    parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache', type=str, nargs='?', const='ram', help='image --cache ram/disk')
    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
    parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
    parser.add_argument('--optimizer', type=str, choices=['SGD', 'Adam', 'AdamW'], default='SGD', help='optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--workers', type=int, default=0, help='max dataloader workers (per RANK in DDP mode)')
    parser.add_argument('--project', default=ROOT / 'runs/train_QR', help='save to project/name')
    parser.add_argument('--name', default='exp', help='save to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--quad', action='store_true', help='quad dataloader')
    parser.add_argument('--cos-lr', action='store_true', help='cosine LR scheduler')
    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
    parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')
    parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone=10, first3=0 1 2')
    parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')
    parser.add_argument('--seed', type=int, default=0, help='Global training seed')
    parser.add_argument('--local_rank', type=int, default=-1, help='Automatic DDP Multi-GPU argument, do not modify')

开启python train.py 

3.性能评价

map 为0.962

 检测结果图:

 

4.QR码识别

4.1 转成onnx模型

python export.py --weights runs/train_QR/exp3/weights/best.pt --include  onnx  engine --device cpu

4.2 基于opencv的QR码识别

import cv2
import time
import sys
import numpy as np



det = cv2.QRCodeDetector()

def build_model(is_cuda):
    net = cv2.dnn.readNet("best.onnx") 
    if is_cuda:  
        print("Attempty to use CUDA")
        net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
        net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA_FP16)
    else:
        print("Running on CPU")
        net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
        net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
    return net

INPUT_WIDTH = 640
INPUT_HEIGHT = 640
SCORE_THRESHOLD = 0.2
NMS_THRESHOLD = 0.4
CONFIDENCE_THRESHOLD = 0.4

def detect(image, net): 
    blob = cv2.dnn.blobFromImage(image, 1/255.0, (INPUT_WIDTH, INPUT_HEIGHT), swapRB=True, crop=False)
    net.setInput(blob)
    preds = net.forward()
    return preds



def load_classes():  
    class_list = []
    with open("classes.txt", "r") as f:
        class_list = [cname.strip() for cname in f.readlines()]
    return class_list

class_list = load_classes()

def wrap_detection(input_image, output_data):  
    class_ids = []  
    confidences = []  
    boxes = [] 

    rows = output_data.shape[0] 

    image_width, image_height, _ = input_image.shape

    x_factor = image_width / INPUT_WIDTH  
    y_factor =  image_height / INPUT_HEIGHT

    for r in range(rows):
        row = output_data[r]
        confidence = row[4]
        if confidence >= 0.4:  

            classes_scores = row[5:]
            _, _, _, max_indx = cv2.minMaxLoc(classes_scores)
            class_id = max_indx[1]
            if (classes_scores[class_id] > .25):

                confidences.append(confidence)

                class_ids.append(class_id)

                x, y, w, h = row[0].item(), row[1].item(), row[2].item(), row[3].item() 
                left = int((x - 0.5 * w) * x_factor)
                top = int((y - 0.5 * h) * y_factor)
                width = int(w * x_factor)
                height = int(h * y_factor)
                box = np.array([left, top, width, height])
                boxes.append(box)

    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.25, 0.45) 

    result_class_ids = []
    result_confidences = []
    result_boxes = []

    for i in indexes:
        result_confidences.append(confidences[i])
        result_class_ids.append(class_ids[i])
        result_boxes.append(boxes[i])

    return result_class_ids, result_confidences, result_boxes

def format_yolov5(frame):  

    row, col, _ = frame.shape
    _max = max(col, row)
    result = np.zeros((_max, _max, 3), np.uint8)
    result[0:row, 0:col] = frame
    return result


colors = [(255, 255, 0), (0, 255, 0), (0, 255, 255), (255, 0, 0)] 

is_cuda = len(sys.argv) > 1 and sys.argv[1] == "cuda"

net = build_model(is_cuda)  


start = time.time_ns()
frame_count = 0
total_frames = 0
fps = -1


frame = cv2.imread('QR-00345.jpg')
inputImage = format_yolov5(frame)  
outs = detect(inputImage, net) 

class_ids, confidences, boxes = wrap_detection(inputImage, outs[0]) 

for (classid, confidence, box) in zip(class_ids, confidences, boxes): 
    color = colors[int(classid) % len(colors)]
    ROI=frame[(box[1]):(box[1]+box[3]),(box[0]):(box[0]+box[2])]  
    
    
    data, pts, st_code = det.detectAndDecode(ROI)  
    print(data)
    
    cv2.rectangle(frame, box, color, 2) 
    #cv2.rectangle(frame, (box[0], box[1] - 20), (box[0] + box[2], box[1]), color, -1)
    #cv2.putText(frame, class_list[classid], (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0))
    cv2.putText(frame, str(data), (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0,0,0))
 
    

cv2.imshow("output", frame)  
cv2.waitKey(10000)



检测结果

4.3 基于zbar的QR码识别 

import cv2
import time
import sys
import numpy as np
import zxing
from pyzbar import pyzbar




def build_model(is_cuda):
    net = cv2.dnn.readNet("best.onnx")
    if is_cuda:
        print("Attempty to use CUDA")
        net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
        net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA_FP16)
    else:
        print("Running on CPU")
        net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
        net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
    return net

INPUT_WIDTH = 640
INPUT_HEIGHT = 640
SCORE_THRESHOLD = 0.2
NMS_THRESHOLD = 0.4
CONFIDENCE_THRESHOLD = 0.4

def detect(image, net):
    blob = cv2.dnn.blobFromImage(image, 1/255.0, (INPUT_WIDTH, INPUT_HEIGHT), swapRB=True, crop=False)
    net.setInput(blob)
    preds = net.forward()
    return preds

def load_capture():
    capture = cv2.VideoCapture("sample.mp4")
    return capture

def load_classes():
    class_list = []
    with open("classes.txt", "r") as f:
        class_list = [cname.strip() for cname in f.readlines()]
    return class_list

class_list = load_classes()

def wrap_detection(input_image, output_data):
    class_ids = []
    confidences = []
    boxes = []

    rows = output_data.shape[0]

    image_width, image_height, _ = input_image.shape

    x_factor = image_width / INPUT_WIDTH
    y_factor =  image_height / INPUT_HEIGHT

    for r in range(rows):
        row = output_data[r]
        confidence = row[4]
        if confidence >= 0.4:

            classes_scores = row[5:]
            _, _, _, max_indx = cv2.minMaxLoc(classes_scores)
            class_id = max_indx[1]
            if (classes_scores[class_id] > .25):

                confidences.append(confidence)

                class_ids.append(class_id)

                x, y, w, h = row[0].item(), row[1].item(), row[2].item(), row[3].item() 
                left = int((x - 0.5 * w) * x_factor)
                top = int((y - 0.5 * h) * y_factor)
                width = int(w * x_factor)
                height = int(h * y_factor)
                box = np.array([left, top, width, height])
                boxes.append(box)

    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.25, 0.45) 

    result_class_ids = []
    result_confidences = []
    result_boxes = []

    for i in indexes:
        result_confidences.append(confidences[i])
        result_class_ids.append(class_ids[i])
        result_boxes.append(boxes[i])

    return result_class_ids, result_confidences, result_boxes

def format_yolov5(frame):

    row, col, _ = frame.shape
    _max = max(col, row)
    result = np.zeros((_max, _max, 3), np.uint8)
    result[0:row, 0:col] = frame
    return result


colors = [(255, 255, 0), (0, 255, 0), (0, 255, 255), (255, 0, 0)]

is_cuda = len(sys.argv) > 1 and sys.argv[1] == "cuda"

net = build_model(is_cuda)
capture = load_capture()

start = time.time_ns()
frame_count = 0
total_frames = 0
fps = -1


frame = cv2.imread('QR-00345.jpg')
inputImage = format_yolov5(frame)
outs = detect(inputImage, net)

class_ids, confidences, boxes = wrap_detection(inputImage, outs[0])


for (classid, confidence, box) in zip(class_ids, confidences, boxes):
    color = colors[int(classid) % len(colors)]
    ROI=frame[(box[1]):(box[1]+box[3]),(box[0]):(box[0]+box[2])]
    
    #barcode = zx.decode(ROI)
    #print(barcode.parsed)
    data = pyzbar.decode(ROI)
    print(data)
    
    cv2.rectangle(frame, box, color, 2)
    #cv2.rectangle(frame, (box[0], box[1] - 20), (box[0] + box[2], box[1]), color, -1)
    #cv2.putText(frame, class_list[classid], (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0))
    cv2.putText(frame, str(data), (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0,0,0))
  
    

cv2.imshow("output", frame)
cv2.waitKey(10000)



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

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

相关文章

设计模式-结构型模式之代理模式

6. 代理模式 6.1. 模式动机 在某些情况下&#xff0c;一个客户不想或者不能直接引用一个对 象&#xff0c;此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用&#xff0c;并且可以通过代理对象去掉客户不能看到 的内…

江苏专转本盐城工学院管理学章节习题

江苏专转本盐城工学院管理学章节习题第一章 管理活动与管理理论 一、单项选择题 1.企业在销售产品时,需要预估货款回收的可能性。为此&#xff0c;信用审核部门力图以一种低成本的方式处理有关客户资信的材料,但因为过程速度太慢,使许多客户另求他处购货。该项信用审核工作可…

Power Automate实现自动填充Word

创建Word模板 1、创建一个Word&#xff0c;按需求写好内容 2、在需要填充的地方插入开发工具-纯文本内容控件 3、编辑控件属性&#xff0c;用于Power Automate中区分字段 4、模板完成后上传至Sharepoint站点中 创建Forms 也可使用Sharepoint列表作申请单&#xff0c;这步就…

实战:快速实现iOS应用中集成即时通讯IM和UI

准备 熟练objective-c语言 有一台mac电脑,并安装了xcode 和 cocoapods 目标 手把手教大家在iOS应用中集成即时通讯IM 功能 内容篇幅较长,需要内心平和耐心看下去,务必戒躁.阅读本文并按照本文进行对接预计时长2小时 注册Appkey和username 本教程以集成环信IM为例 注册环信…

SpringBoot 整合 ES (四十二)

我看到希望&#xff0c;哪怕只有微小的一束光&#xff0c;我也会拼尽全力去寻找 上一章简单介绍了 SpringBoot 整合 RabbitMQ (四十一), 如果没有看过,请观看上一章 ES 相应的教程&#xff0c;可以看老蝴蝶之前写的文章: https://blog.csdn.net/yjltx1234csdn/category_122775…

Java 基础常识

一、Java运行机制 1.Java运行原理 编译&#xff1a;.java(源代码) ---> .class(字节码) 解释&#xff1a;.class(字节码) ---> 加载并启动JVM(类加载) ---> .class(机器指令) 执行&#xff1a;通过JVM来完成运行输出 2.Java运行过程 利用 javac 编译 .java 文件 利…

欧姆龙CP1H系列PLC通讯扩展与数据采集

一、应用场景 纺织厂的粗纱机&#xff0c;控制系统由1台欧姆龙CP1H的PLC和1台昆仑通泰MCGS的触摸屏组成&#xff0c;触摸屏连接到PLC通讯扩展的接口CP1W-CIF01&#xff08;RS232串行通讯&#xff09;。现在MES管理系统&#xff0c;需要采集设备的数据&#xff0c;要求不改变原来…

【详解C++中的引用】

文章目录 一、什么是引用二、引用规则三、引用特性四、使用场景1.做函数参数2.做返回值五、常引用 ps&#xff1a;为什么类型转换会产生临时变量&#xff1f; 六、引用和指针的区别总结 一、什么是引用 引用就是给一个变量取别名。 注意&#xff1a;这个引用不会新开辟一块空…

微信小程序自定义组件:组件间通讯

前言 略 组件间通信 组件间的基本通信方式有以下几种&#xff1a; WXML 数据绑定&#xff1a;用于父组件向子组件的指定属性设置数据&#xff0c;仅能设置 JSON 兼容数据&#xff08;自基础库版本 2.0.9 开始&#xff0c;还可以在数据中包含函数&#xff09;。具体在 组件模…

Mybatis-plus 两种分页方法(分单表和联表)

mybatis-plus分别使用 一、PageHelper插件分页使用 准备1&#xff1a;引入PageHelper依赖 <!-- pagehelper 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId>…

面试高频代码题

文章目录 链表1.删除有序链表中的重复链表2.删除有序链表的重复数组并只保留只出现过一次的结点3. 无序单链表升序排列 数组1. 冒泡排序2. 折半查找3. 快排4.给1001个数&#xff0c;有一个是重复的&#xff0c;如何不使用额外空间找出来这个数&#xff1f;&#xff08;微软&…

智能文案改写工具-智能改写工具免费

智能写作机器人 智能写作机器人&#xff0c;这是一种让人类写作变得更加简单的创新技术。它的出现&#xff0c;为内容生产领域带来了巨大的进步&#xff0c;不仅提高了人们的写作效率&#xff0c;还让优质的内容更容易被产生和共享。现在&#xff0c;让我们来了解一下智能写作…

Spring Security --- formLogin配置

目录 环境准备 配置自定义登录表单页面 配置登录成功的跳转页面方式 配置登录失败的跳转页面方式 前端表单参数获取 CustomWebSecurityConfigurerAdapter配置类代码示例 环境准备 创建springboot项目引入spring security框架引入thymeleaf模板引擎 配置自定义登录表单页面…

TryHackMe-Year of the Pig(Linux渗透测试)

Year of the Pig 有些猪会飞&#xff0c;有些有故事要讲。开始吧&#xff01; 端口扫描 循例nmap Web枚举 进入80 gobuster扫 进到/admin&#xff0c;尝试弱口令&#xff0c;给出了密码提示 密码本身的一些很简单的单词&#xff0c;密码的后三位是两位数字加一个特殊字符 我…

Flask(Jinja2)服务端模板注入漏洞(SSTI)整理

整理一下Flask框架下的SSTI漏洞相关知识&#xff1a; 漏洞原理 Flask是一个很常用的python框架&#xff0c;其中存在SSTI漏洞。 SSTI&#xff0c;服务端模板注入&#xff0c;很早就知道这个东西&#xff0c;但没有仔细整理过&#xff0c;作为一种注入漏洞&#xff0c;简单说…

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数 最近公共祖先[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/)[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-b…

redis单机最大并发量

redis单机最大并发量 布隆过滤器多级缓存客户端缓存应用层缓存Expires和Cache-Control的区别Nginx缓存管理 服务层缓存进程内缓存进程外缓存 缓存数据一致性问题的解决引入多级缓存设计的时刻 Redis的速度非常的快,单机的Redis就可以⽀撑 每秒十几万的并发,相对于MySQL来说,性…

Linux中将Python2升到Python3

目录 1、安装依赖包 2、下载python3 方式一 方式二 3.解压文件 4.安装 5.建立软连接 1、安装依赖包 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-dev…

Mysql·分库分表

Mysql分库分表 在mysql中新建数据库用以表分库分表mycat解压后配置文件参数server.xml 主要配置mycat服务的参数&#xff0c;比如端口号&#xff0c;myact用户名和密码使用的逻辑数据库等rule.xml 主要配置路由策略&#xff0c;主要有分片的片键&#xff0c;拆分的策略&#xf…

Elasticsearch:Elasticsearch 容量规划

Elasticsearch 是一个可扩展的分布式系统&#xff0c;可为企业搜索、日志聚合、可观察性和安全性提供解决方案。 Elastic 解决方案建立在一个单一、灵活的技术堆栈之上&#xff0c;可以部署在任何地方。 要在自托管或云端运行生产环境 Elasticsearch&#xff0c;需要规划基础架…