opencv中的MSER的使用和NMS後的矩形框

MSER

形象一點解釋這個原理就是:MSER對一幅已經處理成灰度的圖像做二值化處理,這個處理的閾值從0到255遞增,這個閾值的遞增類似於在一片土地上做水平面的上升,隨着水平面上升,高高低低凹凸不平的土地區域就會不斷被淹沒,這就是分水嶺算法,而這個高低不同,就是圖像中灰度值的不同。而在一幅含有文字的圖像上,有些區域(比如文字)由於顏色(灰度值)是一致的,因此在水平面(閾值)持續增長的一段時間內都不會被覆蓋直到閾值漲到文字本身的灰度值時纔會被淹沒,這些區域就叫做最大穩定極值區域。

NMS

NMS是經常伴隨圖像區域檢測的算法,作用是去除重複的區域,在人臉識別、物體檢測等領域都經常使用,全稱是非極大值抑制(non maximum suppression),顧名思義就是抑制不是極大值的元素,所以用在這裏就是抑制不是最大框的框,也就是去除大框中包含的小框。

NMS的基本思想是遍歷將所有的框得分排序,選中其中得分最高的框,然後遍歷其餘框找到和當前最高分的框的重疊面積(IOU)大於一定閾值的框,刪除。然後繼續這個過程,找另一個得分高的框,再刪除IOU大於閾值的框,循環。

在這個例子中,就是設定一個IOU閾值(比如0.5,也就是如果兩個框的重疊面積大於其中一個框的50%,那麼就刪除那個框),然後遍歷所有框,對剩下的每個框,遍歷判斷其餘框中與他重疊面積大於閾值的,則刪除。最後剩下的就是不包含重疊部分的文本框了。

測試

測試圖片

在這裏插入圖片描述


import cv2
import numpy as np


def non_max_suppression_fast(boxes, overlapThresh):
    # 空數組檢測
    if len(boxes) == 0:
        return []

        # 將類型轉爲float
    if boxes.dtype.kind == "i":
        boxes = boxes.astype("float")

    pick = []

    # 四個座標數組
    x1 = boxes[:, 0]
    y1 = boxes[:, 1]
    x2 = boxes[:, 2]
    y2 = boxes[:, 3]

    area = (x2 - x1 + 1) * (y2 - y1 + 1)  # 計算面積數組
    idxs = np.argsort(y2)  # 返回的是右下角座標從小到大的索引值

    # 開始遍歷刪除重複的框
    while len(idxs) > 0:
        # 將最右下方的框放入pick數組
        last = len(idxs) - 1
        i = idxs[last]
        pick.append(i)

        # 找到剩下的其餘框中最大的座標x1y1,和最小的座標x2y2,
        xx1 = np.maximum(x1[i], x1[idxs[:last]])
        yy1 = np.maximum(y1[i], y1[idxs[:last]])
        xx2 = np.minimum(x2[i], x2[idxs[:last]])
        yy2 = np.minimum(y2[i], y2[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")


img = cv2.imread('test2.png')
vis = img.copy()  # 用於繪製矩形框圖
orig = img.copy()  # 用於繪製不重疊的矩形框圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 得到灰度圖
mser = cv2.MSER_create()  # 得到mser算法對象
regions, _ = mser.detectRegions(gray)  # 獲取文本區域
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions]  # 繪製文本區域
cv2.polylines(img, hulls, 1, (255, 0, 0))
cv2.namedWindow("img", 0)
cv2.resizeWindow("img", 800, 640)  # 限定顯示圖像的大小
cv2.imshow('img', img)
cv2.imwrite('img.jpg', img)

keep = []
# 繪製目前的矩形文本框
for c in hulls:
    x, y, w, h = cv2.boundingRect(c)
    keep.append([x, y, x + w, y + h])
    cv2.rectangle(vis, (x, y), (x + w, y + h), (255, 255, 0), 1)
print("[x] %d initial bounding boxes" % (len(keep)))
cv2.namedWindow("hulls", 0)
cv2.resizeWindow("hulls", 800, 640)
cv2.imshow("hulls", vis)
cv2.imwrite('hulls.jpg', vis)


# 篩選不重複的矩形框
keep2 = np.array(keep)
pick = non_max_suppression_fast(keep2, 0.5)
print("[x] after applying non-maximum, %d bounding boxes" % (len(pick)))
for (startX, startY, endX, endY) in pick:
    cv2.rectangle(orig, (startX, startY), (endX, endY), (255, 185, 120), 2)
cv2.namedWindow("After NMS", 0)
cv2.resizeWindow("After NMS", 800, 640)
cv2.imshow("After NMS", orig)
cv2.imwrite('afterNMS.jpg', orig)

cv2.waitKey(0)
cv2.destroyAllWindows()

img:
在這裏插入圖片描述
hulls:
在這裏插入圖片描述
使用NMS後的效果:
在這裏插入圖片描述

reference:
https://www.jianshu.com/p/b5af24e2f9ff

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章