训练阶段: 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