非極大值抑制

一、什麼是非極大值抑制

非極大值抑制(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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
KUBRN的頭像KUBRN
上一篇 2025-01-20 14:11
下一篇 2025-01-20 14:11

相關推薦

發表回復

登錄後才能評論