IoU学习

IOU

IoU全称Intersection over Union,交并比。

IoU是一种测量在特定数据集中检测相应物体准确度的一个标准。只要是在输出中得出一个预测范围(bounding boxes)的任务都可以用IoU来进行测量。

IoU算法是使用最广泛的算法,大部分的检测算法都是使用的这个算法。在目标识别中,我们的预测框与实际框的某种比值就是IoU。

IoU Loss的定义是先求出预测框和真实框之间的交集和并集之比,再求负对数,但是在实际使用中我们常常将IOU Loss写成1-IOU。如果两个框重合则交并比等于1,Loss为0说明重合度非常高。
I o U = ∣ A ∩ B ∣ ∣ A ∪ B ∣ IoU=\frac{\mid{A \cap B}\mid}{\mid{A \cup B}\mid} IoU=ABAB L I o U = 1 − ∣ A ∩ B ∣ ∣ A ∪ B ∣ L_{IoU}=1-\frac{\mid{A \cap B}\mid}{\mid{A \cup B}\mid} LIoU=1ABAB
IOU的优点:

  • IOU具有尺度不变性
  • 满足非负性
    IOU的缺点:
  • 如果两个框没有相交,根据定义,IoU=0,不能反映两者的距离大小(重合度)。同时因为loss=0,没有梯度回传,无法进行学习训练。
  • 当预测框和真实框的交并比相同,但是预测框所在位置不同,因为计算出来的损失一样,所以这样并不能判断哪种预测框更加准确
# box1和box2的坐标为左上和右下的坐标  
# IoU  
def IoU(box1, box2):  
    b1_x1, b1_y1, b1_x2, b1_y2 = box1  
    b2_x1, b2_y1, b2_x2, b2_y2 = box2  
  
    # 用于求∩集  
    # 左上角坐标选大的  
    xx1 = np.maximum(b1_x1, b2_x1)  
    yy1 = np.maximum(b1_y1, b2_y1)  
    # 右下角坐标选小的,但是右下角坐标比左下角大  
    xx2 = np.minimum(b1_x2, b2_x2)  
    yy2 = np.minimum(b1_y2, b2_y2)  
  
    w = np.maximum(0.0, xx2 - xx1)  
    h = np.maximum(0.0, yy2 - yy1)  
    # 交集的面积  
    inter = w * h  
    # 并集为A+B-交集  
    IoU = inter / ((b1_x2 - b1_x1) * (b1_y2 - b1_y1) + (b2_x2 - b2_x1) * (b2_y2 - b2_y1) - inter)  
    return IoU  
  
  
box1 = np.array([100, 100, 210, 210])  
box2 = np.array([150, 150, 230, 220])  
print(IoU(box1, box2)) #0.2553191489361702

GIOU

GIoU比IoU多了一个‘Generalized’,能在更广义的层面上计算IoU。当检测框和真实框没有出现重叠的时候IoU的loss都是一样的,因此GIoU就引入了最小封闭形状C(C可以把A,B包含在内),在不重叠情况下能让预测框尽可能朝着真实框前进,这样就可以解决检测框和真实框没有重叠的问题 。
G I O U = I O U − ∣ C − ( A ∪ B ∣ ) ∣ C ∣ GIOU=IOU-\frac{\mid{C-(A \cup B}\mid)}{\mid C\mid} GIOU=IOUCC(AB) G I O U = − 1 + ( A ∪ B C )    i f    I o U = 0 GIOU=-1+(\frac{A\cup B}{C}) ~~if~~IoU=0 GIOU=1+(CAB)  if  IoU=0IoU取值[0,1],但是GIoU有对称区间,取值范围(-1,1]。在在两者无交集且无限远的时候无限趋近于最小值-1,两者重合的时候取最大值1, 因此GIoU是一个非常好的距离度量指标。

GIoU不仅可以关注重叠区域,还可以关注其他非重合区域,能比较好的反映两个框在闭包区域中的相交情况。损失函数为

L G I o U = 1 − G I o U = 1 − I o U + ∣ C − ( A ∪ B ∣ ) ∣ C ∣ L_{GIoU}=1-GIoU=1-IoU+\frac{\mid{C-(A \cup B}\mid)}{\mid C\mid} LGIoU=1GIoU=1IoU+CC(AB)
GIou的缺点

  • 对每个预测框与真实框均要去计算最小外接矩形,计算及收敛速度受到限制
  • 在一个框包含另一个框的情况下,这时GIoU将会退化为IoU,不能反映出实际情况
# box1和box2的坐标为左上和右下的坐标  
# IoU  
def GIoU(box1, box2):  
    b1_x1, b1_y1, b1_x2, b1_y2 = box1  
    b2_x1, b2_y1, b2_x2, b2_y2 = box2  
  
    # 用于求∩集  
    # 左上角坐标选大的  
    xx1 = np.maximum(b1_x1, b2_x1)  
    yy1 = np.maximum(b1_y1, b2_y1)  
    # 右下角坐标选小的,但是右下角坐标比左下角大  
    xx2 = np.minimum(b1_x2, b2_x2)  
    yy2 = np.minimum(b1_y2, b2_y2)  
  
    inter_w = np.maximum(0.0, xx2 - xx1)  
    inter_h = np.maximum(0.0, yy2 - yy1)  
    # 交集的面积  
    inter = inter_h * inter_w  
    # 并集为A+B面积  
    union = (b1_x2 - b1_x1) * (b1_y2 - b1_y1) + (b2_x2 - b2_x1) * (b2_y2 - b2_y1) - inter  
  
    # 求闭包C  
    C_xx1 = np.minimum(b1_x1, b2_x1)  
    C_yy1 = np.minimum(b1_y1, b2_y1)  
    C_xx2 = np.maximum(b1_x2, b2_x2)  
    C_yy2 = np.maximum(b1_y2, b2_y2)  
    C_aera = (C_xx2 - C_xx1) * (C_yy2 - C_yy1)  
  
    iou = inter / union  
    giou = iou - abs((C_aera - union) / C_aera)  
    return giou  
  
  
box1 = np.array([100, 100, 210, 210])  
box2 = np.array([150, 150, 230, 220])  
print(GIoU(box1, box2))  # 0.15916530278232405

DIoU

DIoU考虑到GIoU的缺点,也是增加了C检测框,将真实框和预测框都包含了进来,但是DIoU计算的不是框之间的交并,而是计算的每个检测框(利用中心点)之间的欧氏距离。

DIoU要比GIou更加符合目标框回归的机制,将目标与anchor之间的距离,重叠率以及尺度都考虑进去,使得目标框回归变得更加稳定,不会像IoU和GIoU一样出现训练过程中发散等问题。

D I o U = I o U − ρ 2 ( A , B ) c 2 DIoU=IoU-\frac{\rho^2(A,B)}{c^2} DIoU=IoUc2ρ2(A,B)
其中 d = ρ ( A , B ) d=\rho(A,B) d=ρ(A,B)是A与B框中心坐标的欧式距离,c为包住它们的最小方框的对角线距离。

欧式距离也称欧几里得距离,是最常见的距离度量,衡量的是多维空间中两个点之间的绝对距离。在二维和三维空间中的欧式距离的就是两点之间的距离
二维 : d = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 二维: d=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2} 二维:d=(x1x2)2+(y1y2)2
三维 : d = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 + ( z 1 − z 2 ) 2 三维: d=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2} 三维:d=(x1x2)2+(y1y2)2+(z1z2)2
n 维: X : ( x 1 , y 1 , z 1 , n 1 , . . . . m 1 ) Y : ( x 2 , y 2 , z 2 , n 2 , . . . . . , m 2 ) d ( X , Y ) = ∑ i = 1 m ( X i − Y i ) 2 \begin{align} n维:X:(x_1,y_1,z_1,n_1,....m_1)\\ Y:(x_2,y_2,z_2,n_2,.....,m_2)\\ d(X,Y)=\sqrt{\sum_{i=1}^m(X_i-Y_i)^2} \end{align} n维:X:(x1,y1,z1,n1,....m1)Y:(x2,y2,z2,n2,.....,m2)d(X,Y)=i=1m(XiYi)2
最后, L D I O U L_{DIOU} LDIOU的公式为
L D I o U = 1 − D I o U = 1 − I o U + ρ 2 ( A , B ) c 2 L_{DIoU}=1-DIoU=1-IoU+\frac{\rho^2(A,B)}{c^2} LDIoU=1DIoU=1IoU+c2ρ2(A,B)

  
# box1和box2的坐标为左上和右下的坐标,box1为预测框 box2为真实框(gt)  
# IoU  
def DIoU(box1, box2):  
    b1_x1, b1_y1, b1_x2, b1_y2 = box1  
    b2_x1, b2_y1, b2_x2, b2_y2 = box2  
  
    # 用于求∩集  
    # 左上角坐标选大的  
    xx1 = np.maximum(b1_x1, b2_x1)  
    yy1 = np.maximum(b1_y1, b2_y1)  
    # 右下角坐标选小的,但是右下角坐标比左下角大  
    xx2 = np.minimum(b1_x2, b2_x2)  
    yy2 = np.minimum(b1_y2, b2_y2)  
  
    inter_w = np.maximum(0.0, xx2 - xx1)  
    inter_h = np.maximum(0.0, yy2 - yy1)  
    # 交集的面积  
    inter = inter_h * inter_w  
    # 并集为A+B面积  
    union = (b1_x2 - b1_x1) * (b1_y2 - b1_y1) + (b2_x2 - b2_x1) * (b2_y2 - b2_y1) - inter  
  
    # 求闭包C  
    C_xx1 = np.minimum(b1_x1, b2_x1)  
    C_yy1 = np.minimum(b1_y1, b2_y1)  
    C_xx2 = np.maximum(b1_x2, b2_x2)  
    C_yy2 = np.maximum(b1_y2, b2_y2)  
    # 闭包的对角线  
    C_distance = (C_xx2 - C_xx1) ** 2 + (C_yy2 - C_yy1) ** 2  
  
    # 求A B的Distance  
    center_b_x = (b1_x1 + b1_x2) / 2  
    center_b_y = (b1_y1 + b1_y2) / 2  
    center_gtb_x = (b2_x1 + b2_x2) / 2  
    center_gtb_y = (b2_y1 + b2_y2) / 2  
    center_d = (center_gtb_x - center_b_x) ** 2 + (center_gtb_y - center_b_y) ** 2  

  
    iou = inter / union  
    diou = iou - center_d / C_distance  
    return diou  
  
  
box1 = np.array([100, 100, 210, 210])  
box2 = np.array([150, 150, 230, 220])  
print(DIoU(box1, box2))  # 0.18742777513425327

DIoU的优点

  • DIoU的惩罚项是基于中心点的距离和对角线距离的比值,避免了像GIoU在两框距离较远时,产生较大的外包框,Loss值较大难以优化(因为它的惩罚项是A ∪ B比上最小外包框的面积)。所以DIoU Loss收敛速度会比GIoU Loss快。
  • 即使在一个框包含另一个框的情况下,c值不变,但d值也可以进行有效度量。
  • 与GIoU loss类似,DIoU loss在与目标框不重叠时,仍然可以为边界框提供移动方向。
  • DIoU loss可以直接最小化两个目标框的距离,而GIOU loss优化的是两个目标框之间的面积,因此比GIoU loss收敛快得多。
  • 对于包含两个框在水平方向和垂直方向上这种情况,DIoU损失可以使回归非常快,而GIoU损失几乎退化为IoU损失

一个好的目标框回归损失应该考虑三个重要的几何因素:重叠面积、中心点距离、长宽比。

DIoU的缺点
没有考虑长宽比

CIoU

DIoU的作者考虑到,在两个框中心点重合时,c与d的值都不变。所以此时需要引入框的宽高比
C I o U = I o U − ρ 2 ( A c t r , B c t r ) c 2 − α v CIoU=IoU-\frac{\rho^2{(A_{ctr},B_{ctr}})}{c^2}-\alpha v CIoU=IoUc2ρ2(Actr,Bctr)αv
α = v ( 1 − I o U ) + v \alpha=\frac{v}{(1-IoU)+v} α=(1IoU)+vv
v = 4 π 2 ( a r c t a n w g t h g t − a r c t a n w h ) 2 v=\frac{4}{\pi^2}(arctan{\frac{w^{gt}}{h^{gt}}-arctan{\frac w h}})^2 v=π24(arctanhgtwgtarctanhw)2
公式中,A,B代表两个框, A c t r , B c t r A_{ctr},B_{ctr} Actr,Bctr代表A和B的中心点,其中 α \alpha α是权重函数,v 用来度量宽高比的一致性。最终的CIoU的损失函数为
L C I o U = 1 − I o U ( A , B ) + ρ 2 ( A c t r , B c t r ) c 2 + α v L_{CIoU}=1-IoU(A,B)+\frac{\rho^2{(A_{ctr},B_{ctr}})}{c^2}+\alpha v LCIoU=1IoU(A,B)+c2ρ2(Actr,Bctr)+αv
所以CIOU的前两部分和DIOU是一致的(这里的LOSS就是1-CIOU)。唯一增加的部分是后面的av,这个就是对长宽比的考量。

# box1和box2的坐标为左上和右下的坐标,box1为预测框 box2为真实框(gt)  
# IoU  
def CIoU(box1, box2):  
    b1_x1, b1_y1, b1_x2, b1_y2 = box1  
    b2_x1, b2_y1, b2_x2, b2_y2 = box2  
  
    # 用于求∩集  
    # 左上角坐标选大的  
    xx1 = np.maximum(b1_x1, b2_x1)  
    yy1 = np.maximum(b1_y1, b2_y1)  
    # 右下角坐标选小的,但是右下角坐标比左下角大  
    xx2 = np.minimum(b1_x2, b2_x2)  
    yy2 = np.minimum(b1_y2, b2_y2)  
  
    inter_w = np.maximum(0.0, xx2 - xx1)  
    inter_h = np.maximum(0.0, yy2 - yy1)  
    # 交集的面积  
    inter = inter_h * inter_w  
    # 并集为A+B面积  
    union = (b1_x2 - b1_x1) * (b1_y2 - b1_y1) + (b2_x2 - b2_x1) * (b2_y2 - b2_y1) - inter  
    iou = inter / union  
  
    # 求闭包C  
    C_xx1 = np.minimum(b1_x1, b2_x1)  
    C_yy1 = np.minimum(b1_y1, b2_y1)  
    C_xx2 = np.maximum(b1_x2, b2_x2)  
    C_yy2 = np.maximum(b1_y2, b2_y2)  
    C_distance = (C_xx2 - C_xx1) ** 2 + (C_yy2 - C_yy1) ** 2  
  
    # 求A B的Distance  
    center_b_x = (b1_x1 + b1_x2) / 2  
    center_b_y = (b1_y1 + b1_y2) / 2  
    center_gtb_x = (b2_x1 + b2_x2) / 2  
    center_gtb_y = (b2_y1 + b2_y2) / 2  
    center_d = (center_gtb_x - center_b_x) ** 2 + (center_gtb_y - center_b_y) ** 2  

  
    # 长宽比,计算a和v  
    pred_w=b1_x2-b1_x1  
    pred_h=b1_y2-b1_y1  
    gt_w=b2_x2-b2_x1  
    gt_h=b2_y2-b2_y1  
    v=(4/(np.pi)**2)*(np.arctan(gt_w/gt_h)-np.arctan(pred_w/pred_h))**2  
    alpha=v/(1-iou+v)  
  
  
    ciou = iou - center_d / C_distance-alpha*v  
    return ciou  
  
  
box1 = np.array([100, 100, 210, 210])  
box2 = np.array([150, 150, 230, 220])  
print(CIoU(box1, box2))  # 0.18742345427133264

CIoU的缺点

  • 如果预测框和gt框的长宽比是相同的,那么长宽比的惩罚项恒为0,不合理
  • 观察CIoU中w, h相对于v的梯度,发现这两个梯度是一对相反数,也就是说,w和h不能同时增大或减小,这显然也不够合理的。

EIoU

EIOU 是在 CIOU 的惩罚项基础上将预测框和真实框的纵横比的影响因子拆开分别计算预测框和真实框的长和宽,来解决 CIOU 存在的问题。

EIoU包括三个部分:IoU损失、距离损失、高宽损失(重叠面积、中心点举例、高宽比)
高宽损失直接最小化了预测目标边界框和真实边界框的高度和宽度的差异,使其有更快的收敛速度和更好的定位结果
E I o U = I o U − ρ 2 ( b , b g t ) c 2 − ρ 2 ( w , w g t ) C w 2 − ρ 2 ( h , h g t ) C h 2 EIoU=IoU-\frac{\rho^2(b,b^{gt})}{c^2}-\frac{\rho^2(w,w^{gt})}{C_{w}^2}-\frac{\rho^2(h,h^{gt})}{C_{h}^2} EIoU=IoUc2ρ2(b,bgt)Cw2ρ2(w,wgt)Ch2ρ2(h,hgt)
损失函数为
E I o U = 1 − I o U + ρ 2 ( b , b g t ) c 2 + ρ 2 ( w , w g t ) C w 2 + ρ 2 ( h , h g t ) C h 2 EIoU=1-IoU+\frac{\rho^2(b,b^{gt})}{c^2}+\frac{\rho^2(w,w^{gt})}{C_{w}^2}+\frac{\rho^2(h,h^{gt})}{C_{h}^2} EIoU=1IoU+c2ρ2(b,bgt)+Cw2ρ2(w,wgt)+Ch2ρ2(h,hgt)
其中, ρ 2 ( b , b g t ) \rho^2(b,b^{gt}) ρ2(b,bgt)为预测框和真实框之间中心坐标的欧氏距离, c 2 c^2 c2为闭包C的对角线。 C w {C_{w}} Cw C h C_{h} Ch为闭包C的宽和高, ρ 2 ( w , w g t ) \rho^2(w,w^{gt}) ρ2(w,wgt) ρ 2 ( h , h g t ) \rho^2(h,h^{gt}) ρ2(h,hgt)分别为真实框宽、高-预测框的宽、高的平方。

# box1和box2的坐标为左上和右下的坐标,box1为预测框 box2为真实框(gt)  
def EIoU(box1, box2):  
    b1_x1, b1_y1, b1_x2, b1_y2 = box1  
    b2_x1, b2_y1, b2_x2, b2_y2 = box2  
  
    # 用于求∩集  
    # 左上角坐标选大的  
    xx1 = np.maximum(b1_x1, b2_x1)  
    yy1 = np.maximum(b1_y1, b2_y1)  
    # 右下角坐标选小的,但是右下角坐标比左下角大  
    xx2 = np.minimum(b1_x2, b2_x2)  
    yy2 = np.minimum(b1_y2, b2_y2)  
  
    inter_w = np.maximum(0.0, xx2 - xx1)  
    inter_h = np.maximum(0.0, yy2 - yy1)  
    # 交集的面积  
    inter = inter_h * inter_w  
    # 并集为A+B面积  
    union = (b1_x2 - b1_x1) * (b1_y2 - b1_y1) + (b2_x2 - b2_x1) * (b2_y2 - b2_y1) - inter  
    iou = inter / union  
  
    # 求闭包C  
    C_xx1 = np.minimum(b1_x1, b2_x1)  
    C_yy1 = np.minimum(b1_y1, b2_y1)  
    C_xx2 = np.maximum(b1_x2, b2_x2)  
    C_yy2 = np.maximum(b1_y2, b2_y2)  
    C_distance = (C_xx2 - C_xx1) ** 2 + (C_yy2 - C_yy1) ** 2  
  
    # 求A B的Distance  
    center_b_x = (b1_x1 + b1_x2) / 2  
    center_b_y = (b1_y1 + b1_y2) / 2  
    center_gtb_x = (b2_x1 + b2_x2) / 2  
    center_gtb_y = (b2_y1 + b2_y2) / 2  
    center_d = (center_gtb_x - center_b_x) ** 2 + (center_gtb_y - center_b_y) ** 2  
  
    # 长宽比,计算a和v  
    pred_w = b1_x2 - b1_x1  
    pred_h = b1_y2 - b1_y1  
    gt_w = b2_x2 - b2_x1  
    gt_h = b2_y2 - b2_y1  
    roh_w = (gt_w - pred_w) ** 2  
    roh_h = (gt_h - pred_h) ** 2  
    C_w = (C_xx2 - C_xx1) ** 2  
    C_h = (C_yy2 - C_yy1) ** 2  
  
    eiou = iou - center_d / C_distance - roh_w / C_w - roh_h / C_h  
    return eiou  
  
  
box1 = np.array([100, 100, 210, 210])  
box2 = np.array([150, 150, 230, 220])  
print(EIoU(box1, box2))  # 0.02306222615331968

统一实现

import numpy as np  
import torch  
import math  
  
  
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, EIoU=False, eps=1e-7):  
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4  
    # box2 = box2.T  
    # Get the coordinates of bounding boxes    if x1y1x2y2:  # x1, y1, x2, y2 = box1  
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]  
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]  
    else:  # transform from xywh to xyxy  
        b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2  
        b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2  
        b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2  
        b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2  
  
    # Intersection area  
    inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \  
            (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)  
  
    # Union Area  
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps  
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps  
    union = w1 * h1 + w2 * h2 - inter + eps  
  
    iou = inter / union  
    if GIoU or DIoU or CIoU or EIoU:  
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width  
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height  
        if CIoU or DIoU or EIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1  
            c2 = cw ** 2 + ch ** 2 + eps  # convex diagonal squared  
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +  
                    (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4  # center distance squared  
            if DIoU:  
                return iou - rho2 / c2  # DIoU  
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47  
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)  
                with torch.no_grad():  
                    alpha = v / (v - iou + (1 + eps))  
                return iou - (rho2 / c2 + v * alpha)  # CIoU  
            elif EIoU:  
                rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2  
                rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2  
                cw2 = cw ** 2 + eps  
                ch2 = ch ** 2 + eps  
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)  
        else:  # GIoU https://arxiv.org/pdf/1902.09630.pdf  
            c_area = cw * ch + eps  # convex area  
            return iou - (c_area - union) / c_area  # GIoU  
    else:  
        return iou  # IoU  
  
  
box1 = torch.tensor(np.array([100, 100, 210, 210]))  
box2 = torch.tensor(np.array([150, 150, 230, 220]))  
print(bbox_iou(box1, box2, EIoU=True))  # 0.02306222615331968

reference1
reference2

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值