Python框排序

按照上下左右顺序对一系列框进行排序。

from easydict import EasyDict

def bbox4pto2p(box4p):
    box2p = [
        min(box4p[0], box4p[2], box4p[4], box4p[6]),
        min(box4p[1], box4p[3], box4p[5], box4p[7]),
        max(box4p[0], box4p[2], box4p[4], box4p[6]),
        max(box4p[1], box4p[3], box4p[5], box4p[7]),
    ]
    return box2p


class CompareBoxes(object):
    def __init__(self, coord_key:str):
        self.coord_key = coord_key

    def _structuralize(self, box1, box2):
        if len(box1) == 8:
            box1 = bbox4pto2p(box1)
        if len(box2) == 8:
            box2 = bbox4pto2p(box2)
        b1 = EasyDict()
        b2 = EasyDict()
        b1.minx = min(box1[0], box1[2])
        b1.maxx = max(box1[0], box1[2])
        b1.miny = min(box1[1], box1[3])
        b1.maxy = max(box1[1], box1[3])
        b2.minx = min(box2[0], box2[2])
        b2.maxx = max(box2[0], box2[2])
        b2.miny = min(box2[1], box2[3])
        b2.maxy = max(box2[1], box2[3])
        return b1, b2
    
    @staticmethod
    def calc_x_type(a, b):
        x_type = 0
        if a.maxx < b.minx-1e-4: 
            x_type = 1 # left: a b
        elif a.minx > b.maxx+1e-4:
            x_type = 2  # right: b a
        elif a.minx < b.minx and a.maxx < b.maxx:
            x_type = 3  # near left
        elif a.minx > b.minx and a.maxx > b.maxx:
            x_type = 4  # near right
        elif a.minx < b.minx and a.maxx > b.maxx:
            x_type = 5  # contain
        elif a.minx > b.minx and a.maxx < b.maxx:
            x_type = 6  # inside
        else: x_type = 6
        return x_type

    @staticmethod
    def calc_y_type(a, b):
        y_type = 0
        if a.maxy < b.miny-1e-4:
            y_type = 1  # up
        elif a.miny > b.maxy+1e-4:
            y_type = 2  # down
        elif a.miny < b.miny and a.maxy < b.maxy:
            y_type = 3  # near up
        elif a.miny > b.miny and a.maxy > b.maxy:
            y_type = 4  # near down
        elif a.miny < b.miny and a.maxy > b.maxy:
            y_type = 5  # contain
        elif a.miny > b.miny and a.maxy < b.maxy:
            y_type = 6  # inside
        else: y_type = 6
        return y_type
    
    @staticmethod
    def bool2int(b):
        if b: return -1
        else: return 1
    
    def cmp_boxes(self, a, b):
        y_type = self.calc_y_type(a, b)
        x_type = self.calc_x_type(a, b)
        y_near_rate = 0.0
        x_near_rate = 0.0
        if y_type==3: y_near_rate = (a.maxy-b.miny) / min(a.maxy-a.miny, b.maxy-b.miny)
        elif y_type==4: y_near_rate = (b.maxy-a.miny) / min(a.maxy-a.miny, b.maxy-b.miny)
        if x_type==3: x_near_rate = (a.maxx-b.minx) / min(a.maxx-a.minx, b.maxx-b.minx)
        elif x_type==4: x_near_rate = (b.maxx-a.minx) / min(a.maxx-a.minx, b.maxx-b.minx)

        # fprintf(stderr, "%s vs %s, x_type %d, y_type %d\n", a.text.c_str(), b.text.c_str(), x_type, y_type)
        if y_type==1: res = True
        elif y_type==2: res = False
        elif y_type==3:
            if x_type==1: res = True
            elif x_type==2: res = y_near_rate<0.5
            elif x_type==3: res = True
            elif x_type==4: res = y_near_rate<0.5
            else: res = True
        elif y_type==4:
            if x_type==1: res = y_near_rate>0.5
            elif x_type==2: res = False
            elif x_type==3: res = y_near_rate>0.5
            elif x_type==4: res = False
            else: res = False
        else:
            if x_type==1 or x_type==3: res = True
            elif x_type==2 or x_type==4: res = False
            else: res = (a.minx+a.maxx)<(b.minx+b.maxx)
        return self.bool2int(res)

    def __call__(self, seg1, seg2):
        """
        segi: {..., coord_key: [2 pts or 4 pts]}
        """
        a, b = self._structuralize(seg1[self.coord_key], seg2[self.coord_key])
        return self.cmp_boxes(a, b)


# Usage for example
from functools import cmp_to_key
cmp_box_fn = CompareBoxes(coord_key="box")
line_info = sorted(line_info, key=cmp_to_key(cmp_box_fn))

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值