天天看點

計算機視覺 文本檢測與文本識别 (一)

文本檢測

  • ​​傳統文本檢測​​
  • ​​形态學:​​
  • ​​MSER+NMS​​
  • ​​深度學習文本檢測分類​​
  • ​​基于候選框的文本檢測​​
  • ​​基于分割的文本檢測​​
  • ​​基于混合的文本檢測​​

傳統文本檢測

目前應用中面對文本檢測會遇到很多難點:

  • 文本圖像的背景多樣化,很多背景可能像素情況與文本結構相似
  • 文本的形狀和方向多樣化,可能圖像中文本的擺放方向是傾斜的,橫向的
  • 文本的顔色,字型多樣化
  • 圖像中受光照等環境因素影響

    由于這些檢測上的難點,傳統基于opencv通過形态學、MSER+NMS的方法無法實作實際場景的文本檢測。是以對于複雜場景下文本檢測大多基于深度學習算法實作。

形态學:

計算機視覺 文本檢測與文本識别 (一)
import cv2
import numpy as np
 
# 讀取圖檔
imagePath = 'data.jpg'
img = cv2.imread(imagePath)
 
# 轉化成灰階圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
# 利用Sobel邊緣檢測生成二值圖
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize=3)
# 二值化
ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
 
# 膨脹、腐蝕
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))
 
# 膨脹一次,讓輪廓突出
dilation = cv2.dilate(binary, element2, iterations=1)
 
# 腐蝕一次,去掉細節
erosion = cv2.erode(dilation, element1, iterations=1)
 
# 再次膨脹,讓輪廓明顯一些
dilation2 = cv2.dilate(erosion, element2, iterations=2)
 
#  查找輪廓和篩選文字區域
region = []
contours, hierarchy = cv2.findContours(dilation2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    cnt = contours[i]
 
    # 計算輪廓面積,并篩選掉面積小的
    area = cv2.contourArea(cnt)
    if (area < 1000):
        continue
 
    # 找到最小的矩形
    rect = cv2.minAreaRect(cnt)
    print ("rect is: ")
    print (rect)
 
    # box是四個點的坐标
    box = cv2.boxPoints(rect)
    box = np.int0(box)
 
    # 計算高和寬
    height = abs(box[0][1] - box[2][1])
    width = abs(box[0][0] - box[2][0])
 
    # 根據文字特征,篩選那些太細的矩形,留下扁的
    if (height > width * 1.3):
        continue
 
    region.append(box)
 
# 繪制輪廓
for box in region:
    cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()      

MSER+NMS

MSER全稱叫做最大穩定極值區域(MSER-Maximally Stable Extremal Regions),是一種檢測圖像中文本區域的傳統圖像算法,主要是基于分水嶺的思想來對圖像進行斑點(blob)區域檢測。

MSER對灰階圖像取門檻值進行二值化處理,門檻值從0到255依次進行遞增,門檻值的遞增類似于分水嶺算法中的水準面的上升,随着水準面的上升,有一些山谷和較矮的丘陵會被淹沒,如果從天空往下看,則整個區域被分為陸地和水域兩個部分,這類似于二值圖像。圖像中灰階值的不同就對應地勢高低的不同,每個門檻值都都會生成一個二值圖。

NMS的基本思想是将所有框按得分進行排序,然後無條件保留其中得分最高的框,然後周遊其餘框找到和目前最高分的框的重疊面積(IOU)大于一定門檻值的框,并删除。然後繼續這個過程,找另一個得分高的框,再删除和其IOU大于門檻值的框,一直循環直到所有的框都被處理。

NMS流程:

  1. 根據候選框的類别分類機率(得分),按最高到最低将BBox排序,例如:A>B>C>D>E>F
  2. 先标記最大機率矩形框A是要保留下來的,即A的分數最高,則無條件保留
  3. 将B~E分别與A求重疊率IoU(兩框的交并比),假設B、D與A的IoU大于設定的門檻值,那麼B和D可以認為是重複标記被剔除
  4. 繼續從剩下的矩形框C、E、F中選擇機率最大的C,标記為要無條件保留下來的框,然後分别計算C與E、F的重疊度,扔掉重疊度超過設定門檻值的矩形框
  5. 就這樣一直重複下去,直到剩下的矩形框沒有了,得到所有要保留下來的矩形框
    計算機視覺 文本檢測與文本識别 (一)
    MSER實作:
# 讀取圖檔
imagePath = 'data.jpg'
img = cv2.imread(imagePath)
 
# 灰階化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
vis = img.copy()
orig = img.copy()
 
# 調用 MSER 算法
mser = cv2.MSER_create()
regions, _ = mser.detectRegions(gray)  # 擷取文本區域
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions]  # 繪制文本區域
cv2.polylines(img, hulls, 1, (0, 255, 0))
cv2.imshow('img', 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)
cv2.imshow("hulls", vis)      

NMS實作:

# NMS 方法(Non Maximum Suppression,非極大值抑制)
def nms(boxes, overlapThresh):
    if len(boxes) == 0:
        return []
 
    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)
 
        # 找剩下的其餘框中最大坐标和最小坐标
        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]])
 
        # 計算重疊面積占對應框的比例,即 IoU
        w = np.maximum(0, xx2 - xx1 + 1)
        h = np.maximum(0, yy2 - yy1 + 1)
        overlap = (w * h) / area[idxs[:last]]
 
        # 如果 IoU 大于指定門檻值,則删除
        idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlapThresh)[0])))
 
    return boxes[pick].astype("int")      

深度學習文本檢測分類

目前基于在深度學習的文本檢測方法主要包括如下:

  • 基于候選框的文本檢測
  • 基于分割的文本檢測
  • 基于兩者方法混合文本檢測

基于候選框的文本檢測

思路:基于候選框文本檢測,是利用像素特征提取,用若幹個先驗框産生一些對應的候選文本框。再經過非最大抑制(NMS)得到最終的預測結果

計算機視覺 文本檢測與文本識别 (一)

基于分割的文本檢測

基于混合的文本檢測

繼續閱讀