史上最全AP、mAP详解与代码实现

news2024/11/20 12:19:27

文章目录

  • 前言
  • 一、mAP原理
    • 1、mAP概念
    • 2、准确率
    • 3、精确率
    • 4、召回率
    • 5、AP: Average Precision
  • 二、mAP0.5与mAP0.5:0.95
    • 1、mAP0.5
    • 2、mAP0.5:0.95
  • 三、mAP代码实现
    • 1、真实标签json文件格式
    • 2、模型预测标签json文件格式
    • 3、mAP代码实现
    • 4、mAP结果显示
  • 四、模型集成mAP代码
    • 1、模型main函数
    • 2、模型mAP计算代码


前言

我们在深度学习的论文经常看到实验对比指标mAP,比较mAP@0.5与mAP@0.5:0.95指标。然,又有很多博客并未完全说明清楚,特别说结合代码解释该指标。为此,本文章将梳理mAP指标,主要内容分为mAP原理解释,如何使用代码获得mAP指标,进一步探讨如何结合模型而获得mAP指标。


一、mAP原理

1、mAP概念

mAP,其中代表P(Precision)精确率。AP(Average precision)单类标签平均(各个召回率中最大精确率的平均数)的精确率,mAP(Mean Average Precision)所有类标签的平均精确率。

2、准确率

准确率=预测正确的样本数/所有样本数,即预测正确的样本比例(包括预测正确的正样本和预测正确的负样本,不过在目标检测领域,没有预测正确的负样本这一说法,所以目标检测里面没有用Accuracy的)。
在这里插入图片描述

3、精确率

精确率也称查准率,Precision针对的是某一类样本,如果没有说明类别,那么Precision是毫无意义的(有些地方不说明类别,直接说Precision,是因为二分类问题通常说的Precision都是正样本的Precision)。
在这里插入图片描述

4、召回率

Recall和Precision一样,脱离类别是没有意义的。说道Recall,一定指的是某个类别的Recall。Recall表示某一类样本,预测正确的与所有Ground Truth的比例。
Recall计算的时候,分母是Ground Truth中某一类样本的数量,而Precision计算的时候,是预测出来的某一类样本数。
在这里插入图片描述

5、AP: Average Precision

AP指单个类别平均精确度,而mAP是所有类别的平均精确度,AP是Precision-Recall Curve曲线下面的面积,以Recall为横轴,Precision为纵轴,就可以画出一条PR曲线,PR曲线下的面积就定义为AP,如下。
在这里插入图片描述
由于计算积分相对困难,因此引入插值法,计算AP公式如下:
在这里插入图片描述

在这里插入图片描述

计算面积:
在这里插入图片描述
计算方法如下:
在这里插入图片描述

二、mAP0.5与mAP0.5:0.95

1、mAP0.5

mAP@0.5: mean Average Precision(IoU=0.5)
即将IoU设为0.5时,计算每一类的所有图片的AP,然后所有类别求平均,即mAP。

2、mAP0.5:0.95

mAP@.5:.95(mAP@[.5:.95])
表示在不同IoU阈值(从0.5到0.95,步长0.05)(0.5、0.55、0.6、0.65、0.7、0.75、0.8、0.85、0.9、0.95)上的平均mAP。

三、mAP代码实现

实现mAP计算,我们需要有已知真实标签与模型预测标签,我将介绍2部分,第一部分如何使用有标记的真实数据产生coco json格式与如何使用模型预测结果产生预测json格式,第二部分如何使用代码计算map。

1、真实标签json文件格式

真实数据json格式实际是coco json 格式,我将以图方式说明。
整体json格式内容,包含images、type、annotations、categories,如下图:
在这里插入图片描述
images内容如下图:
在这里插入图片描述

annotations内容如下图:
在这里插入图片描述
categories格式为:
在这里插入图片描述

以上为真实数据转换为json的格式。

2、模型预测标签json文件格式

预测结果数据json为列表,列表保存为字典,一个字典记录一个目标,整体json格式如下图:
在这里插入图片描述

列表中字典内容如下图显示:
在这里插入图片描述
特别注意:image id 对应真实coco json图像的image-id,类别id也是对应真实coco json中的类别id。

3、mAP代码实现

我们调用pycocotool库中集成map方法,按照以上给出gt与pred的json格式,可实现map计算,其详细代码如下:

from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval

if __name__ == "__main__":
    cocoGt = COCO('coco_json_format.json')        #标注文件的路径及文件名,json文件形式
    cocoDt = cocoGt.loadRes('predect_format.json')  #自己的生成的结果的路径及文件名,json文件形式
    cocoEval = COCOeval(cocoGt, cocoDt, "bbox")
    cocoEval.evaluate()
    cocoEval.accumulate()
    cocoEval.summarize()

4、mAP结果显示

我使用gt与pred为相同信息,为此结果为1。
在这里插入图片描述

四、模型集成mAP代码

最后,我是将mAP代码集成多个检测模型,我也在这里大致介绍如何集成模型预测mAP。

1、模型main函数

以下代码展示,检测模型输出后如何集成Computer_map()函数计算mAP方法,我已在代码中有解释,其详情如下:

def computer_main(data_root, model):
    '''
    data_root:任何文件夹,但必须保证每个图片与对应xml必须放在同一个文件夹中
    model:模型,用于预测
    '''
    C = Computer_map()
    img_root_lst = C.get_img_root_lst(data_root)  # 获得图片绝对路径与图片产生image_id映射关系

    # 在self.coco_json中保存categories,便于产生coco_json和predetect_json
    categories = model.CLASSES  # 可以给txt路径读取,或直接给列表  #*********************得到classes,需要更改的地方***********##
    C.get_categories(categories)

    # 产生coco_json格式
    xml_root_lst = [name[:-3] + 'xml' for name in img_root_lst]
    for xml_root in xml_root_lst: C.xml2cocojson(xml_root)  # 产生coco json 并保存到self.coco_json中

    # 产生预测的json
    for img_path in img_root_lst:

        parse_result = predict(model, img_path)  ####**********************需要更改的地方***********************####


        result, classes = parse_result['result'], parse_result['classes']
        # restult 格式为列表[x1,y1,x2,y2,score,label],若无结果为空
        img_name = C.get_strfile(img_path)
        C.detect2json(result, img_name)
    C.computer_map()  # 计算map

2、模型mAP计算代码

以下代码为Computer_map()函数计算mAP方法,我已在代码中有解释,其详情如下:

class Computer_map():
    '''
    主代码样列
    def computer_main(data_root, model):#data_root:任何文件夹,但必须保证每个图片与对应xml必须放在同一个文件夹中,model:模型,用于预测
        C = Computer_map()
        img_root_lst = C.get_img_root_lst(data_root)  # 获得图片绝对路径与图片产生image_id映射关系

        # 在self.coco_json中保存categories,便于产生coco_json和predetect_json
        categories = model.CLASSES  # 可以给txt路径读取,或直接给列表  #*********************得到classes,需要更改的地方***********##
        C.get_categories(categories)

        # 产生coco_json格式
        xml_root_lst = [name[:-3] + 'xml' for name in img_root_lst]
        for xml_root in xml_root_lst: C.xml2cocojson(xml_root)  # 产生coco json 并保存到self.coco_json中

        # 产生预测的json
        for img_path in img_root_lst:

            parse_result = predict(model, img_path)  ####**********************需要更改的地方***********************####

            result, classes = parse_result['result'], parse_result['classes']
            # restult 格式为列表[x1,y1,x2,y2,score,label],若无结果为空
            img_name = C.get_strfile(img_path)
            C.detect2json(result, img_name)
        C.computer_map()  # 计算map

    '''

    def __init__(self):
        self.img_format = ['png', 'jpg', 'JPG', 'PNG', 'bmp', 'jpeg']
        self.coco_json = {'images': [], 'type': 'instances', 'annotations': [], 'categories': []}
        self.predetect_json = []  # 保存字典
        self.image_id = 10000000  # 图像的id,每增加一张图片便+1
        self.anation_id = 10000000
        self.imgname_map_id = {}  # 图片名字映射id

    def read_txt(self, file_path):
        with open(file_path, 'r') as f:
            content = f.read().splitlines()
        return content

    def get_categories(self, categories):
        '''
        categories:为字符串,指绝对路径;为列表,指类本身
        return:将categories存入coco json中
        '''
        if isinstance(categories, str):
            categories = self.read_txt(categories)
        elif isinstance(categories, list or tuple):
            categories = list(categories)

        category_json = [{"supercategory": cat, "id": i + 1, "name": cat} for i, cat in enumerate(categories)]
        self.coco_json['categories'] = category_json

    def computer_map(self, coco_json_path=None, predetect_json_path=None):
        from pycocotools.coco import COCO
        from pycocotools.cocoeval import COCOeval
        from collections import defaultdict
        import time
        import json
        from pycocotools import mask as maskUtils
        import numpy as np
        # 继承修改coco json文件
        class COCO_modify(COCO):
            def __init__(self, coco_json_data=None):
                """
                Constructor of Microsoft COCO helper class for reading and visualizing annotations.
                :param annotation_file (str): location of annotation file
                :param image_folder (str): location to the folder that hosts images.
                :return:
                """
                # load dataset
                self.dataset, self.anns, self.cats, self.imgs = dict(), dict(), dict(), dict()
                self.imgToAnns, self.catToImgs = defaultdict(list), defaultdict(list)
                if coco_json_data is not None:
                    print('loading annotations into memory...')
                    tic = time.time()
                    if isinstance(coco_json_data, str):
                        with open(coco_json_data, 'r') as f:
                            dataset = json.load(f)
                        assert type(dataset) == dict, 'annotation file format {} not supported'.format(type(dataset))
                        print('Done (t={:0.2f}s)'.format(time.time() - tic))
                    else:
                        dataset = coco_json_data
                    self.dataset = dataset
                    self.createIndex()

            def loadRes(self, predetect_json_data):
                import copy
                """
                Load result file and return a result api object.
                :param   resFile (str)     : file name of result file
                :return: res (obj)         : result api object
                """
                res = COCO_modify()
                res.dataset['images'] = [img for img in self.dataset['images']]

                print('Loading and preparing results...')
                tic = time.time()

                if isinstance(predetect_json_data, str):
                    with open(predetect_json_data, 'r') as f:
                        anns = json.load(f)

                    print('Done (t={:0.2f}s)'.format(time.time() - tic))
                else:
                    anns = predetect_json_data

                assert type(anns) == list, 'results in not an array of objects'
                annsImgIds = [ann['image_id'] for ann in anns]
                assert set(annsImgIds) == (set(annsImgIds) & set(self.getImgIds())), \
                    'Results do not correspond to current coco set'
                if 'caption' in anns[0]:
                    imgIds = set([img['id'] for img in res.dataset['images']]) & set([ann['image_id'] for ann in anns])
                    res.dataset['images'] = [img for img in res.dataset['images'] if img['id'] in imgIds]
                    for id, ann in enumerate(anns):
                        ann['id'] = id + 1
                elif 'bbox' in anns[0] and not anns[0]['bbox'] == []:
                    res.dataset['categories'] = copy.deepcopy(self.dataset['categories'])
                    for id, ann in enumerate(anns):
                        bb = ann['bbox']
                        x1, x2, y1, y2 = [bb[0], bb[0] + bb[2], bb[1], bb[1] + bb[3]]
                        if not 'segmentation' in ann:
                            ann['segmentation'] = [[x1, y1, x1, y2, x2, y2, x2, y1]]
                        ann['area'] = bb[2] * bb[3]
                        ann['id'] = id + 1
                        ann['iscrowd'] = 0
                elif 'segmentation' in anns[0]:
                    res.dataset['categories'] = copy.deepcopy(self.dataset['categories'])
                    for id, ann in enumerate(anns):
                        # now only support compressed RLE format as segmentation results
                        ann['area'] = maskUtils.area(ann['segmentation'])
                        if not 'bbox' in ann:
                            ann['bbox'] = maskUtils.toBbox(ann['segmentation'])
                        ann['id'] = id + 1
                        ann['iscrowd'] = 0
                elif 'keypoints' in anns[0]:
                    res.dataset['categories'] = copy.deepcopy(self.dataset['categories'])
                    for id, ann in enumerate(anns):
                        s = ann['keypoints']
                        x = s[0::3]
                        y = s[1::3]
                        x0, x1, y0, y1 = np.min(x), np.max(x), np.min(y), np.max(y)
                        ann['area'] = (x1 - x0) * (y1 - y0)
                        ann['id'] = id + 1
                        ann['bbox'] = [x0, y0, x1 - x0, y1 - y0]
                print('DONE (t={:0.2f}s)'.format(time.time() - tic))

                res.dataset['annotations'] = anns
                res.createIndex()
                return res

        coco_json_data = coco_json_path if coco_json_path is not None else self.coco_json
        cocoGt = COCO_modify(coco_json_data)  # 标注文件的路径及文件名,json文件形式
        predetect_json_data = predetect_json_path if predetect_json_path is not None else self.predetect_json
        cocoDt = cocoGt.loadRes(predetect_json_data)  # 自己的生成的结果的路径及文件名,json文件形式

        cocoEval = COCOeval(cocoGt, cocoDt, "bbox")
        cocoEval.evaluate()
        cocoEval.accumulate()
        cocoEval.summarize()

    def get_img_root_lst(self, root_data):
        import os
        img_root_lst = []
        for dir, file, names in os.walk(root_data):
            img_lst = [os.path.join(dir, name) for name in names if name[-3:] in self.img_format]
            img_root_lst = img_root_lst + img_lst
            for na in img_lst:  # 图片名字映射image_id
                self.image_id += 1
                self.imgname_map_id[self.get_strfile(na)] = self.image_id
        return img_root_lst  # 得到图片绝对路径

    def get_strfile(self, file_str, pos=-1):
        '''
        得到file_str / or \\ 的最后一个名称
        '''
        endstr_f_filestr = file_str.split('\\')[pos] if '\\' in file_str else file_str.split('/')[pos]
        return endstr_f_filestr

    def read_xml(self, xml_root):
        '''
        :param xml_root: .xml文件
        :return: dict('cat':['cat1',...],'bboxes':[[x1,y1,x2,y2],...],'whd':[w ,h,d])
        '''

        import xml.etree.ElementTree as ET
        import os

        dict_info = {'cat': [], 'bboxes': [], 'box_wh': [], 'whd': []}
        if os.path.splitext(xml_root)[-1] == '.xml':
            tree = ET.parse(xml_root)  # ET是一个xml文件解析库,ET.parse()打开xml文件。parse--"解析"
            root = tree.getroot()  # 获取根节点
            whd = root.find('size')
            whd = [int(whd.find('width').text), int(whd.find('height').text), int(whd.find('depth').text)]
            xml_filename = root.find('filename').text
            dict_info['whd'] = whd
            dict_info['xml_filename'] = xml_filename
            for obj in root.findall('object'):  # 找到根节点下所有“object”节点
                cat = str(obj.find('name').text)  # 找到object节点下name子节点的值(字符串)
                bbox = obj.find('bndbox')
                x1, y1, x2, y2 = [int(bbox.find('xmin').text),
                                  int(bbox.find('ymin').text),
                                  int(bbox.find('xmax').text),
                                  int(bbox.find('ymax').text)]
                b_w = x2 - x1 + 1
                b_h = y2 - y1 + 1

                dict_info['cat'].append(cat)
                dict_info['bboxes'].append([x1, y1, x2, y2])
                dict_info['box_wh'].append([b_w, b_h])

        else:
            print('[inexistence]:{} suffix is not xml '.format(xml_root))
        return dict_info

    def xml2cocojson(self, xml_root):
        '''
        处理1个xml,将其真实json保存到self.coco_json中
        '''
        assert len(self.coco_json['categories']) > 0, 'self.coco_json[categories] must exist v'
        categories = [cat_info['name'] for cat_info in  self.coco_json['categories']]
        xml_info = self.read_xml(xml_root)
        if len(xml_info['cat']) > 0:
            xml_filename = xml_info['xml_filename']
            xml_name = self.get_strfile(xml_root)
            img_name = xml_name[:-3] + xml_filename[-3:]
            # 转为coco json时候,若add_file为True则在coco json文件的file_name增加文件夹名称+图片名字

            image_id = self.imgname_map_id[img_name]
            w, h, d = xml_info['whd']
            # 构建json文件字典
            image_json = {'file_name': img_name, 'height': h, 'width': w, 'id': image_id}
            ann_json = []
            for i, category in enumerate(xml_info['cat']):
                # 表示有box存在,可以添加images信息

                category_id = categories.index(category) + 1  # 给出box对应标签索引为类
                self.anation_id = self.anation_id + 1
                xmin, ymin, xmax, ymax = xml_info['bboxes'][i]

                o_width, o_height = xml_info['box_wh'][i]

                if (xmax <= xmin) or (ymax <= ymin):
                    print('code:[{}] will be abandon due to  {} min of box w or h more than max '.format(category,
                                                                                                         xml_root))  # 打印错误的box
                else:
                    ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id': image_id,
                           'bbox': [xmin, ymin, o_width, o_height],
                           'category_id': category_id, 'id': self.anation_id, 'ignore': 0,
                           'segmentation': []}
                    ann_json.append(ann)

            if len(ann_json) > 0:  # 证明存在 annotation
                for ann in ann_json:  self.coco_json['annotations'].append(ann)
                self.coco_json['images'].append(image_json)

    def detect2json(self, predetect_result, img_name,score_thr=-1):
        '''
        predetect_result:为列表,每个列表中包含[x1, y1, x2, y2, score, label]
        img_name: 图片的名字
        '''
        if len(predetect_result) > 0:
            categories = [cat_info['name'] for cat_info in  self.coco_json['categories']]
            for result in predetect_result:
                x1, y1, x2, y2, score, label = result
                if score>score_thr:
                    w, h = int(x2 - x1), int(y2 - y1)
                    x1, y1 = int(x1), int(y1)
                    img_name_new = self.get_strfile(img_name)
                    image_id = self.imgname_map_id[img_name_new]
                    category_id = list(categories).index(label) + 1
                    detect_json = {
                        "area": w * h,
                        "iscrowd": 0,
                        "image_id": image_id,
                        "bbox": [
                            x1,
                            y1,
                            w,
                            h
                        ],
                        "category_id": category_id,
                        "id": image_id,
                        "ignore": 0,
                        "segmentation": [],
                        "score": score
                    }
                    self.predetect_json.append(detect_json)

    def write_json(self,out_dir):
        import os
        import json
        coco_json_path=os.path.join(out_dir,'coco_json_data.json')
        with open(coco_json_path, 'w') as f:
            json.dump(self.coco_json, f, indent=4)  # indent表示间隔长度
        predetect_json_path=os.path.join(out_dir,'predetect_json_data.json')
        with open(predetect_json_path, 'w') as f:
            json.dump(self.predetect_json, f, indent=4)  # indent表示间隔长度

原理参考博客点击这里

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

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

相关文章

项目:点餐系统3mysql知识回顾MySQL客户端

连接数据库 mysql -uroot -p 密码&#xff1a;空 一、第三方库&#xff1a;MySQL 数据库-存储并管理数据的仓库&#xff0c;是一个C/S架构 MySQL客户端通过sql来告诉MySQL服务器&#xff0c;自己需要做什么操作 1.sql语句 sql&#xff1a;structure query language结构化查询…

LeetCode 44题:通配符匹配

题目 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字符。* 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09;。 判定匹配成功的充要条件是&#xff1a;字符模式必须…

AI识别工人安全绳佩戴检测算法

AI识别工人安全绳佩戴检测算法通过yolov5智能图像识别算法对现场图像进行处理和分析&#xff0c;AI识别工人安全绳佩戴检测算法识别出工人是否佩戴安全绳&#xff0c;一旦发现工人未佩戴安全绳&#xff0c;AI识别工人安全绳佩戴检测算法将立即进行告警&#xff0c;并将事件记录…

SOLIDWORKS中多实体文件到装配体的转换技巧

我们在做机械等工程设计中&#xff0c;有时为了节省时间&#xff0c;需要把多实体的“零件”&#xff0c;直接转换为装配体&#xff0c;不再另外装配&#xff0c;这样能大大简化设计的操作时间&#xff0c;复杂程度。 在这里&#xff0c;我们首先要了解&#xff0c;SOLIDWORKS文…

2023常见前端面试题

以下是一些2023年秋招常见的前端面试题及其答案&#xff1a; 1. 请解释一下什么是前端开发&#xff1f; 前端开发是指使用HTML、CSS和JavaScript等技术来构建网页和用户界面的过程。前端开发人员负责将设计师提供的视觉设计转化为可交互的网页&#xff0c;并确保网页在不同设备…

【活体检测模型】活体检测思路推演

ref:https://arxiv.org/pdf/1611.05431.pdf https://github.com/miraclewkf/ResNeXt-PyTorch 用分类的思想做活体检测&#xff0c;要求准确的分出正负样本&#xff0c;否则&#xff0c;支付宝被别人用了&#xff0c;问题就很严重。 大部分的商用场景还是 摇摇头、张张口&#x…

Android——基本控件(下)(二十)

1. 树型组件&#xff1a;ExpandableListView 1.1 知识点 &#xff08;1&#xff09;掌握树型组件的定义&#xff1b; &#xff08;2&#xff09;可以使用事件对树操作进行监听。 2. 具体内容 既然这个组件可以完成列表的功能&#xff0c;肯定就需要一个可以操作的数据&…

Java集合sort排序报错UnsupportedOperationException处理

文章目录 报错场景排查解决UnmodifiableList类介绍 报错场景 我们使用的是PostgreSQL数据库&#xff0c;存储业务数据&#xff0c;业务代码使用的是Spring JPA我们做的是智慧交通信控平台&#xff0c;有个功能是查询展示区域的交通态势&#xff0c;需要按照不同维度排序展示区…

pngPacker与TexturePacker打包对比,手把手教你使用pngPacker

pngPacker与TexturePacker打包对比&#xff0c;手把手教你使用pngPacker打包出媲美texturepacker的效果 pngPacker是一款免费的图片打包工具&#xff0c;软件小巧易用&#xff0c;主流游戏图片格式&#xff0c;如 bmp,jpg,png 可以打包为 png 大图&#xff0c;采用命令行格,前一…

数字乡镇综合解决方案PPT

导读&#xff1a;原文《数字乡镇综合解决方案PPT》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 部分内容&#xff1a; 喜欢文章&#xff0c;您可以关注评论转发本…

网络编程 http 相关基础概念

文章目录 表单是什么http请求是什么http请求的结构和说明关于http方法 GET和POST区别http常见状态码http响应http 请求是无状态的含义html是什么 &#xff08;前端内容&#xff0c;了解即可&#xff09;html 常见标签 &#xff08;前端内容&#xff0c;了解即可&#xff09;关于…

哇塞不!赛博时代云上自动化辅导孩子学习。

背景 孩子天天上网看动画片&#xff0c;都幼儿园大班了还不会100以内的加减法&#xff0c;因为我平时还需要忙着工作不能天天陪着孩子。 这次我们整个活&#xff0c;让孩子每天心甘情愿的做100道题。而且电脑还要给孩子一些提醒&#xff0c;即使做错了也会不厌其烦的给孩子提示…

图像颜色空间转换

目录 1.图像颜色空间介绍 RGB 颜色空间 2.HSV 颜色空间 3.RGBA 颜色空间 2.图像数据类型间的互相转换convertTo() 3.不同颜色空间互相转换cvtColor() 4.Android JNI demo 1.图像颜色空间介绍 RGB 颜色空间 RGB 颜色空间是最常见的颜色表示方式之一&#xff0c;其中 R、…

【C++】—— 异常处理

前言&#xff1a; 本期&#xff0c;我将给大家讲解的是有关 异常处理 的相关知识&#xff01; 目录 &#xff08;一&#xff09;C语言传统的处理错误的方式 &#xff08;二&#xff09;C异常概念 &#xff08;三&#xff09;异常的使用 1、异常的抛出和捕获 1️⃣ 异常的…

Windows Qt 5.12.10下载与安装

Qt 入门实战教程&#xff08;目录&#xff09; C自学精简实践教程 目录(必读) 1 Qt5.12.10下载 qt-opensource-windows-x86-5.12.10.exe 官方离线安装包 Download Source Package Offline Installers | Qt 下载巨慢&#xff08;也可能很快&#xff09; 只能下载到最新的&…

C语言——类型转换

数据有不同的类型&#xff0c;不同类型数据之间进行混合运算时涉及到类型的转换问题。 转换的方法有两种&#xff1a; 自动转换(隐式转换)&#xff1a;遵循一定的规则&#xff0c;由编译系统自动完成强制类型转换&#xff1a;把表达式的运算结果强制转换成所需的数据类型 语法格…

自动化测试(三):接口自动化pytest测试框架

文章目录 1. 接口自动化的实现2. 知识要点及实践2.1 requests.post传递的参数本质2.2 pytest单元测试框架2.2.1 pytest框架简介2.2.2 pytest装饰器2.2.3 断言、allure测试报告2.2.4 接口关联、封装改进YAML动态传参&#xff08;热加载&#xff09; 2.3 pytest接口封装&#xff…

20 MySQL(下)

文章目录 视图视图是什么定义视图查看视图删除视图视图的作用 事务事务的使用 索引查询索引创建索引删除索引聚集索引和非聚集索引影响 账户管理&#xff08;了解非DBA&#xff09;授予权限 与 账户的相关操作 MySQL的主从配置 视图 视图是什么 通俗的讲&#xff0c;视图就是…

编绎和优化,脚本代码小米加步枪赶超英法美

编程达人&#xff1a;冰冻牡蛎 测试&#xff0c;总结》》 今有空&#xff0c;继续看了一下竹笋大师几天前提出的“使用for循环查找10亿内可被7整除的数的个数”的题目&#xff08;相关文件&#xff1a;群文件 10亿以内多少个数字可以整除7.7z &#xff09; 1. 论输出的exe大小…

Pytorch-以数字识别更好地入门深度学习

目录 一、数据介绍 二、下载数据 三、可视化数据 四、模型构建 五、模型训练 六、模型预测 一、数据介绍 MNIST数据集是深度学习入门的经典案例&#xff0c;因为它具有以下优点&#xff1a; 1. 数据量小&#xff0c;计算速度快。MNIST数据集包含60000个训练样本和1000…