文章目录

  • 引言
  • 1 混淆矩阵
  • 2 语义分割
    • PA:像素准确率
    • CPA:类别像素准确率
    • MPA:类别平均像素准确率
    • IoU:交并比
    • MIoU:平均交并比
  • 3 综合实例
    • 步骤一:输入真实、预测图片
    • 步骤二:求出混淆矩阵
    • 步骤三:评价指标计算
      • PA
      • CPA
      • MPA
      • IoU
      • MIoU
  • 4 测试代码
  • 参考

引言

语义分割是像素级别的分类,其常用评价指标:
像素准确率(Pixel Accuracy,PA)、
类别像素准确率(Class Pixel Accuray,CPA)、
类别平均像素准确率(Mean Pixel Accuracy,MPA)、
交并比(Intersection over Union,IoU)、
平均交并比(Mean Intersection over Union,MIoU),
其计算都是建立在混淆矩阵(Confusion Matrix)的基础上。因此,了解基本的混淆矩阵知识对理解上述5个常用评价指标是很有益处的!


1 混淆矩阵

Q: 什么是混淆矩阵?
A: 顾名思义,其就是一个矩阵,可理解为一张表格,但矩阵前加上“混淆”之后,很容易让人理解产生误差,即:“混淆矩阵真混淆(一脸懵逼)”。

下面是一句话解释混淆矩阵:
混淆矩阵就是统计分类模型的分类结果,即:统计归对类,归错类的样本的个数,然后把结果放在一个表里展示出来,这个表就是混淆矩阵。(参考链接)


初步理解混淆矩阵,当以二分类混淆矩阵作为入门,多分类混淆矩阵都是以二分类为基础作为延伸的!

Q: 什么是二分类?
A: 顾名思义,分类器(又叫:网络模型、学习器)对两个类别进行分类处理的问题,就叫二分类

对于二分类问题,将类别1称为正例(Positive)类别2称为反例(Negative),分类器预测正确记作真(True)预测错误记作(False),由这4个基本术语相互组合,构成混淆矩阵的4个基础元素,为:

  • TP(True Positive):真正例,模型预测为正例,实际是正例(模型预测为类别1,实际是类别1)
  • FP(False Positive):假正例,模型预测为正例,实际是反例 (模型预测为类别1,实际是类别2)
  • FN(False Negative):假反例,模型预测为反例,实际是正例 (模型预测为类别2,实际是类别1)
  • TN(True Negative):真反例,模型预测为反例,实际是反例 (模型预测为类别2,实际是类别2)

混淆矩阵示意图(参考:西瓜书 p30):


看到此处,可能对混淆矩阵有了初步了解,但大脑里依旧是:“混淆矩阵很混淆”的状态…
且慢,下面举个例子:

假如:宠物店有10只动物,其中6只狗,4只猫(真实值),现有一个模型将这10只动物进行分类,分类结果为(预测结果为):5只狗,5只猫(预测值),对分类结果画出对应混淆矩阵进行分析(狗:正例,类别1,猫:反例,类别2):(参考链接)

等等…见此表是不是依旧懵逼?(那就对了…)

分析混淆矩阵的3个要点:(参考链接)
①矩阵对角线上的数字,为当前类别预测正确的类别数目;非对角线数字,预测都是错误的!
如:对角线数字5,含义为:预测值为狗,实际是狗的预测数目,即:预测正确(同理:数字4);非对角线数字1,含义为:预测值为猫,实际是狗的预测数目,即:预测错误。

②矩阵每一行数字求和的值,其含义:真实值中,真实情况下属于该行对应类别的数目!
如:第一行,5+1=6,表示真实情况狗有6只.

③矩阵每一列数字求和的值,其含义:预测值中,预测为该列对应类别的数目!
如:第一列,5+0=5,表示模型预测为狗的数目有5只;第二列,1+4=5,表示模型预测为猫的数目有5只(预测有对有错,对4只,错1只)

现小小总结一下这3个小点:

口诀:对角全为对,横看是真实,竖看是预测
解释:混淆矩阵对角元素全是预测正确的,数字的值表示各类别预测正确的数目;横(行)的数字求和,表示某类别真实值的个数,竖(列)的数字求和,表示模型预测为该类别的个数!

此外:对列求和的理解挺“别扭”的,分享一下我的理解技巧:看列时,首先想到是以模型预测为出发点(既然是预测,肯定有对有错),其次是模型对该列对应类别的预测总数是多少,最后才判断预测的对与错,即:“列是预测,先定总数不管对错,后判正误”。
比如:第2列,模型对猫(类别2)预测了1+4=5只(此时,不看预测对与错),再分析,第2列第1行非对角线元素,预测错误(预测值是猫,实际是狗),第2列第2行为对角元素,预测正确(预测值是猫,实际是猫),即:在猫这个类上,预测了5次,对了4次,错了1次!

上面分析了一大堆,最终还是不够精炼,于是大佬们定义了几个公式:

  • 准确率(Accuracy),对应:语义分割的像素准确率 PA
    公式:Accuracy = (TP + TN) / (TP + TN + FP + FN)
    意义:对角线计算。预测结果中正确的占总预测值的比例(对角线元素值的和 / 总元素值的和)
  • 精准率(Precision),对应:语义分割的类别像素准确率 CPA
    公式:Precision = TP / (TP + FP) 或 TN / (TN + FN)
    意义:竖着计算。预测结果中,某类别预测正确的概率
  • 召回率(Recall),不对应语义分割常用指标
    公式:Recall = TP / (TP + FN) 或 TN / (TN + FP)
    意义:横着计算。真实值中,某类别被预测正确的概率

上述公式对应上述例子:

  • 准确率:Accuracy = ( 5 +4 ) / (5 +4 + 0 + 1) = 0.9
  • 精准率:
    • 类别1(狗):P1 = 5 / (5 + 0) = 1
    • 类别2(猫):P2 = 4 / (4 + 1) = 0.8
  • 召回率:
    • 类别1(狗):R1 = 5 / (5 + 1) = 0.83
    • 类别2(猫):R2 = 4 / (4 + 0) = 1

上面是由二分类引出的关于混淆矩阵及其相关公式的介绍,语义分割一般都是多分类的,但也有二分类,对于二分类的语义分割评价指标可参考上述介绍理解,对于多分类的语义分割评价指标,其是基于二分类的思想进行发展延展的,即:将混淆矩阵行、列扩宽(类别增多),进行计算。
二分类和多分类混淆矩阵相关公式的计算都遵循上述口诀:“对角都对,横看真实,竖看预测”,所以遵循此原则,就很容易理解二分类和多分类的语义分割指标。

列举一个多分类(三类别)泛化一下知识点,防止读者学习过拟合!

类别1为例,计算公式为:

  • 准确率:Accuracy = (a + e + i) / (a + b + c + d + e +f + g + h + i)
  • 精准率:P1 = a / (a + d + g)
  • 召回率:R1 = a / (a + b + c)

更多计算例子,见:
4.4.2分类模型评判指标(一) - 混淆矩阵(Confusion Matrix)

2 语义分割

先回顾一下上述的例子:
宠物店有10只动物,其中6只狗,4只猫(真实值),现有一个模型将这10只动物进行分类,分类结果为(预测结果为):5只狗,5只猫(预测值)

此例子中:
进行分类的基础是:动物,然后将动物区分为狗、猫

语义分割中:
进行分类的基础是:图片中的像素点,然后将像素预测为是什么类别

进行上述区分,目的是让大家知道:不管进行分类的是动物,还是图片像素点,其混淆矩阵的获取、评价指标公式的计算都是一样的!

下面开始正题:

一般论文中,对语义分割模型的评估指标有:

PA:像素准确率

  • 对应:准确率(Accuracy)
  • 含义:预测类别正确的像素数占总像素数的比例
  • 混淆矩阵计算:
    • 对角线元素之和 / 矩阵所有元素之和
    • PA = (TP + TN) / (TP + TN + FP + FN)

CPA:类别像素准确率

  • 对应:精准率(Precision)
  • 含义:在类别 i 的预测值中,真实属于 i 类的像素准确率,换言之:模型对类别 i 的预测值有很多,其中有对有错,预测对的值占预测总值的比例
  • 混淆矩阵计算:
    • 类1:P1 = TP / (TP + FP)
    • 类2:P2 = TN / (TN + FN)
    • 类3:…

MPA:类别平均像素准确率

  • 含义:分别计算每个类被正确分类像素数的比例,即:CPA,然后累加求平均
  • 混淆矩阵计算:
    • 每个类别像素准确率为:Pi(计算:对角线值 / 对应列的像素总数)
    • MPA = sum(Pi) / 类别数

IoU:交并比

  • 含义:模型对某一类别预测结果和真实值的交集与并集的比值
  • 混淆矩阵计算:
    • 以求二分类:正例(类别1)的IoU为例
    • 交集:TP,并集:TP、FP、FN求和
    • IoU = TP / (TP + FP + FN)

MIoU:平均交并比

  • 含义:模型对每一类预测的结果和真实值的交集与并集的比值,求和再平均的结果
  • 混淆矩阵计算:
    • 以求二分类的MIoU为例
    • MIoU = (IoU正例p + IoU反例n) / 2 = [ TP / (TP + FP + FN) + TN / (TN + FN + FP) ] / 2

那么问题来了,交集和并集是如何来的?

继续以二分类为例说明,求正例(类别1)的IoU:

如图所示,A代表真实值(ground truth),B代表预测样本(prediction),预测值和真实值的关系如下:

  • TP(True Positive):

    • 橙色,TP = A ∩ B
    • 预测正确,真正例,模型预测为正例,实际是正例(模型预测为类别1,实际是类别1)
  • FP(False Positive):
    • 黄色,FP = B - (A ∩ B)
    • 预测错误,假正例,模型预测为正例,实际是反例 (模型预测为类别1,实际是类别2)
  • FN(False Negative):
    • 红色,FN = A - (A ∩ B)
    • 预测错误,假反例,模型预测为反例,实际是正例 (模型预测为类别2,实际是类别1)
  • TN(True Negative):
    • 白色,TN = ~(A ∪ B)
    • 预测正确,真反例,模型预测为反例,实际是反例 (模型预测为类别2,实际是类别2)

因此,可知正例(类别1)的IoU为:
IoU = TP / (TP + FN + FP)

此处有个比较疑惑的点是:TN有什么用?
因为我们求的是正例(Positive)的IoU,即:只用与P有关的混淆矩阵相关元素:TP、FP、FN,TN是与P无关,所以对于求正例的IoU无用!

如何找与P有关的混淆矩阵元素
“画线法”

求正例的IoU,在真实情况和预测结果正例中各画一条线,线所过之处的元素则与正例有关!
同理,若求反例的IoU,则:

与求反例的IoU有关的元素有:TN FN FP,公式为:
IoU = TN / (TN + FP + FN)

此时是不是有种豁然开朗的感觉?
同理,将画线法延伸到多分类的情形,其余类别的计算公式也是如此得来!

对于IoU的理解,可延伸阅读一下:
语义分割的评价指标——IoU
语义分割代码阅读—评价指标mIoU的计算


3 综合实例

上述对语义分割中常用5个评价指标进行了简介,下面列举一个例子,按照评价指标计算的三个步骤进行讲解:

步骤一:输入真实、预测图片

当你跑完模型,得到网络预测结果图时,用标注图(ground truth)和预测图(pridiction)来得出网络的性能评估指标。语义分割评估指标代码大同小异,一般都是基于FCN源码的score.py中fast_hist()函数的思想来进行计算的。
下面假定输入图片大小为3*3,图片中的像素点表示其分类(即:0代表类别1,1代表类别2,2代表类别3),如图:左图a为标注图,右图b为预测图(参考链接)

左、右图进行对比可知,b中预测值有两个像素点分类错误,即:

b01,b20

步骤二:求出混淆矩阵

混淆矩阵由:fast_hist(a, b, n)函数求出,此函数也是评估指标相关代码的关键!

'''
FCN中score.py原版代码
参考链接:https://blog.csdn.net/qq_21368481/article/details/80424754功能:
产生n×n的混淆矩阵
参数a:标注图(转换为一行输入),即真实的标签
参数b:预测图(转换为一行输入),即预测的标签
参数n: 类别数
'''
def fast_hist(a, b, n):#k为掩膜(去除了255这些点(即标签图中的白色的轮廓),其中的a>=0是为了防止bincount()函数出错)k = (a >= 0) & (a < n) #bincount()函数用于统计数组内每个非负整数的个数#详见https://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.htmlreturn np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n) #核心代码
'''
fast_hist(a, b, n)函数的变形代码,都是为了求混淆矩阵
参考链接:https://blog.csdn.net/kkkkk0826/article/details/102962168
'''
def genConfusionMatrix(self, imgPredict, imgLabel):# remove classes from unlabeled pixels in gt image and predictmask = (imgLabel >= 0) & (imgLabel < self.numClass)label = self.numClass * imgLabel[mask] + imgPredict[mask]count = np.bincount(label, minlength=self.numClass**2)  # 核心代码confusionMatrix = count.reshape(self.numClass, self.numClass)return confusionMatrix

上述函数的功能就是基于标注图和预测图求出混淆矩阵,进而求取相关评估指标的值!

下面对求混淆矩阵的核心代码,进行引用讲解(此大佬写得太好了,链接:FCN源码解读之score.py)

核心代码np.bincount(n * a[k].astype(int) + b[k], minlength=n**2)
(np.bincount函数学习链接:numpy.bincount详解)

其作用是产生一行n * n个元素的向量,向量中的每个元素存储统计结果,假如该向量为d,则其中的d(i*n + j)表示预测结果为类别j,实际标签为类别i的所有像素点的数目。

将上述的a、b和n输入fast_hist(a, b, n),所产生的d为:d=(3,0,0,0,2,1,0,1,2),其中的d(1*3 + 1)=d(4)表示预测类别为1,实际标签也为1的所有像素点数目为2。

通过reshape(n, n)将向量d转换为3*3的矩阵,其结果如下表(该矩阵即为下表中的绿色部分):

其中绿色的3*3表格统计的含义,拿数字3所在的这一格为例,即预测标签中被预测为类别0的且其真实标签也为0的所有像素点数目之和。

下面继续引用大佬讲解,遵循:对角都对,横看真实,竖看预测 原则
表格分析注意小点:

①绿色表格中对角线元素上的数字即为该类别预测正确的像素点数目,非对角线元素都是预测错误的,拿最后一行的数字1为例,其含义即为有一个原本应属于类别2的像素点被错误地预测为类别1;

②绿色表格的每一行求和得到的数字的含义是真实标签中属于某一类别的所有像素点数目,拿第一行为例,3+0+0=3,即真实属于类别0的像素点一共3个;

③绿色表格的每一列求和得到的数字的含义是预测为某一类别的所有像素点数目,拿第二列为例,0+2+1=3,即预测为类别1的所有像素点共有3个。

步骤三:评价指标计算

根据混淆矩阵,则可进行评价指标计算了!
基于上述混淆矩阵,下面列举一下具体计算值!

PA

PA = 对角线元素之和 / 矩阵所有元素之和 = (3 + 2 + 2) / (3 + 2 + 2 + 0 + 0 + 0 + 0 + 1 + 1)= 0.78

CPA

Pi = 对角线值 / 对应列的像素总数
P类别1 = 3 / ( 3 + 0 + 0) = 1
P类别2 = 2 / ( 0 + 2 + 1) = 0.67
P类别3 = 2 / ( 0 + 1 + 2) = 0.67

MPA

MPA = sum(Pi) / 类别数 = ( P类别1 + P类别2 + P类别3 ) / 3 = 0.78

IoU

IoUi = 对角线值 / 与该值有关元素的求和 [画线法]
第一种求法:(混淆矩阵,以对角线值画横、竖线,将相关元素求和)
IoU类别1 = 3 / (3 + 0 + 0 + 0 + 0) = 1
IoU类别2 = 2 / (0 + 2 + 1 + 0 + 1) = 0.5
IoU类别3 = 2 / (0 + 1 + 2 + 0 + 1) = 0.5

第二种求法:(代码中用的求法:SAUB = SA + SB - SA∩B)(参考链接)
IoU类别1 = 3 / [(3 + 0 + 0 ) + ( 3 + 0 + 0) - 3] = 1
IoU类别2 = 2 / [(0 + 2 + 1 ) + (0 + 2 + 1) - 2] = 0.5
IoU类别3 = 2 / [(0 + 1 + 2 ) + (0 + 1 + 2) - 2] = 0.5

MIoU

MIoU = sum(IoUi) / 类别数 = (1 + 0.5 + 0.5) / 3 = 0.67

4 测试代码

参考:
【语义分割】评价指标总结及代码实现

"""
refer to https://github.com/jfzhang95/pytorch-deeplab-xception/blob/master/utils/metrics.py
"""
import numpy as np
__all__ = ['SegmentationMetric']"""
confusionMetric  # 注意:此处横着代表预测值,竖着代表真实值,与之前介绍的相反
P\L     P    N
P      TP    FP
N      FN    TN
"""
class SegmentationMetric(object):def __init__(self, numClass):self.numClass = numClassself.confusionMatrix = np.zeros((self.numClass,)*2)def pixelAccuracy(self):# return all class overall pixel accuracy#  PA = acc = (TP + TN) / (TP + TN + FP + TN)acc = np.diag(self.confusionMatrix).sum() /  self.confusionMatrix.sum()return accdef classPixelAccuracy(self):# return each category pixel accuracy(A more accurate way to call it precision)# acc = (TP) / TP + FPclassAcc = np.diag(self.confusionMatrix) / self.confusionMatrix.sum(axis=1)return classAcc # 返回的是一个列表值,如:[0.90, 0.80, 0.96],表示类别1 2 3各类别的预测准确率def meanPixelAccuracy(self):classAcc = self.classPixelAccuracy()meanAcc = np.nanmean(classAcc) # np.nanmean 求平均值,nan表示遇到Nan类型,其值取为0return meanAcc # 返回单个值,如:np.nanmean([0.90, 0.80, 0.96, nan, nan]) = (0.90 + 0.80 + 0.96) / 3 =  0.89def meanIntersectionOverUnion(self):# Intersection = TP Union = TP + FP + FN# IoU = TP / (TP + FP + FN)intersection = np.diag(self.confusionMatrix) # 取对角元素的值,返回列表union = np.sum(self.confusionMatrix, axis=1) + np.sum(self.confusionMatrix, axis=0) - np.diag(self.confusionMatrix) # axis = 1表示混淆矩阵行的值,返回列表; axis = 0表示取混淆矩阵列的值,返回列表 IoU = intersection / union  # 返回列表,其值为各个类别的IoUmIoU = np.nanmean(IoU) # 求各类别IoU的平均return mIoUdef genConfusionMatrix(self, imgPredict, imgLabel): # 同FCN中score.py的fast_hist()函数# remove classes from unlabeled pixels in gt image and predictmask = (imgLabel >= 0) & (imgLabel < self.numClass)label = self.numClass * imgLabel[mask] + imgPredict[mask]count = np.bincount(label, minlength=self.numClass**2)confusionMatrix = count.reshape(self.numClass, self.numClass)return confusionMatrixdef Frequency_Weighted_Intersection_over_Union(self):# FWIOU =     [(TP+FN)/(TP+FP+TN+FN)] *[TP / (TP + FP + FN)]freq = np.sum(self.confusion_matrix, axis=1) / np.sum(self.confusion_matrix)iu = np.diag(self.confusion_matrix) / (np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -np.diag(self.confusion_matrix))FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()return FWIoUdef addBatch(self, imgPredict, imgLabel):assert imgPredict.shape == imgLabel.shapeself.confusionMatrix += self.genConfusionMatrix(imgPredict, imgLabel)def reset(self):self.confusionMatrix = np.zeros((self.numClass, self.numClass))if __name__ == '__main__':imgPredict = np.array([0, 0, 1, 1, 2, 2]) # 可直接换成预测图片imgLabel = np.array([0, 0, 1, 1, 2, 2]) # 可直接换成标注图片metric = SegmentationMetric(3) # 3表示有3个分类,有几个分类就填几metric.addBatch(imgPredict, imgLabel)pa = metric.pixelAccuracy()cpa = metric.classPixelAccuracy()mpa = metric.meanPixelAccuracy()mIoU = metric.meanIntersectionOverUnion()print('pa is : %f' % pa)print('cpa is :') # 列表print(cpa)print('mpa is : %f' % mpa)print('mIoU is : %f' % mIoU)

相关函数详解,请参考链接:
【语义分割】评价指标代码函数:np.sum()、np.nansum()、np.nanmean()、np.diag()、np.bincount()

测评截图:
步骤一:输入预测和标记图片 (4个类别分类,图片大小:512*512)

imgPredict = pic_predict  # 预测图片
imgLabel =  pic_label # 标注图片

步骤二:获取混淆矩阵 (特别注意:此代码混淆矩阵,行为预测值,列为真实值,因此:CPA的计算需要翻转一下)

可计算上述值的和为:262144,即:图片512 * 512的值,表示模型共预测了512 * 512个像素点的类别
步骤三:评估指标计算

还可参考:
语义分割常用指标详解(附代码)

不知道我说清楚了吗?
欢迎点赞!
欢迎大家留言讨论!

参考

  1. 4.4.2分类模型评判指标(一) - 混淆矩阵(Confusion Matrix)
  2. FCN源码解读之score.py
  3. 模型评估之混淆矩阵(confusion_matrix)含义及Python代码实现
  4. 语义分割的评价指标——IoU
  5. 语义分割代码阅读—评价指标mIoU的计算
  6. 深度学习图像分割评测指标MIOU之python代码详解
  7. 语义分割常用指标详解(附代码)
  8. 【语义分割】评价指标总结及代码实现
  9. numpy.bincount详解
  10. 评估DeepLab-v2的分割结果:pixel accuracy、IoU

【语义分割】评价指标:PA、CPA、MPA、IoU、MIoU详细总结和代码实现(零基础从入门到精通系列!)相关推荐

  1. 憨批的语义分割重制版2——语义分割评价指标mIOU的计算

    憨批的语义分割重制版2--语义分割评价指标mIOU的计算 注意事项 学习前言 什么是mIOU mIOU的计算 1.计算混淆矩阵: 2.计算IOU: 3.计算mIOU: 计算miou 注意事项 这是针对 ...

  2. 语义分割评价指标mIOU

    mIOU定义 Mean Intersection over Union(MIoU,均交并比),为语义分割的标准度量.其计算两个集合的交集和并集之比,在语义分割问题中,这两个集合为真实值(ground ...

  3. 详解语义分割评价指标

    本文主要介绍语义分割的三大评价指标,分别是执行时间.内存占用以及准确度,本文着重介绍准确度. 一.执行时间 二.内存占用 三.准确度 假设一共有k+1类(包括k个目标类和1个背景类): 1.Pixel ...

  4. 语义分割 评价指标(global_acc, mean_acc, mean_iou)等numpy实现

    语义分割常见评价指标global_acc, mean_acc, mean_iou计算,个人学习记录,仅供参考. 一.理论计算 假设真实标签为: 预测标签为: 则手动列出混淆矩阵可得: 1.1 全局准确 ...

  5. MATLAB算法实战应用案例精讲-【人工智能】语义分割(最终篇)(附实战应用案例及代码实现)

    目录 前言 语义分割面临的问题及解决方法 几个高频面试题目 什么是图像中的语义信息?

  6. 【深度学习入门到精通系列】医疗影像分割

    文章目录 1 医学图像种类 2 图像存储格式 3 U-net 4 数据增强 5 3D-Unet 6 Densenet 7 FC-Densenet 8 病理切片 1 医学图像种类 MRI--核磁共振图 ...

  7. Tensorflow keras中实现语义分割多分类指标:IOU、MIOU

    在TF1.x版本中 miou指标可以使用tf.metrics.mean_iou 进行计算: tf.metrics.mean_iou(labels, predictions, num_classes) ...

  8. 目标检测语义分割:隧道裂缝裂痕检测实战,有数据+代码

    目录 项目简介: 最终效果: 项目代码展示: ​编辑 文件名称    文件说明

  9. 【深度学习入门到精通系列】Mean Iou

最新文章

  1. 安装 Python MySQL 驱动(mysql-connector-python、MySQL-python)
  2. 斜杠的意思是或还是和_开启你的斜杠人生
  3. 中国智能高清视频监控未来发展趋势
  4. php 字符串 替换 最后,php如何替换字符串中的最后一个字符
  5. network reactnative_从零学React Native之14 网络请求
  6. 联想y470上三代cpu_AMD三代线程撕裂者首测 单核不再是问题(二)
  7. 《C语言程序设计基础I》秋季学习总结
  8. js获取浏览器和设备相关width(屏幕的宽度)
  9. PAT甲题题解-1124. Raffle for Weibo Followers-模拟,水题
  10. java 性能测试文档模板_最好用的数据库文档生成工具
  11. 正弦波、方波、三角波的产生和两两之间相互转换
  12. 群论基础速成(2):子群,陪集,正规子群,商群
  13. find+sed考试题及生产实战解决案例分享(考试答案系列)
  14. 对“陶哲轩-来自特征值的特征向量”的理解
  15. VBox虚拟机安装Ubuntu
  16. 互联网公司常用架构模式梳理
  17. python实现雪花飘落的效果_简单说 JavaScript实现雪花飘落效果
  18. 全球与中国膏体涂抹器市场深度研究分析报告
  19. Fedora 安装 QQ2012
  20. 失败一时并不可怕,可怕的是不去总结和改正。

热门文章

  1. 在Activiti中如何使用自定义的组织架构
  2. cocos2d-x3.6 连连看随机地图实现
  3. 5-5图层的链接-新版本不常用
  4. JavaBean在jsp中的使用
  5. 访问控制权限和 ------java命名规范
  6. asp.net后台程序动态加载js或样式表
  7. 【Tensorflow深度学习】Tensorflow2.0GPU版极简安装
  8. ubuntu18下vnpy1.9.2的安装
  9. html页面锁屏,JavaScript网页锁屏效果源码实例
  10. 学会这个大屏神器,低代码开发高端可视化大屏不在话下