目标检测 polygon(多边形) iou

训练阶段: batch polygon iou

主要用于模型训练阶段进行批量计算n个多边形和m个多边形之间的iou

import torch
import shapely.geometry
def polygon_inter_union_cpu(boxes1, boxes2):
    """
        Reference: https://github.com/ming71/yolov3-polygon/blob/master/utils/utils.py ;
        iou computation (polygon) with cpu;
        Boxes have shape nx8 and Anchors have mx8;
        Return intersection and union of boxes[i, :] and anchors[j, :] with shape of (n, m).
    """
    
    n, m = boxes1.shape[0], boxes2.shape[0]
    inter = torch.zeros(n, m)
    union = torch.zeros(n, m)
    for i in range(n):
        polygon1 = shapely.geometry.Polygon(boxes1[i, :]).convex_hull
        for j in range(m):
            polygon2 = shapely.geometry.Polygon(boxes2[j, :]).convex_hull
            if polygon1.intersects(polygon2):
                try:
                    inter[i, j] = polygon1.intersection(polygon2).area
                    union[i, j] = polygon1.union(polygon2).area
                except shapely.geos.TopologicalError:
                    print('shapely.geos.TopologicalError occured')
    print("iou=", inter/union)
    return inter, union

#--test code
poly0 = np.int32([[50,10], [100,10], [100,160], [50,160]])
poly1 = np.int32([[0,90], [80,10], [80,180], [30,200]])

polygon_inter_union_cpu(np.array([poly0]), np.array([poly1]))

离线部署 ploygon iou (python)

参考: https://stackoverflow.com/questions/17810681/intersection-area-of-2-polygons-in-opencv

import cv2
import numpy as np

def polygon_iou(poly0, poly1, debug=0):

    # 计算两个多边形角点围城的外接矩形的宽高。
    pts = np.vstack([poly0, poly1])
    # x, y, w, h = cv2.boundingRect(pts)
    minx, miny = np.min(pts,0)
    maxx, maxy = np.max(pts,0)
    w = (maxx-minx) + 20  #+20,增加背景区域,无实际意义。
    h = (maxy-miny) + 20
    
    canv0  = np.zeros((h,w),np.uint8)
    canv1  = np.zeros_like(canv0) 
    canvRes = np.zeros_like(canv0)

    cv2.fillConvexPoly(canv0,poly0, 255)
    cv2.fillConvexPoly(canv1,poly1, 255)
    canvRes = cv2.bitwise_and(canv0,canv1)
    poly0Area = cv2.countNonZero(canv0)
    poly1Area = cv2.countNonZero(canv1)
    intersection = cv2.countNonZero(canvRes)
    union = poly0Area + poly1Area - intersection
    print("inter=%.2f, union=%.2f, iou=%.2f"%(intersection, union, intersection/union))

    if debug:
        canv  = np.zeros((h,w),np.uint8)
        # -----------------debug show
        cv2.polylines(canv, [poly0], True, 255, 2)
        cv2.polylines(canv, [poly1], True, 255, 2)
        cv2.imshow("debug", canv)
        cv2.imshow("poly0_canv0", canv0)
        cv2.imshow("poly1_canv1", canv1)
        cv2.imshow("iou_canvRes", canvRes)
        cv2.waitKey()

#--------------test code
# 输入两个polygon
poly0 = np.int32([[50,10], [100,10], [100,160], [50,160]])
poly1 = np.int32([[0,90], [80,10], [80,180], [30,200]])
polygon_iou(poly0, poly1, debug=1)

# inter=4216.00, union=13541.00, iou=0.31

图一: poly0所在区域数值填充。 图二:poly1所在区域数值填充。图三:poly0 和poly1多边形。图四: poly0和poly1的交集区域数值填充。

离线部署 ploygon iou (c/c++)

上面python版本的c/c++实现。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

    
float polygonIou(const std::vector<cv::Point> &poly0, const std::vector<cv::Point> &poly1, int max_w, int max_h){
        
        cv::Mat canv0 = cv::Mat::zeros(max_h, max_w, CV_8UC1);
        cv::Mat canv1 = cv::Mat::zeros(max_h, max_w, CV_8UC1);
        cv::Mat canvRes;
        
        cv::fillConvexPoly(canv0, poly0, cv::Scalar(1));
        cv::fillConvexPoly(canv1, poly1, cv::Scalar(1));
        cv::bitwise_and(canv0, canv1, canvRes);

        int poly0Area = cv::countNonZero(canv0);
        int poly1Area = cv::countNonZero(canv1);
        int interArea = cv::countNonZero(canvRes);

        float _iou = (float)interArea/(float)(poly0Area + poly1Area - interArea);
        printf("poly0Area=%d,poly1Area=%d, iou=%.3f\n", poly0Area,poly1Area,_iou);
        return _iou;
}

int main(int argc, char** argv){

    std::vector<cv::Point> poly0 {{50,10}, {100,10}, {100,160}, {50,160}};
    std::vector<cv::Point> poly1 {{0,90},{80,10},{80,180},{30,200}};

    float iou = polygonIou(poly0, poly1, 300, 300);
    return 0;
}


# poly0Area=7701,poly1Area=10056, iou=0.311

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值