牛仔行头目标检测竞赛 李沐老师Kaggle(有代码有注释)

 一、比赛地址

CowBoy Outfits Detection | Kaggle

 二、数据介绍

这次比赛的数据集一共有4879个image,需要自己划分训练集和验证集。annotation的格式是json,因此如果用yolo系列的算法会涉及到json2txt这一步。当然如果不用yolo系列的就不要这段代码了。本文使用的是yolov5,所以文章内有json2txt的代码

 json里面是一个大的字典,里面有三个键值对。第一个key是info,这个是描述的数据集信息,第二个image,里面有一些图片的文件名称之类的,如下图所示,最后一个key是annotation,里面有被标记的物体的坐标,xywh等一些关键信息。这个json文件比较特殊,annotation和img对应上需要id对应,而不是文件名,在image里面的id和annotation的image_id是能够匹配上的关键信息。

接下来我就来处理这些数据

三、代码,注释

第一步当然是导包了 

import os
import json
import yaml
import pandas as pd
import shutil
import random

 第二步是加载数据

data =json.load(open(r"D:\cowboyoutfits\\train.json", 'r'))
label = data['annotations'] # 这个就是把json文件里的annotations提取出来了
# print(label)
random.seed(34) # 随机种子的作用是为了固定每次被随机采样的img,在划分train和val用
random.shuffle(label) #打乱标签

 第三步是print一下每个类别的数量,以便确定valset里面的每个类别的数量

ci = [87,1034,131,318,588]  #这个数据是从json文件中获得的,就是category_id
print('total:') # 打印每个类别的总数,每个类别对应一个数据
for i in ci:
    count = 0  # 注意count的位置,我上次leetcode刷题放错位置了,导致一直输出0
    for j in label:
        if j['category_id'] == i:
            count +=1
    print(f'id:{i} counts:{count}')

 第四步

print是你的好朋友,在看不懂的时候需要print,也需要print(type())

total_id = set(each['image_id'] for each in label ) # 比较复杂,for循环获取每个label中的字典,label的类型是string,里面包含的是dict,然后在获取image_id,转化为集合
# print(len(total_id))
# print(total_id)

 第五步,这一步是找出符合要求的图片作为valset

val_id = set()  # total_id用的集合,这里也用集合,可以保证唯一性
a, b, c, d, e = 0, 0, 0, 0, 0
# val的数量少于50=2+20+4+7+17
for each in label:
    if (each['category_id'] == ci[0] ) and (a < 2):
        val_id.add(each['image_id'])  # 集合的属性,add,list属性是append
        a +=1  # 这一步是处理图片
    elif (each['category_id'] == ci[1]) and (b < 20):
        val_id.add(each['image_id'])
        b +=1
    elif (each['category_id'] == ci[2]) and (c < 4):
        val_id.add(each['image_id'])
        c +=1
    elif (each['category_id'] == ci[3]) and (d < 7):
        val_id.add(each['image_id'])
        d +=1
    elif (each['category_id'] == ci[4]) and (e < 17):
        val_id.add(each['image_id'])
        e +=1

第六步,valset的img已经找到,现在需要找出对应的annotation,下面的算法,有一个复杂度是n^2,想不到复杂度更低的,如果大家能想出来,欢迎大家踊跃评论。

# 先通过种类找出image_id,再通过image_id找出annotations
# val_ann = [each_ann for each_ann in label if each_ann['image_id'] in val_id] # 这个也不快,还难懂
val_ann = []  # 开始处理annotations
for imid in val_id: # 这样处理其实很慢的,复杂度是n*m,不过数量比较少,实际有用的结果只有n(相等时)
    for each_ann in label:
        if each_ann['image_id'] == imid:
            val_ann.append(each_ann) # list append

print(len(val_id),len(val_ann))
# 50, 177
#不一样是因为有的一张图片有多个object

第七步,打印valset的总框数 

print('val_set')

for kind in ci:
    num = 0
    for i in val_ann:
        if i['category_id'] == kind:
            num += 1 
    print(f'id: {kind} counts: {num}') # 这个应该是物体的数量,总框数

 第八步,总的数据集减去valset,就是trainset

train_id = total_id - val_id # 这个是集合的减法
# print(train_id = total_id - val_id) 
train_ann = []
for each_ann in label:
    for tid in train_id:  
        if each_ann['image_id'] == tid:
            train_ann.append(each_ann)
            break # 找到就退出内层循环,去掉break会得到重复的结果  for循环换一下就能省掉break了,因为tid是唯一的,each_ann可能是多个
print(len(train_id),len(train_ann))  # 标签和照片数量不等是因为每个照片可能有多个标签

 第九步,创建文件夹,将图片放进对应的文件夹中

file_path = "D://cowboyoutfits//images//"
# print(os.path.join(file_path,'train'))
os.makedirs(os.path.join(file_path,'train'),exist_ok= True) # 在路径下创建文件夹
os.makedirs(os.path.join(file_path,'val'),exist_ok= True)

# current_path = os.getcwd()
# print("当前路径是:", current_path)

train_img = []
for j in data['images']:
    for i in train_id:
        if j['id'] == i:
            shutil.copy(file_path + j['file_name'],"D:\\cowboyoutfits\\images\\train") #两个参数,第一个是原来的文件,即目标文件,第二个参数是要复制到的文件夹 
            # 使用os.path.splitext获取文件名和后缀
            # file_name, file_extension = os.path.splitext(os.path.basename(file_path))
            # 扩展不要可以 file_name, _ = os.path.splitext(os.path.basename(file_path))
            # 扩展不要可以 file_name= os.path.splitext(file_path)[0])
            train_img.append(j)

val_img = []
for j in data['images']:
    for i in val_id:
        if j['id'] == i:
            shutil.copy(file_path + j['file_name'],"D:\\cowboyoutfits\\images\\val")
            val_img.append(j)

print(len(val_img),len(train_img))

第十步,将annotation放到对应的文件夹下,并将json2txt

os.makedirs(os.path.join(file_path,'labels','train'), exist_ok=True)
os.makedirs(os.path.join(file_path,'labels','val'), exist_ok=True)

train_info = [(each['id'], each['file_name'].split('.')[0], each['width'], each['height']) for each in train_img]
val_info = [(each['id'], each['file_name'].split('.')[0], each['width'], each['height']) for each in val_img]

trans = {f'{each}':f'{idx}' for (idx,each) in enumerate(ci)} # 转化为字典,type(trans)--dict

# trans = dict(zip(ci,range(len(ci)))) #不一样,没引号


# Create *.txt files for training
for (imid,fn,w,h) in train_info:
    with open ('D:\\cowboyoutfits\\images\\labels\\train\\' + fn + '.txt', 'w') as t_f:
        for t_ann in train_ann:
            if t_ann['image_id'] == imid:
                bbox = [str((t_ann['bbox'][0] + (t_ann['bbox'][2] / 2) - 1) / float(w)) + ' ', 
                        # 计算 x 中心坐标,并进行归一化。
                        str((t_ann['bbox'][1] + (t_ann['bbox'][3] / 2) - 1 )/ float(h)) + ' ',
                        str(t_ann['bbox'][2] / float(w)) + ' ',  # 计算宽度,并进行归一化。
                        str(t_ann['bbox'][3] / float(h))]
                print(bbox)
                t_f.write(trans[str(t_ann['category_id'])] + ' ' + str(bbox[0] + bbox[1] + bbox[2] + bbox[3]))
                t_f.write('\n')

# Create *.txt files for evaluating
for (imid, fn, w, h) in val_info:
    with open('D:\\cowboyoutfits\\images\\labels\\val\\' + fn + '.txt', 'w') as v_f:
        for v_ann in val_ann:
            if v_ann['image_id'] == imid:
                bbox = [str((v_ann['bbox'][0] + (v_ann['bbox'][2] / 2) - 1) / float(w)) + ' ',
                        str((v_ann['bbox'][1] + (v_ann['bbox'][3] / 2) - 1) / float(h)) + ' ',
                        str(v_ann['bbox'][2] / float(w)) + ' ',
                        str(v_ann['bbox'][3] / float(h))]
                v_f.write(trans[str(v_ann['category_id'])] + ' ' + str(bbox[0] + bbox[1] + bbox[2] + bbox[3]))
                v_f.write('\n')

 第十一步,设定一些参数,数据集放置的路径等生成yaml文件

data_yaml = dict(
    path = 'D:/cowboyoutfits', # dataset toot dir
    train = 'images/train', # train images('relative to 'path')
    val = 'images/val', # val images (relative to 'path')
    test = 'images/test', # test images (relation to 'path')
    nc = 5,
    names = ['belt', 'sunglasses', 'boot', 'coeboy_hot', 'jacket'],
    download = 'None'  
    )
with open('D:/cowboyoutfits/my_data_config.yaml', 'w') as f:
    yaml.dump(data_yaml, f, default_flow_style=False)

hyp_yaml = dict(
    lr0 = 0.01, # initial learning rate (SGD=1E-2,Adam=1E-3)
    lrf = 0.16, # final OneCycleLR learning rate (lr0 * lrf)
    momentum = 0.937, # SGD momentum/Adam beta1
    weight_decay = 0.0005, # optimizer weight decay 5e-4
    warmup_epoch = 5.0, # warmup epochs(fractions ok)
    warmup_momentum = 0.8, # warmup initial momentum
    warmup_bias_ls = 0.1, # warmup initial bias lr  
    box = 0.05, # box loss gain 
    cls = 0.3, # cls loss gain
    cls_pw = 1.0, # cls BECloss positive_weight
    obj = 0.7, #obj loss gain (scale with pixels)
    obj_pw = 1.0, # obj BCELoss positive_weight
    iou_t = 0.20, #IoU training threshold
    anchor_t =  4.0, # anchor-multiple thredshold
    fl_gamma = 0.0, # focal loss gamma (efficientDet default gamma= 1.5)
    hsv_h = 0.015, # images HSV-Hue augmentation (fraction)
    hsv_s = 0.7, # images HSV-Saturation augmentation (fraction)
    hsv_v = 0.4, # images HSV-Value augmentation (fraction)
    degrees = 0.0, #images rotatio(+/- deg)
    translate = 0.1, # images translation (+/- fraction)
    scale = 0.25, # image scale(+/- gain)
    shear = 0.0, # image shear(+/- deg)
    perspective = 0.0, # image perspective (+/- fraction), range 0-0.001
    flipup = 0.0, # image flip up-down(probability)
    fliplr = 0.5, # image flip left-right(probability)
    mosaic = 1.0, # image mosaic(probability)
    mixup = 0.0, # image mixup (probability)
    copy_paste = 0.0, # segment copy-paste (probability)  
    )

with open('D:/cowboyoutfits/hyp_config.yaml','w') as f:
    yaml.dump(hyp_yaml, f, default_flow_style=False)

第十二步,调用yolov5的三个模型。有两个使用了transformer,transformer也可以多加层,只不过我电脑不太行,只能加这点。没在服务器上运,大家有条件的可以试试。

model1_yaml = dict(
    nc = 5,  # number of classes
    depth_multiple = 1.33,  # model depth multiple
    width_multiple = 1.25,  # layer channel multiple
    anchors = 3,  # 这里把默认的anchors配置改成了3以启用autoanchor, 获取针对自己训练时的img_size的更优质的anchor size
    
    # YOLOv5 backbone
    backbone =
      # [from, number, module, args]
      [[-1, 1, 'Focus', [64, 3]],  # 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, 9, 'C3', [256]],
       [-1, 1, 'Conv', [512, 3, 2]],  # 5-P4/16
       [-1, 9, 'C3', [512]],
       [-1, 1, 'Conv', [768, 3, 2]],  # 7-P5/32
       [-1, 3, 'C3', [768]],
       [-1, 1, 'Conv', [1024, 3, 2]],  # 9-P6/64
       [-1, 1, 'SPP', [1024, [3, 5, 7]]],
       [-1, 3, 'C3', [1024, 'False']],  # 11
      ],

    # YOLOv5 head
    head =
      [[-1, 1, 'Conv', [768, 1, 1]],
       [-1, 1, 'nn.Upsample', ['None', 2, 'nearest']],
       [[-1, 8], 1, 'Concat', [1]],  # cat backbone P5
       [-1, 3, 'C3', [768, 'False']],  # 15

       [-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']],  # 19

       [-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']],  # 23 (P3/8-small)

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

       [-1, 1, 'Conv', [512, 3, 2]],
       [[-1, 16], 1, 'Concat', [1]],  # cat head P5
       [-1, 3, 'C3', [768, 'False']],  # 29 (P5/32-large)

       [-1, 1, 'Conv', [768, 3, 2]],
       [[-1, 12], 1, 'Concat', [1]],  # cat head P6
       [-1, 3, 'C3', [1024, 'False']],  # 32 (P6/64-xlarge)

       [[23, 26, 29, 32], 1, 'Detect', ['nc', 'anchors']],  # Detect(P3, P4, P5, P6)
      ]
    )
with open('D:/cowboyoutfits/yolov5x6.yaml', 'w') as f:
    yaml.dump(model1_yaml, f, default_flow_style=True)

model2_yaml = dict(
    nc = 5,  # number of classes
    depth_multiple = 1.33,  # model depth multiple
    width_multiple = 1.25,  # layer channel multiple
    anchors = 3,  # 这里把默认的anchors配置改成了3以启用autoanchor, 获取针对自己训练时的img_size的更优质的anchor size
    
    # YOLOv5 backbone
    backbone =
      # [from, number, module, args]
      [[-1, 1, 'Focus', [64, 3]],  # 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, 9, 'C3', [256]],
       [-1, 1, 'Conv', [512, 3, 2]],  # 5-P4/16
       [-1, 9, 'C3', [512]],
       [-1, 1, 'Conv', [768, 3, 2]],  # 7-P5/32
       [-1, 3, 'C3', [768]],
       [-1, 1, 'Conv', [1024, 3, 2]],  # 9-P6/64
       [-1, 1, 'SPP', [1024, [3, 5, 7]]],
       [-1, 3, 'C3TR', [1024, 'False']],  # 11  <-------- C3TR() Transformer module
      ],

    # YOLOv5 head
    head =
      [[-1, 1, 'Conv', [768, 1, 1]],
       [-1, 1, 'nn.Upsample', ['None', 2, 'nearest']],
       [[-1, 8], 1, 'Concat', [1]],  # cat backbone P5
       [-1, 3, 'C3', [768, 'False']],  # 15

       [-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']],  # 19

       [-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']],  # 23 (P3/8-small)

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

       [-1, 1, 'Conv', [512, 3, 2]],
       [[-1, 16], 1, 'Concat', [1]],  # cat head P5
       [-1, 3, 'C3', [768, 'False']],  # 29 (P5/32-large)

       [-1, 1, 'Conv', [768, 3, 2]],
       [[-1, 12], 1, 'Concat', [1]],  # cat head P6
       [-1, 3, 'C3', [1024, 'False']],  # 32 (P6/64-xlarge)

       [[23, 26, 29, 32], 1, 'Detect', ['nc', 'anchors']],  # Detect(P3, P4, P5, P6)
      ]
    )
with open('D:/cowboyoutfits/yolov5x6-transformer.yaml', 'w') as f:
    yaml.dump(model2_yaml, f, default_flow_style=True)

model3_yaml = dict(
    nc = 5,  # number of classes
    depth_multiple = 1.0,  # model depth multiple
    width_multiple = 1.0,  # layer channel multiple
    anchors = 3,  # 这里把默认的anchors配置改成了3以启用autoanchor, 获取针对自己训练时的img_size的更优质的anchor size
    
    # YOLOv5 backbone
    backbone =
      # [from, number, module, args]
      [[-1, 1, 'Focus', [64, 3]],  # 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, 9, 'C3', [256]],
       [-1, 1, 'Conv', [512, 3, 2]],  # 5-P4/16
       [-1, 9, 'C3TR', [512]],  #   <-------- C3TR() Transformer module
       [-1, 1, 'Conv', [768, 3, 2]],  # 7-P5/32
       [-1, 3, 'C3', [768]],
       [-1, 1, 'Conv', [1024, 3, 2]],  # 9-P6/64
       [-1, 1, 'SPP', [1024, [3, 5, 7]]],
       [-1, 3, 'C3TR', [1024, 'False']],  # 11  <-------- C3TR() Transformer module
      ],

    # YOLOv5 head
    head =
      [[-1, 1, 'Conv', [768, 1, 1]],
       [-1, 1, 'nn.Upsample', ['None', 2, 'nearest']],
       [[-1, 8], 1, 'Concat', [1]],  # cat backbone P5
       [-1, 3, 'C3', [768, 'False']],  # 15

       [-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']],  # 19

       [-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']],  # 23 (P3/8-small)

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

       [-1, 1, 'Conv', [512, 3, 2]],
       [[-1, 16], 1, 'Concat', [1]],  # cat head P5
       [-1, 3, 'C3', [768, 'False']],  # 29 (P5/32-large)

       [-1, 1, 'Conv', [768, 3, 2]],
       [[-1, 12], 1, 'Concat', [1]],  # cat head P6
       [-1, 3, 'C3', [1024, 'False']],  # 32 (P6/64-xlarge)

       [[23, 26, 29, 32], 1, 'Detect', ['nc', 'anchors']],  # Detect(P3, P4, P5, P6)
      ],
    )
with open('D:/cowboyoutfits/yolov5l6-transformer.yaml', 'w') as f:
    yaml.dump(model3_yaml, f, default_flow_style=True)

print("successful")

所有的准备工作都完成了,就差 python trian.py啦,快去看看结果怎么样了

手敲代码300+行,觉得本文对您有帮助的话,不妨给我点个赞,如果还有哪里没看懂,可以在评论区讨论,欢迎大家踊跃发言

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

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

相关文章

PyTorch Tutorial

本文作为博客“Transformer - Attention is all you need 论文阅读”的补充内容&#xff0c;阅读的内容来自于 https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html#recommended-preparation 建议的准备流程。 Deep Learning with PyTorch: …

java实现局域网内视频投屏播放(五)视频搜索和投屏自动切换下一个

代码链接 这次对ui做了一些调整&#xff0c;整体分成了5个类别分别为 搜索设备播放任务已下载视频列表视频搜索下载任务列表 视频搜索 搜索 点击搜索后&#xff0c;会从执行所有VideoResolver实现类的search方法&#xff0c;将搜索到的结果汇总到一起&#xff0c;根据视频的…

Python爬虫---scrapy shell 调试

Scrapy shell是Scrapy提供的一个交互式shell工具&#xff0c;它可以帮助我们进行爬虫的开发和调试。可以使用它来测试xpath或css表达式&#xff0c;查看它们是如何工作的&#xff0c;以及它们从你试图抓取的网页中提取的数据。它允许你在编写spider时交互地测试表达式&#xff…

set -e的作用

今天看人家代码看到一个很有意思的命令 后面我搜索了一下&#xff0c;感觉还是很好用的 set -e 是一个调试用的好东西 比如test.sh echo "执行第一个命令" cd /aaa/bbb echo "执行第二个命令"结果如下 可以看到第二个命令是执行了&#xff0c;虽然我的第…

stm32学习笔记:DMA

每个DMA通道硬件触发源是不一样的&#xff0c;要使用某个外设的硬件触发源&#xff0c;就必须使用它连接的那个通道 12个独立可配置的通道&#xff1a;DMA1(7个通道)&#xff0c;DMA2(5个通道) 每个通道都支持软件触发和特定的硬件触发 C8T6 DMA资源&#xff1a;DMA1 &#xff…

陶瓷碗口缺口检测-图像形态学

图像形态学 对得到的灰度图像&#xff0c;需要进行二值化处理和区域填充。二值化涉及两个步骤&#xff0c;第一&#xff0c;对图像行图像分割&#xff0c;将图像分割成目标和和背景&#xff1b;第二&#xff0c;对分割后图像进行区域填充。本例中的背景为黑色&#xff0c;可以…

前端工程化相关

工具方法&#xff1a; 知道软件包名&#xff0c;拿到源码或者路径的方法 在浏览器输入以下内容&#xff0c;就可以找到你想要的。。。 unpkg.com/输入包名 一、模块化 ESM特性清单&#xff1a; 自动采取严格模式&#xff0c;忽略“use strict”每个ESM模块都是单独的私有作用…

x-cmd pkg | csvkit - csv 实用工具集

目录 介绍首次用户功能特点类似工具与竞品进一步阅读 介绍 csvkit 是一个用Python编写的工具包&#xff0c;用于处理CSV文件。该工具包提供了一组命令行工具&#xff0c;可用于转换、查询和分析CSV文件。csvkit的主要命令包括csvcut&#xff08;用于选择特定列&#xff09;、c…

又涨了:net的域名铁定涨价

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 又要涨价了&#xff0c;又要涨价了&#xff0c;又要涨价了!继.com域名涨价后&#xff0c;.net的域名也逐步涨价。最近一年来域名疯狂涨价&#xff0c;几个月内已经几乎翻番。 阿里云2月1日起上调.net英文域名价格…

allegro PCB设计心得笔记(二) PCB板框设计心得

Cadence Allegro软件设计PCB板框时&#xff0c;使用Add -> line&#xff0c;在Option选择Board Geometry/Outline&#xff0c;根据PCB需要输入对应坐标&#xff0c;设计好板框。 使用Z-Copy命令设计Route Keepin和Package Keepin时&#xff0c;需要先使用使用Shape -> Co…

仿真验证方法(3)——物理验证

目录 一、物理验证的分类 二、DRC 2.1 设计规则 2.2 规则示例 2.3 线宽违例 2.4 间距违例 2.5 交叠违例 三、金属覆盖图形密度检查 四、天线比率检查 4.1 起因 4.2 计算 4.3 改进 五、LVS检查 六、物理验证常用的EDA工具 七、总结 一、物理验证的分类 对于物理验…

哪里能找到好用的PPT模板?12个免费模板网站让你畅快办公!

你是否有过这样的经历&#xff0c;在准备重要会议或者演讲的时候&#xff0c;为找不到合适的PPT模板而困扰&#xff1f;或是在网上漫无目的地搜寻&#xff0c;结果收获的是设计平淡无奇的PPT模板&#xff1f; 如果你有同样的疑问&#xff0c;那么你来对地方了&#xff01;在这…

什么是有机搜索引擎优化以及如何入门

什么是有机搜索引擎优化&#xff1f; 有机搜索引擎优化&#xff0c;简称 SEO&#xff0c;是指从搜索引擎的无偿搜索结果中增加网站流量的做法。 未付费搜索结果是获得的列表&#xff0c;而不是付费的。 这样做的目的是让您的网页在与您业务相关的未付费搜索结果中排名靠前。…

高级路由技术案例

文章目录 案例项目一&#xff1a;1、静态ECMP和浮动静态路由配置实验2、浮动静态路由配置 案例项目二&#xff1a;使用filter-policy过滤路由案例项目三&#xff1a;IS-IS基本配置案例项目四&#xff1a;OSPF基本配置案例任务一&#xff1a;OSPF单区域配置案例任务二&#xff1…

蓝桥杯单片机进阶教程4——需要分配进程的模块

前言&#xff1a; 【蓝桥杯单片机保姆级教学】 https://www.bilibili.com/video/BV1h3411m7Aw/?p117&share_sourcecopy_web&vd_sourcec4fc67867c5218768e783d04475bc5a2 P117-118 比赛的时候也按照这个顺序来写 一、数码管显示 分析考题 &#xff08;1&#xff09;…

【LeetCode每日一题】2182. 构造限制重复的字符串

2024-1-13 文章目录 [2182. 构造限制重复的字符串](https://leetcode.cn/problems/construct-string-with-repeat-limit/)思路&#xff1a; 2182. 构造限制重复的字符串 思路&#xff1a; 按照字符出现次数从高到低的顺序进行重复&#xff0c;通过维护一个指针 j 来寻找下一个…

【python】进阶--->MySQL数据库(二)

一、sql语句(结构化查询语言) 要和数据库进行交互,需要使用到数据库认识的语言 : sql语句 是关系型数据库都需要遵循的规范。不同数据库都支持sql语句,但是都有特有内容。 二、sql语句分类 数据定义语言 : 用来定义数据库–数据库,表,列. 数据操作语言 : 对数据库表中的记录进…

Modbus协议学习第一篇之基础概念

什么是“协议” 大白话解释&#xff1a;协议是用来正确传递消息数据而设立的一种规则。传递消息的双方&#xff08;两台计算机&#xff09;在通信时遵循同一种协议&#xff0c;即可理解彼此传递的消息数据。 Modbus协议模型 Modbus协议模型较为简单&#xff0c;使用一种称为应用…

Colab 谷歌免费的云端Python编程环境初体验

最新在学习AIGC的过程中&#xff0c;发现很多教程&#xff0c;demo使用到了Colab这个谷歌工具。 Colab 是什么&#xff1f; Google Colab是一个强大且免费的云端Python编程环境&#xff0c;为学生、研究人员和开发者提供了一个便捷的平台来开展数据科学、机器学习和深度学习项…

力扣(leetcode)第500题键盘行(Python)

500.键盘行 题目链接&#xff1a;500.键盘行 给你一个字符串数组 words &#xff0c;只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。 美式键盘 中&#xff1a; 第一行由字符 “qwertyuiop” 组成。 第二行由字符 “asdfghjkl” 组成。 第三行由字…