一、什麼是非極大值抑制
非極大值抑制(Non-Maximum Suppression,簡稱NMS)是一種用於邊緣檢測和目標檢測中的常用技術,其作用是對檢測到的邊緣或目標進行篩選和過濾,只保留最明顯、最顯著的部分。
在邊緣檢測中,Canny演算法常常會產生較多的細節邊緣,而非極大值抑制可以將這些邊緣過濾掉,只保留最明顯的邊緣;同樣,在目標檢測中,非極大值抑制有助於消除重複或遮蓋的目標,並只留下一些最突出的目標。
二、非極大值抑制的原理
非極大值抑制的原理非常簡單:對於檢測到的每個邊緣點或目標,取其周圍一個窗口內的所有相鄰點的灰度值,如果該點的灰度值最大,那麼就將其保留,否則將其丟棄。
以邊緣檢測為例,當Canny演算法對圖像進行邊緣檢測後,會得到很多邊緣點。由於像素點的灰度值往往會出現較大的變化,我們可以將這些邊緣點看作是局部的”山峰”,其周圍的邊緣點則是”山峰”的”山峰麓”。我們希望保留的是”山峰”最高、最明顯的點,而將其他點抑制掉。
三、非極大值抑制的實現
下面是一個使用Python實現的非極大值抑制的代碼示例:
import cv2 def non_max_suppression(boxes, overlapThresh): # 如果框的數量為空,直接返回空列表 if len(boxes) == 0: return [] # 如果輸入的框的數據類型為整數,將其轉換為浮點數 if boxes.dtype.kind == "i": boxes = boxes.astype("float") # 初始化選擇框的列表 pick = [] # 分別獲取框的坐標軸信息 startX = boxes[:, 0] startY = boxes[:, 1] endX = boxes[:, 2] endY = boxes[:, 3] # 計算矩形框的面積和排序 area = (endX - startX + 1) * (endY - startY + 1) idxs = np.argsort(endY) # 循環遍歷排序後的框的索引 while len(idxs) > 0: # 取出框列表中的最後一個索引,並將其添加到已選擇的列表中 last = len(idxs) - 1 i = idxs[last] pick.append(i) # 尋找其他矩形與當前矩形交叉的面積 xx1 = np.maximum(startX[i], startX[idxs[:last]]) yy1 = np.maximum(startY[i], startY[idxs[:last]]) xx2 = np.minimum(endX[i], endX[idxs[:last]]) yy2 = np.minimum(endY[i], endY[idxs[:last]]) # 計算矩形框之間的交叉面積 w = np.maximum(0, xx2 - xx1 + 1) h = np.maximum(0, yy2 - yy1 + 1) # 計算交叉面積比 overlap = (w * h) / area[idxs[:last]] # 將交叉面積比小於給定閾值的索引從列表中刪除 idxs = np.delete(idxs, np.concatenate(([last],np.where(overlap > overlapThresh)[0]))) # 返回選擇框的列表 return boxes[pick].astype("int")
該代碼實現了一個基於IoU重疊度的非極大值抑制演算法,其中的參數boxes代表一組含有x、y、w、h四個坐標的框,overlapThresh代表給定的IoU重疊度閾值。該演算法會對輸入的框進行遍歷,依次計算每個框和其他框的IoU重疊度,並選擇IoU大於給定閾值的框保留。
四、非極大值抑制的應用
在實際應用中,非極大值抑制被廣泛應用於目標檢測、人臉識別、OCR等領域。例如,當我們要對一組人臉圖像進行檢測時,非極大值抑制可以幫助我們消除重複或遮蓋的人臉,並只保留一些最明顯、最突出的人臉。
下面是一個基於非極大值抑制演算法的人臉檢測示例代碼:
import cv2 def detect_faces(image, face_cascade): # 將圖像轉灰度 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用分類器檢測圖像中的人臉 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5) # 對檢測到的矩形框進行非極大值抑制,保留最突出的人臉 faces = non_max_suppression(faces, 0.3) # 返回人臉框的坐標信息及圖像 return faces, image # 初始化人臉檢測器 face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") # 讀取輸入圖像 image = cv2.imread("test.jpg") # 檢測圖像中的人臉 faces, image = detect_faces(image, face_cascade) # 循環遍歷檢測到的人臉,並在圖像上進行標註 for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 顯示標註後的圖像 cv2.imshow("Faces found", image) cv2.waitKey(0)
該代碼利用OpenCV庫提供的分類器,從一張圖像中檢測到其中的人臉框,然後使用非極大值抑制方法,從中選擇最突出、最明顯的人臉框。最後,程序對圖像中的每個人臉框進行標記,並在圖像上顯示標記後的結果。
原創文章,作者:KUBRN,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/332039.html