非极大值抑制(NMS)算法详解

NMS(non maximum suppression)即非极大值抑制,广泛应用于传统的特征提取和深度学习的目标检测算法中。
NMS原理是通过筛选出局部极大值得到最优解。
在2维边缘提取中体现在提取边缘轮廓后将一些梯度方向变化率较小的点筛选掉,避免造成干扰。
在三维关键点检测中也起到重要作用,筛选掉特征中非局部极值。
在目标检测方面,无论是One-stage的SSD系列算法、YOLO系列算法还是Two-stage的基于RCNN系列的算法,非极大值抑制都是其中必不可少的一个组件,可以将较小分数的输出框过滤掉,同样,在三维基于点云的目标检测模型中亦有使用。

在现有的基于anchor的目标检测算法中,都会产生数量巨大的候选矩形框,这些矩形框有很多是指向同一目标,因此就存在大量冗余的候选矩形框。非极大值抑制算法的目的正在于此,它可以消除多余的框,找到最佳的物体检测位置。
image

IoU(Intersection over Union) :定位精度评价公式。
相当于两个区域交叉的部分除以两个区域的并集部分得出的结果。
image
IoU各个取值时的情况展示,一般来说,这个 Score > 0.5 就可以被认为一个不错的结果了。
image

IOU计算:

image

如何计算IoU(交并比)
image

选取两个矩形框左顶角的横,纵坐标的最大值,x21,y21;选取两个矩形框右下边角的横纵坐标的最小值,x12,y12;

  • 交集面积计算:

\[{Area(A \cap B)} = |x12 - x21| * |y12 - y21| \]

  • 并集面积计算:

\[{Area(A \cup B)} = |x11 - x12| * |y11 - y12| + |x21 - x22| * |y21 - y22| - {Area(A \cap B)} \]

  • 计算IOU公式

\[IoU = \frac {Area(A \cap B)} {Area(A \cup B)} \]

算法流程如下:

  • 将所有框的得分排序,选中最高分及其对应的框
  • 遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值(常用的值为0.5左右),我们就将框删除。(为什么要删除,是因为超过设定阈值,认为两个框的里面的物体属于同一个类别,比如都属于狗这个类别。我们只需要留下一个类别的可能性框图即可。)
  • 从未处理的框中继续选一个得分最高的,重复上述过程。
    image
    image
    image

代码如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NMS function(Non-Maximum Suppression,  抑制不是极大值的元素)
        psedocode:
            1. choose the highest score element  a_1  in set B, add a_1 to the keep set C
            2. compute the IOU between the chosen element(such as a_1) and others elements in set B
            3. only keep the nums  at set B whose IOU value is less than thresholds (can be set as >=0.5), delete the nums similiar
                to a_1(the higher IOU it is , the more interseciton between a_1 and it will have)
            4. choose the highest score value a_2 left at set B  and add a_2 to set C
            5. repeat the 2-4 until  there is nothing in set B, while set C is the NMS value set

"""
import numpy as np

# boxes表示人脸框的xywh4点坐标+相关置信度
boxes = np.array([[100, 100, 210, 210, 0.72],
                  [250, 250, 420, 420, 0.8],
                  [220, 220, 320, 330, 0.92],
                  [230, 240, 325, 330, 0.81],
                  [220, 230, 315, 340, 0.9]])


def py_cpu_nms(dets, thresh):
    # dets:(m,5)  thresh:scaler

    x1 = dets[:, 0]  # [100. 250. 220. 230. 220.]
    y1 = dets[:, 1]  # [100. 250. 220. 240. 230.]
    x2 = dets[:, 2]  # [210. 420. 320. 325. 315.]
    y2 = dets[:, 3]  # [210. 420. 330. 330. 340.]

    areas = (y2 - y1 + 1) * (x2 - x1 + 1)
    scores = dets[:, 4]  # [0 1 3 4 2]
    keep = []
    # index表示按照scores从高到底的相关box的序列号
    index = scores.argsort()[::-1]  # [2 4 3 1 0]

    while index.size > 0:
        print("sorted index of boxes according to scores", index)
        # 选择得分最高的score直接加入keep列表中
        i = index[0]
        keep.append(i)
        # 计算score最高的box和其他box分别的相关交集坐标
        x11 = np.maximum(x1[i], x1[index[1:]])  # [220. 230. 250. 220.]  最高的被提走了,所以要从1开始取后 4位
        y11 = np.maximum(y1[i], y1[index[1:]])  # [230. 240. 250. 220.]
        x22 = np.minimum(x2[i], x2[index[1:]])  # [315. 320. 320. 210.]
        y22 = np.minimum(y2[i], y2[index[1:]])  # [330. 330. 330. 210.]

        print("x1 values by original order:", x1)
        print("x1 value by scores:", x1[index[:]])  #  [220. 220. 230. 250. 100.]
        print("x11 value means  replacing the less value compared" \
              " with the value by the largest score :", x11)
        # 计算交集面积
        w = np.maximum(0, x22 - x11 + 1)  # the weights of overlap
        h = np.maximum(0, y22 - y11 + 1)  # the height of overlap
        overlaps = w * h
        # 计算相关IOU值(交集面积/并集面积,表示边框重合程度,越大表示越相似,越该删除)
        # 重叠面积 /(面积1+面积2-重叠面积)
        ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
        # 只保留iou小于阈值的索引号,重复上步
        idx = np.where(ious <= thresh)[0]
        # 因为第一步index[0]已经被划走,所以需要原来的索引号需要多加一
        index = index[idx + 1]

    return keep


import matplotlib.pyplot as plt


def plot_bbox(ax, dets, c='b', title_name="title"):
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]

    ax.plot([x1, x2], [y1, y1], c)
    ax.plot([x1, x1], [y1, y2], c)
    ax.plot([x1, x2], [y2, y2], c)
    ax.plot([x2, x2], [y1, y2], c)
    ax.set_title(title_name)


if __name__ == '__main__':
    # 1.创建画板fig
    fig = plt.figure(figsize=(12, 6))

    # 参数解释,前两个参数 1,2 表示创建了一个一行两列的框 第三个参数表示当前所在的框
    ax1 = fig.add_subplot(1, 2, 1)
    ax2 = fig.add_subplot(1, 2, 2)

    plot_bbox(ax1, boxes, 'k', title_name="before nms")  # before nms

    keep = py_cpu_nms(boxes, thresh=0.7)

    plot_bbox(ax2, boxes[keep], 'r', title_name="after nms")  # after nms
    plt.show()

image

参考文献:
http://blog.csdn.net/weixin_42237113/article/details/105743296
http://blog.csdn.net/lz867422770/article/details/100019587

本文转载于网络 如有侵权请联系删除

相关文章

  • 好家伙,你管这破玩意叫“双指针”?

    1478·最接近target的值描述给出一个数组,在数组中找到两个数,使得它们的和最接近目标值但不超过目标值,返回它们的和。解题思路思考:如果数组是已按照升序排列的,那么这个题目是不是就很好做?那样的话,可以定义两个分别指向数组的第一个元素和最后一个元素的指针,将两个指针指向的元素和与目标值target进行比较,然后再根据比较的结果,决定移动那一个指针。但是由于题目没有告知数组是有序的,所以需要先对数组进行排序,然后再采用双指针的策略去做。注意点当数组长度小于2时,不存在满足要求的结果,直接返回-1;由于题目要求找到的两个数的和最接近目标值但不超过目标值,因此只需要考虑找到的两个数的和小于等于目标值即可,不需要考虑大于的情况。定义变量diff用于保存当target大于等于sum时,target-sum的值,并不断更新(取最小值),diff初始值设置为INT_MAX。补充说明注意点中的第3点中,diff不断更新取最小值的原因是题目要求在数组找到两个数的和最接近目标值但不超过目标值,diff=min(differ,target-sum)。举栗以nums=[-18,-4,-6,13,4,4,

  • PHP数据结构-二叉树的遍历及逻辑操作

    二叉树的遍历及逻辑操作上篇文章我们讲了许多理论方面的知识,虽说很枯燥,但那些都是我们今天学习的前提,一会看代码的时候你就会发现这些理论知识是多么地重要了。首先,我们还是要说明一下,我们学习的主要内容是二叉树,因为二叉树是最典型的一种树的应用,不管是考试还是面试,它都是必知必学的内容。首先,在学习树的操作之前,我们先要明白在树的操作中,最核心的就是“遍历”。为什么这么说呢?不同于栈和队列,树结构其实已经不是一维的了,它有分支,有不同的角度,更重要的是它有了层级的概念。一维空间的东西就是我们常见的“线”,它只有长度,没有高度,而这个长度就是它唯一的维度,栈和队列很明显都是一维的。而树就不同了,因为层级的概念,所以它有了“高度”,也就是说,它升级到了二维的概念。就像上一篇文章中介绍的那一堆名词中,就有“树的高度(深度)”的概念。能够遍历一颗树之后,我们就可以在遍历的基础上对这颗树的结点进行增、删、改等操作,这些基本的逻辑操作全都是建立在遍历的基础之上的,仔细回想一下栈和队列,其实它们的这些逻辑操作不也是从遍历入手吗?不管是出栈入栈还是出队入队,我们都是建立在一种固定的遍历规则之下的(FILO

  • Nginx高可用的配置-Keepalived

    Nginx高可用  为什么需要高可用配置 单个Nginx负载均衡整个系统,如果nginx挂了,那么整个系统都将瘫痪,这时我们就需要保证及时1个Nginx挂了,整个系统也是可用的。   这时我们就需要实现Nginx的高可用,nginx的高可用需要配合keepalived一起实现。准备工作1.两个nginx服务  部署两个Linux节点,ip分别为192.168.12.120和198.168.12.121,分别启动nginx 2.两个keepalived服务1).yum命令安装keepalivedyuminstall-ykeepalived复制2)安装之后,在etc里面生成目录keepalived,有文件keepalived.conf3.完成高可用的配置  修改/etc/keepalived/keepalivec.conf配置文件global_defs{ notification_email{ acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_fr

  • 从Redshift看弹性分析演进

    弹性能力,是云产品的核心能力之一,也是各大云厂商的竞争热点。AWS作为全球云厂商的领军企业,其发展方向具备一定的代表意义。下面就从其数据仓库产品-Redshift入手,分析其在弹性能力方面的演进过程,同时也谈谈自己对弹性问题的一些理解。1.弹性发展阶段产品弹性能力的发展,是有其一定的规律。一方面是企业在根据需求不断打磨,更好地满足客户方需求;一方面也是需要一个技术积累沉淀的过程。下面是我将弹性发展划分的几个阶段,需要说明的是,为了满足不同客户场景,不同阶段的产品是会长期共存的。 1).第一阶段:无弹性 第一个阶段,就是无弹性节点。这一时期,云厂商更多是提供标准品。但为了满足来自客户侧的不同需求,往往通过定义多个规格来完成。从数据分析场景来看,比较显著的需求差异就是对核心两类资源:计算、存储的需求差异。一类是提供快速的计算访问,一类是提供海量的数据存储。因此在产品定义阶段,就分拆成不同的规格。例如Redshift的售卖规格(来自官网资料)通过不同的硬件提供了差异化的服务,满足客户的不同需求。当然这种方式的弊端也很明显,标品不能很好地满足客户个性化需求。2).第二阶段:资源弹性 走到第二阶

  • 研究了3天,终于将 Shader 移植到 Cocos Creator 2.2.0 上了

    01预览扫光特效—Fluxay2 马赛克像素特效—Mosaic过渡效果—TransferShawn花了3天时间,研究了CocosCreator2.2.0的Effect语法,终于在1024节前夕,大概知道如何将2.1.3的Shader特效给移植过去,成功移植了上面几个Effect文件,下面我讲一下关键要点,相信你可以自行完成。02uniformblock在片元代码中定义uniform变量,除了sampler2D类型以外,必须将uniform变量放到uniformblock里面,代码如下: uniformPROPERTIES{ vec4color; floatfactor; floatwidth; floattime; }复制在WebGL2中新增了UniformBlock的写法,着色器与应用程序之间,或者着色器各阶段之间共享的变量可组织为变量块(UniformBlock)的形式,并且有时候必须采取这种形式。Shawn对具体细节也不清楚,还需要进一步学习。02vec3不可用有几个Shader有包含有vec3类型的uniform变量,始终报错,如下提示:没有办法,搞了好次几都不行,只有求助引

  • python输入与输出涨姿势

    知识回顾: 上一节主要学习了利用python写第一个程序,学会使用了print函数进行输出。本节知识主要开始介绍输出与输入的方法。本节知识视频教程 文字教程开始: 一、print输出函数我们使用print(具体要输出的值)X=5Print(X)我们如何进入到python的编辑与解释环境呢?只需要通过命令提示符,输出python即可,如下: Cmd->python二、数据类型python语言中有很多数据类型,我们今天先学习一种整型。整型:整数类型整数:正整数、零、负整数整型的英文:integer,简写intpython中的整型用int表示。三、输入函数是什么?我们可以使用input函数,使用的时候格式input(“提示文字”)input函数有一个返回值,这个返回值就是输入的值,返回值的类型为字符串类型。举例:X=input(“请输入X的值:”)当输入完成后,X就等于刚输入的值。**这里注意,Python语言中所有的符号都要使用英文输入法状态下的半角符号。四、文本类型,又称字符串类型什么是文本类型?被单引号包围的一串文本,就是文本类型。文本类型的特征,可以进行拼接,就像贪吃蛇一样。五

  • 未来五年SSD市场趋势看这篇就够了

    近日,知名市场情报公司TrendFocus分析师在Memblaze发布会上分享对未来五年数据中心SSD市场趋势的预测。TrendFocus表示,虽然未来很长时间内,传统机械硬盘仍然会是数据中心用户们在容量上的优先选择,但是企业级SSD在容量和出货量已经开始超过传统的高性能机械硬盘,而且随着SSD借口的转换和更高容量的出现,SSD出货量将会保持稳定;更加重要的是,在超大规模数据中心用户的推动下,NVMe/PCIe将推动性能存储的未来发展。以下是详细解读:根据TrendFocus的市场统计数据,近年来,SSD已经出货容量上已经完成了对高性能机械硬盘的超越。随着NAND产能逐步稳定,未来SSD的出货量一定会进一步提升。在企业级SSD方面,TrendFocus认为PIC-E接口的SSD未来五年增长将会最快,并且PCI-E接口的SSD平均容量增长也更快,而SATA接口的SSD虽然平均容量也会增长,但是未来市场占比将会逐步下滑。以Facebook、Amazon、Google、阿里巴巴、腾讯、百度为代表的超大型数据中心用户对于企业级SSD的影响是巨大的,TrendFocus认为这些超大型数据中心用户

  • K8S学习笔记之Kubernetes数据持久化方案

    在开始介绍k8s持久化存储前,我们有必要了解一下k8s的emptydir和hostpath、configmap以及secret的机制和用途。0x00EmptydirEmptyDir是一个空目录,他的生命周期和所属的Pod是完全一致的,EmptyDir主要作用可以在同一Pod内的不同容器之间共享工作过程中产生的文件。如果Pod配置了emptyDir类型Volume,Pod被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失。#catemptydir.yaml apiVersion:v1 kind:Pod metadata: name:busybox spec: containers: -name:busybox image:registry.fjhb.cn/busybox imagePullPolicy:IfNotPresent command: -sleep -"3600&q

  • [C#] 常用工具类——直接在浏览器输出数据

    ///<summary> ///<para> </para> /// 常用工具类——直接在浏览器输出数据 ///<para> -------------------------------------------------------------</para> ///<para> DumpDataTable:接在浏览器输出数据DataTable</para> ///<para> DumpListItemILIST:直接在浏览器输出数据ILIST<ListItem></para> ///<para> DumpDataTableILIST:直接在浏览器输出数据DataTableILIST</para> ///<para> DumpIntArrILIST:直接在浏览器输出数据整型数组ILIST<int[]></para> ///<para> DumpStrArrILIST:直接在浏览器输出数据字符串数组的ILIST<stri

  • python笔记1-用python解决小学生数学题

    前几天有人在群里给小编出了个数学题:假设你有无限数量的邮票,面值分别为6角,7角,8角,请问你最大的不可支付邮资是多少元?小编掰着手指头和脚趾头算了下,答案是:1.7元那么问题来了?为啥是1.7呢,于是小编用python解决了这个小学数学题。一、排列组合假设6、7、8角各有50张(50张够了),先计算出所有的可能组合二、排序、去重先对组合就行排序,从小到大的顺序,排队站好,这里用到sort()函数(要是你用冒泡排序,那你就out啦!)sort函数只是对list序列排序,并没有返回值排序完成后,接下来就是去掉重复的数据三、取出不能生成的数字不在上面组合里面的数字就是不能生成的数字了,于是我们可以先取出来。 取出来后的数据放到r队列里。从r队列取最后一个数据,就是答案啦。四、参考代码#coding:utf-8 a=6 b=7 c=8 t=50#票的张数 s=[]#排列组合全部放到这里 #生成的组合 foriinrange(t+1): s1=a*i s.append(s1) forjinrange(t+1): s2=a*i+b*j s.append(s2) forkinrange(t+1):

  • Java魔法堂:类加载机制入了个门

    一、前言                               当在CMD/SHELL中输入 $javaMain<CR><LF> 后,Main程序就开始运行了,但在运行之前总得先把Main.class及其所依赖的类加载到JVM中吧!本篇将记录这些日子对类加载机制的学习心得,以便日后查阅。若有纰漏请大家指正,谢谢!以下内容均基于JDK7和HotSpotVM。二、执行java的那刻                          大家都知道通过java命令来启动JVM和运行应用程序,但实际的流程又是如何的呢? 1.首先根据java后的运行模式配置项或<JAVA_HOME>/jre/lib/i386/jvm.cfg来决定是以client还是server模式运行JVM,然后加载<JAVA_HOME>/jre/bin/client或server/jvm.dll,并开始启动JVM; 2.在启动JVM的同时将加载BootstrapClassLoader(启动类加载器,使用C/C++编写,属于JVM的一部分); 3.通过BootstrapClas

  • OpenCV ——背景建模之CodeBook(2)

    1,CodeBook的来源  先考虑平均背景的建模方法。该方法是针对每一个像素,累积若干帧的像素值,然后计算平均值和方差,以此来建立背景模型,相当于模型的每一个像素含有两个特征值,这两个特征值只是单纯的统计量,没有记录该像素值的历史起伏,即没有考虑时间序列和噪声干扰,不具备鲁棒性,因此建模时不能有运动前景的部分,要求光线保持不变。  如果我们考虑到时间起伏序列建模,比如利用60帧图像建模,对于每一个像素点会产生60个像素值,分别给他们加上60个相关的权值,或者进一步统计不同像素值出现的频次或者距离,以此来排除噪声,这样能够模拟复杂的背景,但是会带来巨大的内存消耗。  如果我们对该像素值起伏的动态范围进行压缩,压缩的依据是像素值之间的大小距离,即当前观测值与历史的记录值对比,如果两个值接近,就归为一类,也就是隶属同一个码元(CodeWord),如果差别过大,就以当前观测值新建一个码元,因为背景的变化情况远小于前景,所以压缩之后我们就得到了只含有若个码元的一个编码本(CodeBook),这个编码本不仅能够模拟复杂背景,同时大大减少内存消耗。此外,对每个码元的更新频率进行监督,剔除那些频率低

  • mod35云掩膜产品用法

    在网上一直没找到一个明确说怎么用MOD35产品的,都是说去看用户手册,第一次看了过一段时间我又忘记怎么搞了,赶紧记下来。 而且现在才发现第一次自己搞的都弄错了。 简单的判断是否是云,只要读取mod35产品的cloudmask数据集,其中的第一个波段就可以。     第一次用直接判断像素值是否大于128,因为看到产品说明书里bit0的值代表是否determined,以为是1就说明确定是云了。 现在才发现这是错上加错,   首先第一个byte的8个bit数据,bit0代表的是最末尾的那个,而不是第一位,即他是决定是0还是1,而不是128还是256。是xxxxxxx0,不是0xxxxxxx。   第二个错误是,bit0代表的是算法对这个像元的判断是否确定,一般来说都是1,如果是0这个像元其他的值都没用了。那到底要看哪个呢,仔细再阅读了一遍      要读的是bit1和2,也就是上表里分的四种情况,显示的是一个判断准确率,可能是0,0.33,0.67,1这样分的。所以重点来了,读第一个波段的xxxxx00x,判断里面00代表的两位,是11就是最高等级

  • numpy中np.max和np.maximum

    1.np.max(a,axis=None,out=None,keepdims=False)   求序列的最值       最少接受一个参数      axis默认为axis=0即列向,如果axis=1即横向 ex: >> np.max([-2,-1, 0, 1, 2]) 2   2.np.maximum(X,Y,out=None)     X和Y逐位进行比较,选择最大值.     最少接受两个参数 ex: >> np.maximum([-3,-2, 0, 1, 2], 0) array([0, 0, 0, 1, 2])

  • 对文件名进行重新排序命名

    1、编写脚本:提取该文件夹内的文件名 (1)建立一个TXT文件,输入DIR*.*/B>LIST.TXT,保存为.bat文件后运行该文件便可提取文件名 (2)文件名分列:数据窗口——分列 2、vlookup函数的使用: (1)vlookup函数 说起vlookup函数,相信每个Excel的使用者对其至少略有耳闻,比起lookup、hlookup函数名气要大得多。因为vlookup函数符合我们的思维习惯,在日常查找中足够使用了。 vlookup函数有四个参数,函数公式=vlookup(查找依据,查找范围,查找值在查找范围的列数,精确匹配或模糊匹配)。https://baijiahao.baidu.com/s?id=1631797217160023564&wfr=spider&for=pc 注:查找范围的列数要在查找值的右侧,选定区域后按F4锁定该查找范围($符号的使用) (2)运用vlookup函数查找所要SCD号的正确序号 3、批处理ren命令(脚本处理) (1)数据名称转化:EXCEL中把分列出来的旧名称重新筛选整合成新名称,后变成——REN“旧名称”“新名称”—

  • mysql分布式事务XA语法

    XA事务简介 XA事务的基础是两阶段提交协议。需要有一个事务协调者来保证所有的事务参与者都完成了准备工作(第一阶段)。如果协调者收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。MySQL 在这个XA事务中扮演的是参与者的角色,而不是协调者(事务管理器)。 mysql 的XA事务分为内部XA和外部XA。外部XA可以参与到外部的分布式事务中,需要应用层介入作为协调者;内部XA事务用于同一实例下跨多引擎事务,由Binlog作为协调者,比如在一个存储引擎提交时,需要将提交信息写入二进制日志,这就是一个分布式内部XA事务,只不过二进制日志的参与者是MySQL本身。Mysql在XA事务中扮演的是一个参与者的角色,而不是协调者。   MySQLXA事务基本语法 XA{START|BEGIN}xid[JOIN|RESUME]  启动一个XA事务(xid必须是一个唯一值;[JOIN|RESUME] 字句不被支持)   XAENDxid[SUSPEND[FORMIGRATE]] 结束一个XA

  • 正则表达式

    1边界符  ^  开始符   $  结束符  []  单字符  ()  分组  -  区间a-zA-Z0-9 2转义符 \b  Break,打破,单词边界 \w word,单词字母数字组合 \d Digit,数字  \s  space空格  \t  Table制表符  \n Newline 换行  \r Return 回车 3计量符号 *  重复0次或更多次 +  重复1次或更多次 ?  重复0次或1次可有可无占位符  (n)  重复n次  (n,m) 重复n次到m次(至少重复n次最多重复m次)  (n,)  重复n次,没最多次限制 4逻辑符 |  逻辑或 =  逻辑等

  • 元组

    定义:使用小括号来表示(),元组中的数据可以是任意类型。复制 tu=(1,2,3) print(type(tu))复制 1:元组中只要一个元素,怎么定义?需要在括号中加一个逗号复制 tu2=(1,)复制 2:元组的操作方法 1)下标取值、切片 tu3=(11,22,33,44,55) #下标取值 print(tu3[2]) #切片 print(tu3[1:4])复制 2)index:根据元素查找对应的下标(如果找不到对应的元素,会报错)    count:查找某个元素在元组中出现的次数 tu4=(11,22,33,44,55,11,22,33,11,11,22) print(tu4.index(111)) print(tu4.count(22))复制  注意点: #元组没有添加数据的方法,也没有修改数据的方法,也没有删除数据的方法 #元组是不可变类型的数据:定义的之后内部的数据不可以修改 #字符串也是不可变类型的数据: #数值类型数据是不可变类型; #列表:是可变类型的数据 #数据内容发生变化,id不变的是可变类型数据,数据发

  • Hibernate的cache(转)

    Cache就是缓存,它往往是提高系统性能的最重要手段,对数据起到一个蓄水池和缓冲的作用。Cache对于大量依赖数据读取操作的系统而言尤其重要。在大并发量的情况下,如果每次程序都需要向数据库直接做查询操作,它们所带来的性能开销是显而易见的,频繁的网络舆,数据库磁盘的读写操作都会大大降低系统的性能。此时如果能让数据库在本地内存中保留一个镜像,下次访问的时候只需要从内存中直接获取,那么显然可以带来不小的性能提升。引入Cache机制的难点是如何保证内存中数据的有效性,否则脏数据的出现将会给系统带来难以预知的严重后果。虽然一个设计得很好的应用程序不用Cache也可以表现出让人接受的性能,但毫无疑问,一些对读取操作要求比较高的应用程序可以通过Cache获得更高的性能。对于应用程序,Cache通过内存或磁盘保存了数据库中的当前有关数据状态,它是一个存储在本地的数据备份。Cache位于数据库和应用程序之间,从数据库更新数据,并给程序提供数据。 Hibernate实现了良好的Cache机制,可以借助Hibernate内部的Cache迅速提高系统的数据读取性能。Hibernate中的Cache可分为两层:

  • Android Library的依赖方式及发布(转)

    还是那句老话,好记性不然烂笔头,在此整理AndroidStudio依赖相关以及如何发布项目到JCenter AndroidStudio添加依赖Module依赖module依赖是指在本地创建一个module,然后如下步骤,依赖此模块。   这样做的好处就是随时可以修改module。 上图可以看到,AndroidStudio(以下简称AS)提供了三种依赖方式。 本地依赖本地依赖是指,将jar或者aar直接拷贝到项目的libs文件夹下,然后对其进行依赖。 jar的依赖如图一,拷贝进libs目录后,AS才能识别到。aar的本地依赖官方没有提供解决方案,不过高手在民间。 在讲解本地aar依赖之前,先科普一下aar文件。 aar文件是基于jar文件之上开发的。因为有些AndroidLibrary需要植入一些安卓特有的文件,比如AndroidManifest.xml,资源文件,Assets或者JNI。这些文件在Jar中是没有的,因此诞生了aar文件。 aar文件和jar一样,只是普通的zip文件。不过具有不同的文件结构。jar文件以classes.jar的名字被嵌入到aar文件中。 aar

  • github小白入门上手

    参考博客: 入门设置:https://blog.csdn.net/nmjuzi/article/details/82184818 一、把github上的文件弄到本地:在bash里面:gitclonehttps://github.com/......然后就把这个项目克隆到本地了。     参考博客:https://www.cnblogs.com/jf-67/p/6415637.html   二、把本地的代码上传到github:在bash里面就gitremoteaddoriginhttps://github.com/zlxzlxzlx/Test.git(关联到github上的那个仓库)                         gitpulloriginmaster   &nbs

相关推荐

推荐阅读