mirror of
				https://github.com/PaddlePaddle/PaddleOCR.git
				synced 2025-11-04 03:39:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			200 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Locality aware nms.
 | 
						|
This code is refered from: https://github.com/songdejia/EAST/blob/master/locality_aware_nms.py
 | 
						|
"""
 | 
						|
 | 
						|
import numpy as np
 | 
						|
from shapely.geometry import Polygon
 | 
						|
 | 
						|
 | 
						|
def intersection(g, p):
 | 
						|
    """
 | 
						|
    Intersection.
 | 
						|
    """
 | 
						|
    g = Polygon(g[:8].reshape((4, 2)))
 | 
						|
    p = Polygon(p[:8].reshape((4, 2)))
 | 
						|
    g = g.buffer(0)
 | 
						|
    p = p.buffer(0)
 | 
						|
    if not g.is_valid or not p.is_valid:
 | 
						|
        return 0
 | 
						|
    inter = Polygon(g).intersection(Polygon(p)).area
 | 
						|
    union = g.area + p.area - inter
 | 
						|
    if union == 0:
 | 
						|
        return 0
 | 
						|
    else:
 | 
						|
        return inter / union
 | 
						|
 | 
						|
 | 
						|
def intersection_iog(g, p):
 | 
						|
    """
 | 
						|
    Intersection_iog.
 | 
						|
    """
 | 
						|
    g = Polygon(g[:8].reshape((4, 2)))
 | 
						|
    p = Polygon(p[:8].reshape((4, 2)))
 | 
						|
    if not g.is_valid or not p.is_valid:
 | 
						|
        return 0
 | 
						|
    inter = Polygon(g).intersection(Polygon(p)).area
 | 
						|
    #union = g.area + p.area - inter
 | 
						|
    union = p.area
 | 
						|
    if union == 0:
 | 
						|
        print("p_area is very small")
 | 
						|
        return 0
 | 
						|
    else:
 | 
						|
        return inter / union
 | 
						|
 | 
						|
 | 
						|
def weighted_merge(g, p):
 | 
						|
    """
 | 
						|
    Weighted merge.
 | 
						|
    """
 | 
						|
    g[:8] = (g[8] * g[:8] + p[8] * p[:8]) / (g[8] + p[8])
 | 
						|
    g[8] = (g[8] + p[8])
 | 
						|
    return g
 | 
						|
 | 
						|
 | 
						|
def standard_nms(S, thres):
 | 
						|
    """
 | 
						|
    Standard nms.
 | 
						|
    """
 | 
						|
    order = np.argsort(S[:, 8])[::-1]
 | 
						|
    keep = []
 | 
						|
    while order.size > 0:
 | 
						|
        i = order[0]
 | 
						|
        keep.append(i)
 | 
						|
        ovr = np.array([intersection(S[i], S[t]) for t in order[1:]])
 | 
						|
 | 
						|
        inds = np.where(ovr <= thres)[0]
 | 
						|
        order = order[inds + 1]
 | 
						|
 | 
						|
    return S[keep]
 | 
						|
 | 
						|
 | 
						|
def standard_nms_inds(S, thres):
 | 
						|
    """
 | 
						|
    Standard nms, retun inds.
 | 
						|
    """
 | 
						|
    order = np.argsort(S[:, 8])[::-1]
 | 
						|
    keep = []
 | 
						|
    while order.size > 0:
 | 
						|
        i = order[0]
 | 
						|
        keep.append(i)
 | 
						|
        ovr = np.array([intersection(S[i], S[t]) for t in order[1:]])
 | 
						|
 | 
						|
        inds = np.where(ovr <= thres)[0]
 | 
						|
        order = order[inds + 1]
 | 
						|
 | 
						|
    return keep
 | 
						|
 | 
						|
 | 
						|
def nms(S, thres):
 | 
						|
    """
 | 
						|
    nms.
 | 
						|
    """
 | 
						|
    order = np.argsort(S[:, 8])[::-1]
 | 
						|
    keep = []
 | 
						|
    while order.size > 0:
 | 
						|
        i = order[0]
 | 
						|
        keep.append(i)
 | 
						|
        ovr = np.array([intersection(S[i], S[t]) for t in order[1:]])
 | 
						|
 | 
						|
        inds = np.where(ovr <= thres)[0]
 | 
						|
        order = order[inds + 1]
 | 
						|
 | 
						|
    return keep
 | 
						|
 | 
						|
 | 
						|
def soft_nms(boxes_in, Nt_thres=0.3, threshold=0.8, sigma=0.5, method=2):
 | 
						|
    """
 | 
						|
    soft_nms
 | 
						|
    :para boxes_in, N x 9 (coords + score)
 | 
						|
    :para threshould, eliminate cases min score(0.001)
 | 
						|
    :para Nt_thres, iou_threshi
 | 
						|
    :para sigma, gaussian weght
 | 
						|
    :method, linear or gaussian
 | 
						|
    """
 | 
						|
    boxes = boxes_in.copy()
 | 
						|
    N = boxes.shape[0]
 | 
						|
    if N is None or N < 1:
 | 
						|
        return np.array([])
 | 
						|
    pos, maxpos = 0, 0
 | 
						|
    weight = 0.0
 | 
						|
    inds = np.arange(N)
 | 
						|
    tbox, sbox = boxes[0].copy(), boxes[0].copy()
 | 
						|
    for i in range(N):
 | 
						|
        maxscore = boxes[i, 8]
 | 
						|
        maxpos = i
 | 
						|
        tbox = boxes[i].copy()
 | 
						|
        ti = inds[i]
 | 
						|
        pos = i + 1
 | 
						|
        #get max box
 | 
						|
        while pos < N:
 | 
						|
            if maxscore < boxes[pos, 8]:
 | 
						|
                maxscore = boxes[pos, 8]
 | 
						|
                maxpos = pos
 | 
						|
            pos = pos + 1
 | 
						|
        #add max box as a detection
 | 
						|
        boxes[i, :] = boxes[maxpos, :]
 | 
						|
        inds[i] = inds[maxpos]
 | 
						|
        #swap
 | 
						|
        boxes[maxpos, :] = tbox
 | 
						|
        inds[maxpos] = ti
 | 
						|
        tbox = boxes[i].copy()
 | 
						|
        pos = i + 1
 | 
						|
        #NMS iteration
 | 
						|
        while pos < N:
 | 
						|
            sbox = boxes[pos].copy()
 | 
						|
            ts_iou_val = intersection(tbox, sbox)
 | 
						|
            if ts_iou_val > 0:
 | 
						|
                if method == 1:
 | 
						|
                    if ts_iou_val > Nt_thres:
 | 
						|
                        weight = 1 - ts_iou_val
 | 
						|
                    else:
 | 
						|
                        weight = 1
 | 
						|
                elif method == 2:
 | 
						|
                    weight = np.exp(-1.0 * ts_iou_val**2 / sigma)
 | 
						|
                else:
 | 
						|
                    if ts_iou_val > Nt_thres:
 | 
						|
                        weight = 0
 | 
						|
                    else:
 | 
						|
                        weight = 1
 | 
						|
                boxes[pos, 8] = weight * boxes[pos, 8]
 | 
						|
                #if box score falls below thresold, discard the box by
 | 
						|
                #swaping last box update N
 | 
						|
                if boxes[pos, 8] < threshold:
 | 
						|
                    boxes[pos, :] = boxes[N - 1, :]
 | 
						|
                    inds[pos] = inds[N - 1]
 | 
						|
                    N = N - 1
 | 
						|
                    pos = pos - 1
 | 
						|
            pos = pos + 1
 | 
						|
 | 
						|
    return boxes[:N]
 | 
						|
 | 
						|
 | 
						|
def nms_locality(polys, thres=0.3):
 | 
						|
    """
 | 
						|
    locality aware nms of EAST
 | 
						|
    :param polys: a N*9 numpy array. first 8 coordinates, then prob
 | 
						|
    :return: boxes after nms
 | 
						|
    """
 | 
						|
    S = []
 | 
						|
    p = None
 | 
						|
    for g in polys:
 | 
						|
        if p is not None and intersection(g, p) > thres:
 | 
						|
            p = weighted_merge(g, p)
 | 
						|
        else:
 | 
						|
            if p is not None:
 | 
						|
                S.append(p)
 | 
						|
            p = g
 | 
						|
    if p is not None:
 | 
						|
        S.append(p)
 | 
						|
 | 
						|
    if len(S) == 0:
 | 
						|
        return np.array([])
 | 
						|
    return standard_nms(np.array(S), thres)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    # 343,350,448,135,474,143,369,359
 | 
						|
    print(
 | 
						|
        Polygon(np.array([[343, 350], [448, 135], [474, 143], [369, 359]]))
 | 
						|
        .area) |