xml转voc,voc转coco,coco转yolo,coco划分,coco检查,yolo检查,coco可视化
平常用coco格式的数据集比较多,所有这里整合一下数据集相关的常用的脚本。
pycocotools安装
这个非常重要,因为处理coco数据集时,用pycocotools包非常方便。
自行搜索一下怎么安装吧,windows安装比较麻烦。网上有很多方法,但是都有时效性,不定时就失效了。如果有好的安装pycocotools的文章,可以把链接评论在评论区。
xml转voc
xml2voc.py
# 命令行执行:  python xml2voc2007.py --input_dir data --output_dir VOCdevkit
# 输出文件夹必须为空文件夹
import argparse
import glob
import os
import random
import sys
import shutil
# 主程序执行
def xml2voc():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    parser.add_argument("--input_dir", default="data", help="input annotated directory")
    parser.add_argument("--output_dir", default="VOCdevkit", help="output dataset directory")
    args = parser.parse_args()
    if os.path.exists(args.output_dir):
        print("Output directory already exists:", args.output_dir)
        sys.exit(1)
    os.makedirs(args.output_dir)
    print("| Creating dataset dir:", os.path.join(args.output_dir, "VOC2007"))
    # 创建保存的文件夹
    if not os.path.exists(os.path.join(args.output_dir, "VOC2007", "Annotations")):
        os.makedirs(os.path.join(args.output_dir, "VOC2007", "Annotations"))
    if not os.path.exists(os.path.join(args.output_dir, "VOC2007", "ImageSets")):
        os.makedirs(os.path.join(args.output_dir, "VOC2007", "ImageSets"))
    if not os.path.exists(os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main")):
        os.makedirs(os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main"))
    if not os.path.exists(os.path.join(args.output_dir, "VOC2007", "JPEGImages")):
        os.makedirs(os.path.join(args.output_dir, "VOC2007", "JPEGImages"))
    # 获取目录下所有的.jpg文件列表
    total_img = glob.glob(os.path.join(args.input_dir, "*.jpg"))
    print('| Image number: ', len(total_img))
    # 获取目录下所有的joson文件列表
    total_xml = glob.glob(os.path.join(args.input_dir, "*.xml"))
    print('| Xml number: ', len(total_xml))
    percent_trainval = 0.8
    percent_train = 0.75
    num_total = len(total_xml)
    data_list = range(num_total)
    num_tv = int(num_total * percent_trainval)
    num_tr = int(num_tv * percent_train)
    num_trainval = random.sample(data_list, num_tv)
    num_train = random.sample(num_trainval, num_tr)
    print('| Train number: ', num_tr)
    print('| Val number: ', num_tv - num_tr)
    print('| Test number: ', num_total - num_tv)
    file_trainval = open(
        os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main", "trainval.txt"), 'w')
    file_test = open(
        os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main", "test.txt"), 'w')
    file_train = open(
        os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main", "train.txt"), 'w')
    file_val = open(
        os.path.join(args.output_dir, "VOC2007", "ImageSets", "Main", "val.txt"), 'w')
    for i in data_list:
        name = os.path.basename(total_xml[i])[:-4] + '\n'  # 去掉.xml后缀以及父级目录,只保留文件名
        if i in num_trainval:
            file_trainval.write(name)
            if i in num_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()
    if os.path.exists(args.input_dir):
        # root 所指的是当前正在遍历的这个文件夹的本身的地址
        # dirs 是一个 list,内容是该文件夹中所有的目录的名字(不包括子目录)
        # files 同样是 list, 内容是该文件夹中所有的文件(不包括子目录)
        for root, dirs, files in os.walk(args.input_dir):
            for file in files:
                src_file = os.path.join(root, file)
                if src_file.endswith(".jpg"):
                    shutil.copy(src_file, os.path.join(args.output_dir, "VOC2007", "JPEGImages"))
                else:
                    shutil.copy(src_file, os.path.join(args.output_dir, "VOC2007", "Annotations"))
    print('| Done!')
if __name__ == "__main__":
    print("—" * 50)
    xml2voc()
    print("—" * 50)
voc转coco
voc2coco.py
import json
import os
import shutil
import datetime
from PIL import Image
from tqdm import trange
root_dir = os.getcwd()
def voc2coco():
    # 处理coco数据集中category字段。
    # 创建一个 {类名 : id} 的字典,并保存到 总标签data 字典中。
    class_name_to_id = {'class1': 1, 'class2': 2, 'class3': 3, 'class4': 4, 'class5': 5, 'class6': 6, 'class7': 7, 'class8': 8}        # 改为自己的类别名称,以及对应的类别id
    # 创建coco的文件夹
    if not os.path.exists(os.path.join(root_dir, "coco")):
        os.makedirs(os.path.join(root_dir, "coco"))
        os.makedirs(os.path.join(root_dir, "coco", "annotations"))
        os.makedirs(os.path.join(root_dir, "coco", "train"))
        os.makedirs(os.path.join(root_dir, "coco", "val"))
    # 创建 总标签data
    now = datetime.datetime.now()
    data = dict(
        info=dict(
            description=None,
            url=None,
            version=None,
            year=now.year,
            contributor=None,
            date_created=now.strftime("%Y-%m-%d %H:%M:%S.%f"),
        ),
        licenses=[dict(url=None, id=0, name=None, )],
        images=[
            # license, file_name,url, height, width, date_captured, id
        ],
        type="instances",
        annotations=[
            # segmentation, area, iscrowd, image_id, bbox, category_id, id
        ],
        categories=[
            # supercategory, id, name
        ],
    )
    for name, id in class_name_to_id.items():
        data["categories"].append(
            dict(supercategory=None, id=id, name=name, )
        )
    # 处理coco数据集train中images字段。
    images_dir = os.path.join(root_dir, 'VOCdevkit', 'VOC2012', 'JPEGImages')
    images = os.listdir(images_dir)
    # 生成每个图片对应的image_id
    images_id = {}
    for idx, image_name in enumerate(images):
        images_id.update({image_name[:-4]: idx})
    # 获取训练图片
    train_img = []
    fp = open(os.path.join(root_dir, 'VOCdevkit', 'VOC2012', 'ImageSets', 'Main', 'train.txt'))
    for i in fp.readlines():
        train_img.append(i[:-1] + ".jpg")
    # 获取训练图片的数据
    for image in train_img:
        img = Image.open(os.path.join(images_dir, image))
        data["images"].append(
            dict(
                license=0,
                url=None,
                file_name=image,  # 图片的文件名带后缀
                height=img.height,
                width=img.width,
                date_captured=None,
                # id=image[:-4],
                id=images_id[image[:-4]],
            )
        )
    # 获取coco数据集train中annotations字段。
    train_xml = [i[:-4] + '.xml' for i in train_img]
    bbox_id = 0
    for xml in train_xml:
        category = []
        xmin = []
        ymin = []
        xmax = []
        ymax = []
        import xml.etree.ElementTree as ET
        tree = ET.parse(os.path.join(root_dir, 'VOCdevkit', 'VOC2012', 'Annotations', xml))
        root = tree.getroot()
        object = root.findall('object')
        for i in object:
            category.append(class_name_to_id[i.findall('name')[0].text])
            bndbox = i.findall('bndbox')
            for j in bndbox:
                xmin.append(float(j.findall('xmin')[0].text))
                ymin.append(float(j.findall('ymin')[0].text))
                xmax.append(float(j.findall('xmax')[0].text))
                ymax.append(float(j.findall('ymax')[0].text))
        for i in range(len(category)):
            data["annotations"].append(
                dict(
                    id=bbox_id,
                    image_id=images_id[xml[:-4]],
                    category_id=category[i],
                    area=(xmax[i] - xmin[i]) * (ymax[i] - ymin[i]),
                    bbox=[xmin[i], ymin[i], xmax[i] - xmin[i], ymax[i] - ymin[i]],
                    iscrowd=0,
                )
            )
            bbox_id += 1
    # 生成训练集的json
    json.dump(data, open(os.path.join(root_dir, 'coco', 'annotations', 'train.json'), 'w'))
    # 获取验证图片
    val_img = []
    fp = open(os.path.join(root_dir, 'VOCdevkit', 'VOC2012', 'ImageSets', 'Main', 'val.txt'))
    for i in fp.readlines():
        val_img.append(i[:-1] + ".jpg")
    # 将训练的images和annotations清空,
    del data['images']
    data['images'] = []
    del data['annotations']
    data['annotations'] = []
    # 获取验证集图片的数据
    for image in val_img:
        img = Image.open(os.path.join(images_dir, image))
        data["images"].append(
            dict(
                license=0,
                url=None,
                file_name=image,  # 图片的文件名带后缀
                height=img.height,
                width=img.width,
                date_captured=None,
                id=images_id[image[:-4]],   # 图片名作为id
            )
        )
    # 处理coco数据集验证集中annotations字段。
    val_xml = [i[:-4] + '.xml' for i in val_img]
    for xml in val_xml:
        category = []
        xmin = []
        ymin = []
        xmax = []
        ymax = []
        import xml.etree.ElementTree as ET
        tree = ET.parse(os.path.join(root_dir, 'VOCdevkit', 'VOC2012', 'Annotations', xml))
        root = tree.getroot()
        object = root.findall('object')
        for i in object:
            category.append(class_name_to_id[i.findall('name')[0].text])
            bndbox = i.findall('bndbox')
            for j in bndbox:
                xmin.append(float(j.findall('xmin')[0].text))
                ymin.append(float(j.findall('ymin')[0].text))
                xmax.append(float(j.findall('xmax')[0].text))
                ymax.append(float(j.findall('ymax')[0].text))
        for i in range(len(category)):
            data["annotations"].append(
                dict(
                    id=bbox_id,
                    image_id=images_id[xml[:-4]],
                    category_id=category[i],
                    area=(xmax[i] - xmin[i]) * (ymax[i] - ymin[i]),
                    bbox=[xmin[i], ymin[i], xmax[i] - xmin[i], ymax[i] - ymin[i]],
                    iscrowd=0,
                )
            )
            bbox_id += 1
    # 生成验证集的json
    json.dump(data, open(os.path.join(root_dir, 'coco', 'annotations', 'val.json'), 'w'))
    print('| VOC -> COCO annotations transform finish.')
    print('Start copy images...')
    # 复制图片
    m = len(train_img)
    for i in trange(m):
        shutil.copy(os.path.join(images_dir, train_img[i]), os.path.join(root_dir, 'coco', 'train', train_img[i]))
    print('| Train images copy finish.')
    m = len(val_img)
    for i in trange(m):
        shutil.copy(os.path.join(images_dir, val_img[i]), os.path.join(root_dir, 'coco', 'val', val_img[i]))
    print('| Val images copy finish.')
if __name__ == '__main__':
    voc2coco()
coco转yolo
coco数据集目录结构:
coco_small
├── train
│   ├── 001.jpg
│   ├── 002.jpg
│   ├── 003.jpg
│   └── ...
│
├── val
│   ├── 004.jpg
│   ├── 005.jpg
│   ├── 006.jpg
│   └── ...
├── test
│   ├── 007.jpg
│   ├── 008.jpg
│   ├── 009.jpg
│   └── ...
│
└── annotatoins
    ├── train.json
    ├── val.json
    └── test.json
生成的yolo数据集目录:
yolo_dataset
├── images
│   ├── 001.jpg
│   ├── 002.jpg
│   ├── 003.jpg
│   └── ...
│
├── labels
│   ├── 001.txt
│   ├── 002.txt
│   ├── 003.txt
│   └── ...
│
└── ImageSets
    ├── train.txt
    ├── val.txt
    └── test.txt
将coco的train,val,test分别转换为yolo的train,val,test
coco2yolo.py
# coco是x1,y1,w,h,yolo是x,y,w,h。 x1,y1是左上角坐标,x,y是中心坐标
import os
import shutil
from pycocotools.coco import COCO
from tqdm import trange
root_dir = os.getcwd()
# 将coco的bbox转换为yolo的bbox
def cocobbox2yolobbox(coco_box):
    x1, y1, w, h = coco_box
    x = x1 + w / 2
    y = y1 + h / 2
    return [x, y, w, h]
def coco2yolo(dataset_type, json_fp, origin_imgs_dir, save_dir):
    imgs_dir = os.path.join(save_dir, 'images')
    labels_dir = os.path.join(save_dir, 'labels')
    ImageSets_dir = os.path.join(save_dir, 'ImageSets')
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
        os.mkdir(imgs_dir)
        os.mkdir(labels_dir)
        os.mkdir(ImageSets_dir)
    text_data_fp = os.path.join(ImageSets_dir, dataset_type + '.txt')
    text_data = []
    coco = COCO(json_fp)
    imgs = coco.imgs
    img_ids = coco.getImgIds()
    m = len(img_ids)
    for i in trange(m):
        img_id = img_ids[i]
        filename = imgs[img_id]['file_name']
        text_data.append(os.path.join(imgs_dir, filename))
        txt_name = filename.split('.')[0] + ".txt"  # 对应的txt名字,与jpg一致
        f_txt = open(os.path.join(labels_dir, txt_name), 'w')
        ann_ids = coco.getAnnIds(imgIds=img_id)
        anns = coco.loadAnns(ann_ids)
        for ann in anns:
            bbox = cocobbox2yolobbox(ann["bbox"])
            f_txt.write("%s %s %s %s %s\n" % (ann['category_id'], bbox[0], bbox[1], bbox[2], bbox[3]))
        f_txt.close()
    # 将数据集写入文件
    with open(text_data_fp, 'w') as f:
        for line in text_data:
            f.write(line + '\n')
    print('labels create done.')
    for i in trange(m):
        img_id = img_ids[i]
        filename = imgs[img_id]['file_name']
        shutil.copy(os.path.join(origin_imgs_dir, filename), os.path.join(imgs_dir, filename))
    print('images copy done.')
def coco2yolo_type(dataset_type):
    save_dir = os.path.join(root_dir, 'yolo_dataset')
    if dataset_type == 'train':
        json_fp = os.path.join(root_dir, 'coco_small', 'annotations', 'train.json')
        imgs_dir = os.path.join(root_dir, 'coco_small', 'train')
        coco2yolo(dataset_type, json_fp, imgs_dir, save_dir)
    elif dataset_type == 'val':
        json_fp = os.path.join(root_dir, 'coco_small', 'annotations', 'val.json')
        imgs_dir = os.path.join(root_dir, 'coco_small', 'val')
        coco2yolo(dataset_type, json_fp, imgs_dir, save_dir)
    elif dataset_type == 'test':
        json_fp = os.path.join(root_dir, 'coco_small', 'annotations', 'test.json')
        imgs_dir = os.path.join(root_dir, 'coco_small', 'test')
        coco2yolo(dataset_type, json_fp, imgs_dir, save_dir)
if __name__ == '__main__':
    coco2yolo_type('train')
    coco2yolo_type('val')
    coco2yolo_type('test')
coco数据集划分为train,val,test
划分前目录结构:
coco
   +annotations
   +val2017
   +split_coco.py
划分后目录结构:
coco_small
   +annotations
      +train.json
      +val.json
      +test.json
   +train
   +val
   +test
split_coco.py
# 划分coco数据集
# 将coco数据集分为train和val两个子集
import json
import os
import random
import shutil
from pycocotools.coco import COCO
from tqdm import trange
train_percentage = 0.7
val_percentage = 0.2
root_dir = os.getcwd()
json_fp = os.path.join(root_dir, 'coco', 'annotations', 'instances_val2017.json')
img_dir = os.path.join(root_dir, 'coco', 'val2017')
save_dir = os.path.join(root_dir, 'coco_small')
def split_coco(json_fp, img_dir, save_dir):
    json_data = json.load(open(json_fp, 'r'))
    coco = COCO(json_fp)
    train_dir = os.path.join(save_dir, 'train')
    val_dir = os.path.join(save_dir, 'val')
    test_dir = os.path.join(save_dir, 'test')
    train_json = {'info': json_data['info'], 'licenses': json_data['licenses'], 'images': [], 'annotations': [],
                  'categories': json_data['categories']}
    val_json = {'info': json_data['info'], 'licenses': json_data['licenses'], 'images': [], 'annotations': [],
                'categories': json_data['categories']}
    test_json = {'info': json_data['info'], 'licenses': json_data['licenses'], 'images': [], 'annotations': [],
                 'categories': json_data['categories']}
    # 创建coco目录结构
    if os.path.exists(save_dir):
        shutil.rmtree(save_dir)
    os.makedirs(save_dir)
    os.mkdir(train_dir)
    os.mkdir(val_dir)
    os.mkdir(test_dir)
    os.mkdir(os.path.join(save_dir, 'annotations'))
    imgs = coco.imgs
    img_ids = coco.getImgIds()
    train_ids = random.sample(img_ids, int(len(img_ids) * train_percentage))
    val_ids = random.sample(list(set(img_ids) - set(train_ids)), int(len(img_ids) * val_percentage))
    m = len(img_ids)
    for i in trange(m):
        ann_ids = coco.getAnnIds(imgIds=img_ids[i])
        if img_ids[i] in train_ids:
            train_json['images'].append(imgs[img_ids[i]])
            shutil.copy(os.path.join(img_dir, imgs[img_ids[i]]['file_name']),
                        os.path.join(train_dir, imgs[img_ids[i]]['file_name']))
            for ann_id in ann_ids:
                train_json['annotations'].append(coco.anns[ann_id])
        elif img_ids[i] in val_ids:
            val_json['images'].append(imgs[img_ids[i]])
            shutil.copy(os.path.join(img_dir, imgs[img_ids[i]]['file_name']),
                        os.path.join(val_dir, imgs[img_ids[i]]['file_name']))
            for ann_id in ann_ids:
                val_json['annotations'].append(coco.anns[ann_id])
        else:
            test_json['images'].append(imgs[img_ids[i]])
            shutil.copy(os.path.join(img_dir, imgs[img_ids[i]]['file_name']),
                        os.path.join(test_dir, imgs[img_ids[i]]['file_name']))
            for ann_id in ann_ids:
                test_json['annotations'].append(coco.anns[ann_id])
    with open(os.path.join(save_dir, 'annotations', 'train.json'), 'x') as f:
        json.dump(train_json, f)
    with open(os.path.join(save_dir, 'annotations', 'val.json'), 'x') as f:
        json.dump(val_json, f)
    with open(os.path.join(save_dir, 'annotations', 'test.json'), 'x') as f:
        json.dump(test_json, f)
if __name__ == '__main__':
    split_coco(json_fp, img_dir, save_dir)
    print('done')
coco数据集图片检查
check_coco.py
# 检查coco数据集每张图片能否打开
import os
import cv2
from pycocotools.coco import COCO
from tqdm import trange
root_dir = os.getcwd()
def check_coco(json_fp, img_dir):
    coco = COCO(json_fp)
    imgs = coco.imgs
    img_ids = coco.getImgIds()
    for i in trange(len(img_ids)):
        img_fp = os.path.join(img_dir, imgs[img_ids[i]]['file_name'])
        img = cv2.imread(img_fp)
        try:
            img.shape
        except:
            print(img_fp)
if __name__ == '__main__':
    json_fp = os.path.join(root_dir, 'coco', 'annotations', 'instances_val2017.json')
    img_dir = os.path.join(root_dir, 'coco', 'val2017')
    check_coco(json_fp, img_dir)
    print('done')
yolo数据集图片检查
check_yolo.py
# 检查yolo数据集每张图片能否打开
import os
import cv2
from tqdm import trange
root_dir = os.getcwd()
def check_coco(txt_fp):
    imgs = []
    with open(txt_fp, 'r') as f:
        for line in f:
            imgs.append(line.strip())
    for i in trange(len(imgs)):
        img = cv2.imread(imgs[i])
        try:
            s = img.shape
        except:
            print(imgs[i])
if __name__ == '__main__':
    txt_fp = os.path.join(root_dir, 'yolo_dataset', 'annotations', 'train.txt')
    check_coco(txt_fp)
    print('done')
coco数据集bbox可视化
visiual_coco.py
import os
import random
import cv2
from pycocotools.coco import COCO
from tqdm import trange
root_dir = os.getcwd()
# 检查转变后coco的json文件,坐标是否正确。
def visiual_coco(json_fp, images_dir):
    coco = COCO(json_fp)
    imgs = coco.imgs
    img_ids = coco.getImgIds()
    cats = coco.cats
    random.shuffle(img_ids)
    for i in trange(len(img_ids)):
        img_fp = os.path.join(images_dir, imgs[img_ids[i]]['file_name'])
        img = cv2.imread(img_fp)
        ann_ids = coco.getAnnIds(imgIds=img_ids[i])
        anns_ = coco.loadAnns(ann_ids)
        for ann in anns_:
            bbox = ann['bbox']
            left_top = (int(bbox[0]), int(bbox[1]))  # coco数据集中bbox的含义是x1,y1,w,h
            right_bottom = (int(bbox[0]) + int(bbox[2]), int(bbox[1]) + int(bbox[3]))
            cv2.rectangle(img, left_top, right_bottom, (0, 255, 0), 2)  # 图像,左上角,右下坐标,颜色,粗细
            cv2.putText(img, cats[ann['category_id']]['name'], left_top, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
        cv2.imshow('image', img)
        cv2.waitKey(0)
    cv2.destroyAllWindows()
if __name__ == '__main__':
    json_fp = os.path.join(root_dir, 'coco', 'annotations', 'instances_val2017.json')
    images_dir = os.path.join(root_dir, 'coco', 'val2017')
    visiual_coco(json_fp, images_dir)
												
											xml转voc,voc转coco,coco转yolo,coco划分,coco检查,yolo检查,coco可视化的更多相关文章
- 训练自己数据-xml文件转voc格式
		
首先我们有一堆xml文件 笔者是将mask-rcnn得到的json标注文件转为xml的 批量json转xml方法:https://www.cnblogs.com/bob-jianfeng/p/1112 ...
 - COCO数据集深入理解
		
TensorExpand/TensorExpand/Object detection/Data_interface/MSCOCO/ 深度学习数据集介绍及相互转换 Object segmentation ...
 - [PocketFlow]解决TensorFLow在COCO数据集上训练挂起无输出的bug
		
1. 引言 因项目要求,需要在PocketFlow中添加一套PeleeNet-SSD和COCO的API,具体为在datasets文件夹下添加coco_dataset.py, 在nets下添加pelee ...
 - Microsoft COCO 数据集
		
本篇博客主要以介绍MS COCO数据集为目标,分为3个部分:COCO介绍,数据集分类和COCO展示. 本人主要下载了其2014年版本的数据,一共有20G左右的图片和500M左右的标签文件.标签文件标记 ...
 - COCO 数据集的使用
		
Windows 10 编译 Pycocotools 踩坑记 COCO数据库简介 微软发布的COCO数据库, 除了图片以外还提供物体检测, 分割(segmentation)和对图像的语义文本描述信息. ...
 - 自制 COCO api 直接读取类 COCO 的标注数据的压缩文件
		
第6章 COCO API 的使用 COCO 数据库是由微软发布的一个大型图像数据集,该数据集专为对象检测.分割.人体关键点检测.语义分割和字幕生成而设计.如果你要了解 COCO 数据库的一些细节,你可 ...
 - COCO 数据集使用说明书
		
下面的代码改写自 COCO 官方 API,改写后的代码 cocoz.py 被我放置在 Xinering/cocoapi.我的主要改进有: 增加对 Windows 系统的支持: 替换 defaultdi ...
 - 《Microsoft COCO Captions Data Collection and Evaluation Server》论文笔记
		
出处:CVPR2015 Motivation 本文描述了MSCoco标题数据集及评估服务器(Microsoft COCO Caption dataset and evaluation server), ...
 - coco标注信息与labelme标注信息的详解、相互转换及可视化
		
引言 在做实例分割或语义分割的时候,我们通常要用labelme进行标注,labelme标注的json文件与coco数据集已经标注好的json文件的格式和内容有差异.如果要用coco数据集的信息,就要对 ...
 - 解决 Jumpserver coco 使用登录用户(ldap)进行SSH连接目标主机,忽略系统用户
		
前言 Jumpserver 作为国内流行的开源堡垒机,很多公司都在尝试使用,同时 Jumpserver 为了契合众多公司的用户认证,也提供了 LDAP 的用户认证方式,作为 Jumpserver 的用 ...
 
随机推荐
- 5、mysql优化--索引使用情况、索引的结构
			
避免索引失效 1). 全值匹配 ,对索引中所有列都指定具体值. 2). 最左前缀法则 如果索引了多列,要遵守最左前缀法则.指的是查询从索引的最左前列开始,并且不跳过索引中的列. 3). 范围查询右边的 ...
 - zabbix“专家坐诊”第178期问答汇总
			
大家好,我是乐乐.早在三年前,我们就在社区举办了zabbix公益问答活动,并且定在每周三邀请资深的zabbix技术工程师,为社群的小伙伴进行免费的答疑.到现在已经178期了.后续我将会把每期的答疑汇总 ...
 - vscode 翻译插件推荐 Easy Translator,只因为有音标,和位置好
			
vscode 翻译插件推荐 Easy Translator,只因为有音标,和位置好
 - vue-cli-service build 时间戳 方便查看bug发布时间和项目发布时间对比
			
vue.config.js let ret = '' const date = new Date() ret += date.getFullYear() ret += '-'+ (date.getMo ...
 - STM32芯片SPI接口接收数据左移一位问题定位总结
			
一 问题 最近在一个项目中,调试SPI的过程中遇到一个问题--接收数据整体向左移了一位(1bit).SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节( ...
 - kettle教程--通过配置文件同步所需要的列数据
			
kettle教程--通过配置文件同步所需要的列数据 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章, 关注回复「kettle」, 免费领取全网最热的kettle实战视频教程 ht ...
 - MediaCodec硬解流程
			
一 MediaCodec概述 MediaCodec是Android 4.1(api 16)版本引入的低层编解码接口,同时支持音视频的编码和解码.通常与MediaExtractor.MediaMuxer ...
 - PAT 甲级【1011 World Cup Betting】
			
import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; public ...
 - STL:vector中如何使用at()来避免程序报错
			
#include <iostream> #include <vector> using namespace std; int main() { vector<int> ...
 - JavaScript知识总结 基础篇
			
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. new操作符的实现原理 new操作符的执行过程: (1)首先创建了一个新的空对象 (2)设置原型,将对象的原型设置为函数的 prot ...