├── data_aug.py ├── nms_cpp ├── polyiou.cpp ├── polyiou.h └── nms.h ├── README.md ├── nms.py ├── nms_mutiprocess.py ├── ImgSplit_multiprocess_HBB.py └── poly_to_rect.py /data_aug.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fan0210/detection_tools/HEAD/data_aug.py -------------------------------------------------------------------------------- /nms_cpp/polyiou.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fan0210/detection_tools/HEAD/nms_cpp/polyiou.cpp -------------------------------------------------------------------------------- /nms_cpp/polyiou.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dingjian on 18-2-3. 3 | // 4 | 5 | #ifndef POLYIOU_POLYIOU_H 6 | #define POLYIOU_POLYIOU_H 7 | 8 | #include 9 | double iou_poly(std::vector p, std::vector q); 10 | #endif //POLYIOU_POLYIOU_H -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # detection_tools 2 | Some Useful Tools for Object Detection in Remote Sensing Imagery. 一些遥感图像目标检测的实用代码及工具,不断更新中... 3 | 4 | ## Usage 5 | 6 | * [ImgSplit_multiprocess_HBB.py](https://github.com/fan0210/detection_tools/blob/master/ImgSplit_multiprocess_HBB.py) 7 | 8 | 对原始遥感图像训练数据进行裁切,生成固定大小的patches,适用于HBB(Horizontal Bounding Box)。 9 | 10 | * [data_aug.py](https://github.com/fan0210/detection_tools/blob/master/data_aug.py) 11 | 12 | 遥感图像目标检测数据扩充(在线增强),包括随机旋转、随机裁切、水平竖直翻转、随机线性增强、随机灰度化等,适用于OBB和HBB 13 | 14 | * [poly_to_rect.py](https://github.com/fan0210/detection_tools/blob/master/poly_to_rect.py) 15 | 16 | 代替cv2.minAreaRect,在DOTA上可提升~1AP 17 | 18 | * [nms_cpp](https://github.com/fan0210/detection_tools/blob/master/nms_cpp) 19 | 20 | 部署用的C++版nms,支持正矩形和任意四边形 21 | 22 | -------------------------------------------------------------------------------- /nms.py: -------------------------------------------------------------------------------- 1 | #Created by fankai 2020/6/16 21:11, https://github.com/fan0210/detection_tools 2 | 3 | import numpy as np 4 | from polyiou import polyiou 5 | 6 | def riounms(bboxes_per_img, classes, thresh=0.2): 7 | if len(bboxes_per_img) == 0: 8 | return [] 9 | bboxes = [] 10 | for bb in bboxes_per_img: 11 | x1,y1,x2,y2,x3,y3,x4,y4 = bb['bbox'] 12 | score,cl,x1,y1,x2,y2,x3,y3,x4,y4 = float(bb['score']),float(classes.index(bb['class'])),float(x1),float(y1),float(x2),float(y2),float(x3),float(y3),float(x4),float(y4) 13 | bboxes.append([score,cl,x1,y1,x2,y2,x3,y3,x4,y4]) 14 | bboxes = np.array(bboxes).astype('float32') 15 | bboxfiltered = [] 16 | for c in range(15): 17 | dets = bboxes[bboxes[:,1]==c] 18 | if dets.shape[0] == 0: 19 | continue 20 | scores = dets[:, 0] 21 | polys = [] 22 | areas = [] 23 | for i in range(len(dets)): 24 | tm_polygon = polyiou.VectorDouble([float(dets[i][2]), float(dets[i][3]), float(dets[i][4]), float(dets[i][5]), float(dets[i][6]), float(dets[i][7]), float(dets[i][8]), float(dets[i][9])]) 25 | polys.append(tm_polygon) 26 | order = scores.argsort()[::-1] 27 | 28 | keep = [] 29 | while order.size > 0: 30 | ovr = [] 31 | i = order[0] 32 | keep.append(i) 33 | for j in range(order.size - 1): 34 | iou = polyiou.iou_poly(polys[i], polys[order[j + 1]]) 35 | ovr.append(iou) 36 | ovr = np.array(ovr) 37 | inds = np.where(ovr <= thresh)[0] 38 | order = order[inds + 1] 39 | bboxfiltered.append(dets[keep]) 40 | if len(bboxfiltered)==0: 41 | return [] 42 | bboxfiltered = np.concatenate(bboxfiltered,axis=0) 43 | bboxes_out = [] 44 | for box in bboxfiltered: 45 | bb={} 46 | bb['bbox']=[box[2],box[3],box[4],box[5],box[6],box[7],box[8],box[9]] 47 | bb['score']=box[0] 48 | bb['class']=classes[int(box[1])] 49 | bboxes_out.append(bb) 50 | return bboxes_out 51 | 52 | -------------------------------------------------------------------------------- /nms_cpp/nms.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "polyiou.h" 6 | 7 | using namespace std; 8 | 9 | struct BBox 10 | { 11 | float iou(const BBox &, bool rect)const; 12 | string cla; 13 | float score; 14 | float x1, y1, x2, y2, x3, y3, x4, y4; 15 | }; 16 | 17 | float BBox::iou(const BBox &bbox, bool rect)const 18 | { 19 | if (rect) 20 | { 21 | float xmin = bbox.x1, ymin = bbox.y1, xmax = bbox.x3, ymax = bbox.y3; 22 | float x_lt = max(x1, xmin); 23 | float y_lt = max(y1, ymin); 24 | float x_rb = min(x3, xmax); 25 | float y_rb = min(y3, ymax); 26 | float inter_area = max(x_rb - x_lt, static_cast(0.))*max(y_rb - y_lt, static_cast(0.)); 27 | float union_area = (xmax - xmin)*(ymax - ymin) + (x3 - x1)*(y3 - y1); 28 | return inter_area / (union_area - inter_area); 29 | } 30 | else 31 | return iou_poly({ x1, y1, x2, y2, x3, y3, x4, y4 }, 32 | { bbox.x1, bbox.y1, bbox.x2, bbox.y2, bbox.x3, bbox.y3, bbox.x4, bbox.y4 }); 33 | } 34 | 35 | struct ListNode 36 | { 37 | ListNode(const BBox &bbox, ListNode *next = nullptr) :val(bbox), next(next) {} 38 | BBox val; 39 | ListNode *next; 40 | }; 41 | 42 | vector nms(vector &bboxes, const vector &cls, float thresh, bool rect) //rect:Õý¿òΪtrue, б¿òΪfalse 43 | { 44 | sort(bboxes.begin(), bboxes.end(), [](const BBox &bb1, const BBox &bb2) {return bb1.score > bb2.score; }); 45 | vectorret; 46 | for (auto c : cls) 47 | { 48 | ListNode *head = new ListNode(BBox()); 49 | ListNode *cur = head; 50 | for (auto i : bboxes) 51 | if (c == i.cla) 52 | { 53 | cur->next = new ListNode(i); 54 | cur = cur->next; 55 | } 56 | 57 | while (head->next) 58 | { 59 | ListNode *front = head->next; 60 | ret.push_back(front->val); 61 | head->next = head->next->next; 62 | if (!head->next) 63 | { 64 | delete front; 65 | break; 66 | } 67 | ListNode *pre = head; 68 | cur = head->next; 69 | while (cur) 70 | { 71 | float iou = front->val.iou(cur->val, rect); 72 | if (iou > thresh) 73 | { 74 | pre->next = cur->next; 75 | delete cur; 76 | cur = pre->next; 77 | } 78 | else 79 | { 80 | pre = pre->next; 81 | cur = cur->next; 82 | } 83 | } 84 | delete front; 85 | } 86 | delete head; 87 | } 88 | return ret; 89 | } 90 | -------------------------------------------------------------------------------- /nms_mutiprocess.py: -------------------------------------------------------------------------------- 1 | #Created by fankai 2020/6/16 20:28, https://github.com/fan0210/detection_tools 2 | 3 | import os 4 | import numpy as np 5 | from polyiou import polyiou 6 | from multiprocessing import Pool 7 | from functools import partial 8 | 9 | def riounms(pathsrc, classes, thresh): 10 | file = open(pathsrc,'r').readlines() 11 | os.remove(pathsrc) 12 | bboxes = [] 13 | for bb in file: 14 | bb = bb.split() 15 | score,cl,x1,y1,x2,y2,x3,y3,x4,y4 = float(bb[0]),float(classes.index(str(bb[1]))),float(bb[2]),float(bb[3]),float(bb[4]),float(bb[5]),float(bb[6]),float(bb[7]),float(bb[8]),float(bb[9]) 16 | bboxes.append([score,cl,x1,y1,x2,y2,x3,y3,x4,y4]) 17 | bboxes = np.array(bboxes).astype('float32') 18 | bboxfiltered = [] 19 | #bboxes = bboxes[bboxes[:,0]>0.05] 20 | for c in range(15): 21 | dets = bboxes[bboxes[:,1]==c] 22 | if dets.shape[0] == 0: 23 | continue 24 | scores = dets[:, 0] 25 | polys = [] 26 | areas = [] 27 | for i in range(len(dets)): 28 | tm_polygon = polyiou.VectorDouble([float(dets[i][2]), float(dets[i][3]), float(dets[i][4]), float(dets[i][5]), float(dets[i][6]), float(dets[i][7]), float(dets[i][8]), float(dets[i][9])]) 29 | polys.append(tm_polygon) 30 | order = scores.argsort()[::-1] 31 | 32 | keep = [] 33 | while order.size > 0: 34 | ovr = [] 35 | i = order[0] 36 | keep.append(i) 37 | for j in range(order.size - 1): 38 | iou = polyiou.iou_poly(polys[i], polys[order[j + 1]]) 39 | ovr.append(iou) 40 | ovr = np.array(ovr) 41 | inds = np.where(ovr <= thresh)[0] 42 | order = order[inds + 1] 43 | bboxfiltered.append(dets[keep]) 44 | if len(bboxfiltered)==0: 45 | return 46 | bboxfiltered = np.concatenate(bboxfiltered,axis=0) 47 | with open(pathsrc,'w') as fin: 48 | for box in bboxfiltered: 49 | score,cl,x1,y1,x2,y2,x3,y3,x4,y4 = box[0],classes[int(box[1])],box[2],box[3],box[4],box[5],box[6],box[7],box[8],box[9] 50 | fin.write(str(score)[0:5]+' '+cl+' '+str(int(x1))+' '+str(int(y1))+' '+str(int(x2))+' '+str(int(y2))+' '+str(int(x3))+' '+str(int(y3))+' '+str(int(x4))+' '+str(int(y4))+'\n') 51 | 52 | def merge(dirsrc,dirdst,classes): 53 | files = os.listdir(dirsrc) 54 | fins = [] 55 | for cl in classes: 56 | dstpath = 'Task1_'+cl+'.txt' 57 | fin = open(os.path.join(dirdst,dstpath),'a') 58 | fins.append(fin) 59 | for file in files: 60 | f = open(os.path.join(dirsrc,file),'r').readlines() 61 | oriname = file.split('.')[0] 62 | for bbox in f: 63 | bbox = bbox.split() 64 | cl_id = classes.index(bbox[1]) 65 | fins[cl_id].write(oriname+' '+bbox[0]+' '+bbox[2]+' '+bbox[3]+' '+bbox[4]+' '+bbox[5]+' '+bbox[6]+' '+bbox[7]+' '+bbox[8]+' '+bbox[9]+'\n') 66 | for fin in fins: 67 | fin.close() 68 | 69 | def nms(files, classes, merge_for_dota=False, dota_merged_dir=None, iou_thresh=0.2, num_workers=8): 70 | filepathsrc = [os.path.join(files,f) for f in os.listdir(files)] 71 | worker = partial(riounms, classes=classes, thresh=iou_thresh) 72 | Pool(num_workers).map(worker, filepathsrc) 73 | if merge_for_dota: 74 | assert dota_merged_dir, "dota_merged_dir should not be None" 75 | if not os.path.exists(dota_merged_dir): 76 | os.mkdir(dota_merged_dir) 77 | merge(files,dota_merged_dir,classes) 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ImgSplit_multiprocess_HBB.py: -------------------------------------------------------------------------------- 1 | """ 2 | 对原始遥感图像训练数据进行裁切,生成固定大小的patches,适用于HBB(Horizontal Bounding Box) 3 | """ 4 | 5 | import cv2 6 | import os 7 | import sys 8 | import numpy as np 9 | from multiprocessing import Pool 10 | from functools import partial 11 | 12 | def iou(BBGT, imgRect): 13 | """ 14 | 并不是真正的iou。计算每个BBGT和图像块所在矩形区域的交与BBGT本身的的面积之比,比值范围:0~1 15 | 16 | 输入:BBGT:n个标注框,大小为n*4,每个标注框表示为[xmin,ymin,xmax,ymax],类型为np.array 17 | imgRect:裁剪的图像块在原图上的位置,表示为[xmin,ymin,xmax,ymax],类型为np.array 18 | 返回:每个标注框与图像块的iou(并不是真正的iou),返回大小n,类型为np.array 19 | """ 20 | left_top = np.maximum(BBGT[:,:2], imgRect[:2]) 21 | right_bottom = np.minimum(BBGT[:,2:], imgRect[2:]) 22 | wh = np.maximum(right_bottom-left_top,0) 23 | inter_area = wh[:,0]*wh[:,1] 24 | iou = inter_area/((BBGT[:,2]-BBGT[:,0])*(BBGT[:,3]-BBGT[:,1])) 25 | return iou 26 | 27 | def split(imgname,dirsrc,dirdst, subsize=800,gap=200,iou_thresh=0.3,ext='.png'): 28 | """ 29 | imgname: 待裁切图像名(带扩展名) 30 | dirsrc: 待裁切的图像保存目录的上一个目录,默认图像与标注文件在一个文件夹下,图像在images下,标注在labelTxt下,标注文件格式为每行一个gt, 31 | 格式为xmin,ymin,xmax,ymax,class,想读其他格式自己动手改 32 | dirdst: 裁切的图像保存目录的上一个目录,目录下有images,labelTxt两个目录分别保存裁切好的图像或者txt文件, 33 | 保存的图像和txt文件名格式为 oriname_min_ymin.png(.txt),(xmin,ymin)为裁切图像在原图上的左上点坐标,txt格式和原文件格式相同 34 | subsize: 裁切图像的尺寸,默认为正方形,想裁切矩形自己动手改 35 | gap: 相邻行或列的图像重叠的宽度 36 | iou_thresh:小于该阈值的BBGT不会保存在对应图像的txt中(在图像过于边缘或与图像无交集) 37 | ext: 保存图像的格式 38 | """ 39 | img = cv2.imread(os.path.join(os.path.join(dirsrc,'images'),imgname),-1) 40 | bboxes = open(os.path.join(os.path.join(dirsrc,'labelTxt'),imgname.split('.')[0]+'.txt')).readlines() 41 | BBGT = [] 42 | for bb in bboxes: 43 | xmin,ymin,xmax,ymax,cl = bb.strip().split('\n')[0].split()[:5] 44 | BBGT.append([xmin,ymin,xmax,ymax,cl]) 45 | BBGT = np.array(BBGT) 46 | 47 | img_h,img_w = img.shape[:2] 48 | top = 0 49 | reachbottom = False 50 | while not reachbottom: 51 | reachright = False 52 | left = 0 53 | if top+subsize>=img_h: 54 | reachbottom = True 55 | top = max(img_h-subsize,0) 56 | while not reachright: 57 | if left+subsize>=img_w: 58 | reachright = True 59 | left = max(img_w-subsize,0) 60 | imgsplit = img[top:min(top+subsize,img_h),left:min(left+subsize,img_w)] 61 | if imgsplit.shape[:2] != (subsize,subsize): 62 | template = np.zeros((subsize,subsize,3),dtype=np.uint8) 63 | template[0:imgsplit.shape[0],0:imgsplit.shape[1]] = imgsplit 64 | imgsplit = template 65 | cv2.imwrite(os.path.join(os.path.join(dirdst,'images'),imgname.split('.')[0]+'_'+str(left)+'_'+str(top)+ext),imgsplit) 66 | imgrect = np.array([left,top,left+subsize,top+subsize]).astype('float32') 67 | ious = iou(BBGT[:,:4].astype('float32'),imgrect) 68 | BBpatch = BBGT[ious>iou_thresh] 69 | fin = open(os.path.join(os.path.join(dirdst,'labelTxt'),imgname.split('.')[0]+'_'+str(left)+'_'+str(top)+'.txt'),'a') 70 | for bb in BBpatch: 71 | fin.write(str(int(bb[0])-left)+' '+str(int(bb[1])-top)+' '+str(int(bb[2])-left)+' '+str(int(bb[3])-top)+' '+bb[4]+'\n') 72 | fin.close() 73 | left+=subsize-gap 74 | top+=subsize-gap 75 | 76 | 77 | if __name__ == '__main__': 78 | dirsrc=r'/media/ubuntu/FANK/Dataset/secret' #待裁剪图像所在目录的上级目录,图像在images文件夹下,标注文件在labelTxt下 79 | dirdst=r'/media/ubuntu/FANK/Dataset/secret_split' #裁剪结果存放目录,格式和原图像目录一样 80 | if not os.path.isdir(os.path.join(dirdst,'images')): 81 | os.mkdir(os.path.join(dirdst,'images')) 82 | if not os.path.isdir(os.path.join(dirdst,'labelTxt')): 83 | os.mkdir(os.path.join(dirdst,'labelTxt')) 84 | subsize=800 85 | gap=200 86 | iou_thresh=0.3 87 | ext='.png' 88 | num_thresh = 8 89 | 90 | def split_patch_wrap(imgname): 91 | split(imgname,dirsrc,dirdst,subsize,gap,iou_thresh,ext) 92 | 93 | images = os.listdir(os.path.join(dirsrc,'images')) 94 | worker = partial(split_patch_wrap) 95 | Pool(num_thresh).map(worker, images) 96 | -------------------------------------------------------------------------------- /poly_to_rect.py: -------------------------------------------------------------------------------- 1 | # Created by fankai 2020/6/8 23:15, https://github.com/fan0210/detection_tools/ 2 | 3 | import numpy as np 4 | import cv2 5 | import math 6 | 7 | def poly_to_rect(polygons): 8 | """ 9 | polygons: 10 | type=np.array.float32 11 | shape=(n_poly,8) 12 | return: 13 | type=np.array.float32 14 | shape=(n_poly,8) 15 | """ 16 | rects_min_area = [] 17 | for poly in polygons: 18 | x1,y1,x2,y2,x3,y3,x4,y4 = poly 19 | (r_x1,r_y1),(r_x2,r_y2),(r_x3,r_y3),(r_x4,r_y4) = \ 20 | cv2.boxPoints(cv2.minAreaRect(np.array([[int(x1),int(y1)],[int(x2),int(y2)],[int(x3),int(y3)],[int(x4),int(y4)]]))) 21 | rects_min_area.append([r_x1,r_y1,r_x2,r_y2,r_x3,r_y3,r_x4,r_y4]) 22 | rects_min_area = np.array(rects_min_area) 23 | w_rects = np.sqrt((rects_min_area[:,0]-rects_min_area[:,2])**2+(rects_min_area[:,1]-rects_min_area[:,3])**2) 24 | h_rects = np.sqrt((rects_min_area[:,2]-rects_min_area[:,4])**2+(rects_min_area[:,3]-rects_min_area[:,5])**2) 25 | mask_x1_eq_x2 = rects_min_area[:,0]==rects_min_area[:,2] 26 | angle_w = np.where(mask_x1_eq_x2,0.5,np.arctan((rects_min_area[:,1]-rects_min_area[:,3])/ 27 | (np.where(mask_x1_eq_x2,0.0001,rects_min_area[:,2]-rects_min_area[:,0])))/math.pi) 28 | mask_x2_eq_x3 = rects_min_area[:,2]==rects_min_area[:,4] 29 | angle_h = np.where(mask_x2_eq_x3,0.5,np.arctan((rects_min_area[:,3]-rects_min_area[:,5])/ 30 | (np.where(mask_x2_eq_x3,0.0001,rects_min_area[:,4]-rects_min_area[:,2])))/math.pi) 31 | angle = np.where(w_rects>h_rects,angle_w,angle_h) 32 | angle = np.where(angle<0,angle+1,angle) 33 | mx_1,mx_2,mx_3,mx_4,my_1,my_2,my_3,my_4 = \ 34 | (polygons[:,0]+polygons[:,2])/2,(polygons[:,2]+polygons[:,4])/2,(polygons[:,4]+polygons[:,6])/2,(polygons[:,6]+polygons[:,0])/2,\ 35 | (polygons[:,1]+polygons[:,3])/2,(polygons[:,3]+polygons[:,5])/2,(polygons[:,5]+polygons[:,7])/2,(polygons[:,7]+polygons[:,1])/2 36 | wh = np.concatenate([np.sqrt((mx_1-mx_3)**2+(my_1-my_3)**2)[:,None],np.sqrt((mx_2-mx_4)**2+(my_2-my_4)**2)[:,None]],axis=-1) 37 | mask_mx1_eq_mx3 = mx_1==mx_3 38 | angle_mw = np.where(mask_mx1_eq_mx3,0.5,np.arctan((my_1-my_3)/ 39 | (np.where(mask_mx1_eq_mx3,0.0001,mx_3-mx_1)))/math.pi) 40 | mask_mx2_eq_mx4 = mx_2==mx_4 41 | angle_mh = np.where(mask_mx2_eq_mx4,0.5,np.arctan((my_2-my_4)/ 42 | (np.where(mask_mx2_eq_mx4,0.0001,mx_4-mx_2)))/math.pi) 43 | angle_m = np.where(wh[:,0]>wh[:,1],angle_mw,angle_mh) 44 | angle_m = np.where(angle_m<0,angle_m+1,angle_m) 45 | angle_err = np.sin(np.abs(angle-angle_m)*math.pi) 46 | angle_out = np.where(angle_err>math.sin(math.pi/4),angle-0.5,angle) 47 | angle_out = np.where(angle_out<0,angle_out+1,angle_out) 48 | angle_out = angle_out*math.pi 49 | cx_out = polygons[:,0::2].sum(axis=-1)/4 50 | cy_out = polygons[:,1::2].sum(axis=-1)/4 51 | w_out = np.max(wh,axis=-1) 52 | h_out = np.min(wh,axis=-1) 53 | half_dl = np.sqrt(w_out*w_out+h_out*h_out)/2 54 | a1 = math.pi-(math.pi-angle_out+np.arccos(w_out/2/half_dl)) 55 | a2 = 2*np.arctan(h_out/w_out)+a1 56 | x1 = half_dl*np.cos(a2) 57 | y1 = -half_dl*np.sin(a2) 58 | x2 = half_dl*np.cos(a1) 59 | y2 = -half_dl*np.sin(a1) 60 | x3,y3,x4,y4 = -x1,-y1,-x2,-y2 61 | 62 | return np.stack([x1+cx_out,y1+cy_out,x2+cx_out,y2+cy_out,x3+cx_out,y3+cy_out,x4+cx_out,y4+cy_out]).transpose() 63 | 64 | if __name__ == '__main__': 65 | import os 66 | import shapely.geometry as shgeo 67 | 68 | imgpath = r'F:\polytorect\P0049.png' 69 | labelpath = r'F:\polytorect\P0049.txt' 70 | 71 | img = cv2.imread(imgpath) 72 | 73 | files = open(labelpath,'r').readlines() 74 | bboxes_poly = np.array([bbox.split()[0:8] for bbox in files if len(bbox.split())==10],dtype='float32') 75 | 76 | bboxes_min_area = [] 77 | for poly in bboxes_poly: 78 | x1,y1,x2,y2,x3,y3,x4,y4 = poly 79 | (r_x1,r_y1),(r_x2,r_y2),(r_x3,r_y3),(r_x4,r_y4) = \ 80 | cv2.boxPoints(cv2.minAreaRect(np.array([[int(x1),int(y1)],[int(x2),int(y2)],[int(x3),int(y3)],[int(x4),int(y4)]]))) 81 | bboxes_min_area.append([r_x1,r_y1,r_x2,r_y2,r_x3,r_y3,r_x4,r_y4]) 82 | bboxes_min_area = np.array(bboxes_min_area) 83 | 84 | bboxes_rect = poly_to_rect(bboxes_poly) 85 | colors = [(0,255,0),(0,0,255),(255,0,0)] 86 | for i in range(len(bboxes_rect)): 87 | bboxes = [bboxes_rect[i],bboxes_poly[i],bboxes_min_area[i]] 88 | bboxes_shego = [] 89 | for j,bb in enumerate(bboxes): 90 | x1,y1,x2,y2,x3,y3,x4,y4 = bb.astype('int32') 91 | cv2.line(img,(int(x1),int(y1)),(int(x2),int(y2)),colors[j],1,16) 92 | cv2.line(img,(int(x2),int(y2)),(int(x3),int(y3)),colors[j],1,16) 93 | cv2.line(img,(int(x3),int(y3)),(int(x4),int(y4)),colors[j],1,16) 94 | cv2.line(img,(int(x4),int(y4)),(int(x1),int(y1)),colors[j],1,16) 95 | bboxes_shego.append(shgeo.Polygon([(x1, y1),(x2, y2),(x3, y3),(x4, y4)])) 96 | 97 | rect_refined,polygon,rect_min_area=bboxes_shego 98 | area_rect_refined = rect_refined.area 99 | area_polygon = polygon.area 100 | area_rect_min_area = rect_min_area.area 101 | 102 | intersec_rectrefined_ploy = rect_refined.intersection(polygon) 103 | intersec_rectminarea_poly = rect_min_area.intersection(polygon) 104 | iou1 = intersec_rectrefined_ploy.area/(area_rect_refined+area_polygon-intersec_rectrefined_ploy.area) 105 | iou2 = intersec_rectminarea_poly.area/(area_rect_min_area+area_polygon-intersec_rectminarea_poly.area) 106 | print(iou1,iou2) 107 | 108 | cv2.imwrite('im.png',img) 109 | 110 | 111 | --------------------------------------------------------------------------------