array python 交集_NMS原理(非极大值抑制)+python实现
1.先解釋什么叫IoU(intersection-over-union)。IoU表示(A∩B)/(A∪B) 即交并比。 非極大值抑制:圖一 ——> 圖二 ,剔除同一個目標上的重疊建議框,最終一個目標保留一個得分最高的建議框。
圖一圖二2.那么如何實現非極大值抑制呢?步驟如下(假設進行非極大值抑制的輸入為2000x20的矩陣,2000表示該圖像上框的個數,20表示類別數):
① 對2000×20維矩陣中每列按從大到小進行排序(每列表示一類,共20類。同一類可能有多個目標,如上圖有兩個人);
② 從每列最大的得分建議框開始,分別與該列后面的得分建議框進行IoU計算,若IoU>閾值,則剔除得分較小的建議框,否則認為圖像中同一類物體有多個目標;[兩個同類的目標的建議框基本不會有重疊,因此去掉建議框重疊較大的實際上是實現了剔除同一個目標的重疊框]
③ 從每列次大的得分建議框開始,重復步驟②;
④ 重復步驟③直到遍歷完該列所有建議框;
⑤ 遍歷完2000×20維矩陣所有列,即所有物體種類都做一遍非極大值抑制;
3.代碼實現如下,也可以在我的github上下載:https://github.com/hiJulie/NMS
import numpy as np import random import cv2def non_max_suppress(predicts_dict, threshold):for object_name, bbox in predicts_dict.items():#對每一個類別分別進行NMS;一次讀取一對鍵值(即某個類別的所有框)bbox_array = np.array(bbox, dtype=np.float)#下面分別獲取框的左上角坐標(x1,y1),右下角坐標(x2,y2)及此框的置信度;這里需要注意的是圖像左上角可以看做坐標點(0,0),右下角可以看做坐標點(1,1),也就是說從左往右x值增大,從上往下y值增大x1 = bbox_array[:, 0]y1 = bbox_array[:, 1]x2 = bbox_array[:, 2]y2 = bbox_array[:, 3]scores = bbox_array[:, 4]order = scores.argsort()[::-1]#argsort函數返回的是數組值從小到大的索引值,[::-1]表示取反。即這里返回的是數組值從大到小的索引值areas = (x2 - x1 + 1) * (y2 - y1 + 1)#當前類所有框的面積(python會自動使用廣播機制,相當于MATLAB中的.*即兩矩陣對應元素相乘);x1=3,x2=5,習慣上計算x方向長度就是x=3、4、5這三個像素,即5-3+1=3,而不是5-3=2,所以需要加1keep = []#按confidence從高到低遍歷bbx,移除所有與該矩形框的IoU值大于threshold的矩形框while order.size > 0:i = order[0]keep.append(i)#保留當前最大confidence對應的bbx索引#獲取所有與當前bbx的交集對應的左上角和右下角坐標,并計算IoU(注意這里是同時計算一個bbx與其他所有bbx的IoU)xx1 = np.maximum(x1[i], x1[order[1:]])#最大置信度的左上角坐標分別與剩余所有的框的左上角坐標進行比較,分別保存較大值;因此這里的xx1的維數應該是當前類的框的個數減1yy1 = np.maximum(y1[i], y1[order[1:]])xx2 = np.minimum(x2[i], x2[order[1:]])yy2 = np.minimum(y2[i], y2[order[1:]])inter = np.maximum(0.0, xx2-xx1+1) * np.maximum(0.0, yy2-yy1+1)iou = inter / (areas[i] + areas[order[1:]] - inter)#注意這里都是采用廣播機制,同時計算了置信度最高的框與其余框的IoUinds = np.where(iou <= threshold)[0]#保留iou小于等于闕值的框的索引值order = order[inds + 1]#將order中的第inds+1處的值重新賦值給order;即更新保留下來的索引,加1是因為因為沒有計算與自身的IOU,所以索引相差1,需要加上bbox = bbox_array[keep]predicts_dict[object_name] = bbox.tolist()#predicts_dict = predicts_dictreturn predicts_dict#下面在一張全黑圖片上測試非極大值抑制的效果 img = np.zeros((600,600), np.uint8) #predicts_dict = {'black1': [[83, 54, 165, 163, 0.8], [67, 48, 118, 132, 0.5], [91, 38, 192, 171, 0.6]]} predicts_dict = {'black1': [[83, 54, 165, 163, 0.8], [67, 48, 118, 132, 0.5], [91, 38, 192, 171, 0.6]], 'black2': [[59, 120, 137, 368, 0.12], [54, 154, 148, 382, 0.13]] } #在全黑的圖像上畫出設定的幾個框 for object_name, bbox in predicts_dict.items():for box in bbox:x1, y1, x2, y2, score = box[0], box[1], box[2], box[3], box[-1]y_text = int(random.uniform(y1, y2))# uniform()是不能直接訪問的,需要導入 random 模塊,然后通過 random 靜態對象調用該方法。uniform() 方法將隨機生成下一個實數,它在 [x, y) 范圍內cv2.rectangle(img, (x1, y1), (x2, y2), (255, 255, 255), 2)cv2.putText(img, str(score), (x2 - 30, y_text), 2, 1, (255, 255, 0))cv2.namedWindow("black1_roi")# 創建一個顯示圖像的窗口cv2.imshow("black1_roi", img)# 在窗口中顯示圖像;注意這里的窗口名字如果不是剛剛創建的窗口的名字則會自動創建一個新的窗口并將圖像顯示在這個窗口cv2.waitKey(0)# 如果不添這一句,在IDLE中執行窗口直接無響應。在命令行中執行的話,則是一閃而過。cv2.destroyAllWindows() # 最后釋放窗口是個好習慣!#在全黑圖片上畫出經過非極大值抑制后的框 img_cp = np.zeros((600,600), np.uint8) predicts_dict_nms = non_max_suppress(predicts_dict, 0.1) for object_name, bbox in predicts_dict_nms.items():for box in bbox:x1, y1, x2, y2, score = int(box[0]), int(box[1]), int(box[2]), int(box[3]), box[-1]y_text = int(random.uniform(y1, y2))# uniform()是不能直接訪問的,需要導入 random 模塊,然后通過 random 靜態對象調用該方法。uniform() 方法將隨機生成下一個實數,它在 [x, y) 范圍內cv2.rectangle(img_cp, (x1, y1), (x2, y2), (255, 255, 255), 2)cv2.putText(img_cp, str(score), (x2 - 30, y_text), 2, 1, (255, 255, 0))cv2.namedWindow("black1_nms")# 創建一個顯示圖像的窗口cv2.imshow("black1_nms", img_cp)# 在窗口中顯示圖像;注意這里的窗口名字如果不是剛剛創建的窗口的名字則會自動創建一個新的窗口并將圖像顯示在這個窗口cv2.waitKey(0)# 如果不添這一句,在IDLE中執行窗口直接無響應。在命令行中執行的話,則是一閃而過。cv2.destroyAllWindows() # 最后釋放窗口是個好習慣!參考博客:
非極大值抑制(nms)算法功能及python實現 - CSDN博客
目標定位和檢測系列(3):交并比(IOU)和非極大值抑制(NMS)的python實現 - CSDN博
總結
以上是生活随笔為你收集整理的array python 交集_NMS原理(非极大值抑制)+python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每次执行java命令 都要source_
- 下一篇: 调用接口登录禅道_第三方应用配置免密登录