人工智能学习--文本检测实践
注釋:文本檢測 和 文本識別是兩回事。 可能現在已經有 end-to-end的深度神經網絡可以將文本檢測和識別一起實現,這個要去搜相關的sci論文。
文本檢測,是從一張圖片中找到文字區域,并用矩形框標注出來。 不做識別的功能。
文本識別,前提是假設已經有文本框的內容,對這些內容實現文字識別。
?
轉自:https://my.oschina.net/u/876354/blog/3054322? ?并加以小修改,供學習參考。
文字檢測是文字識別過程中的一個非常重要的環節,文字檢測的主要目標是將圖片中的文字區域位置檢測出來,以便于進行后面的文字識別,只有找到了文本所在區域,才能對其內容進行識別。
文字檢測的場景主要分為兩種,一種是簡單場景,另一種是復雜場景。其中,簡單場景的文字檢測較為簡單,例如像書本掃描、屏幕截圖、或者清晰度高、規整的照片等;而復雜場景,主要是指自然場景,情況比較復雜,例如像街邊的廣告牌、產品包裝盒、設備上的說明、商標等等,存在著背景復雜、光線忽明忽暗、角度傾斜、扭曲變形、清晰度不足等各種情況,文字檢測的難度更大。如下圖:
本文將介紹簡單場景、復雜場景中常用的文字檢測方法,包括形態學操作、MSER+NMS、CTPN、SegLink、EAST等方法,并主要以ICDAR場景文字圖片數據集介紹如何使用這些方法,如下圖:
1、簡單場景:形態學操作法
通過利用計算機視覺中的圖像形態學操作,包括膨脹、腐蝕基本操作,即可實現簡單場景的文字檢測,例如檢測屏幕截圖中的文字區域位置,如下圖:
其中,“膨脹”就是對圖像中的高亮部分進行擴張,讓白色區域變多;“腐蝕”就是圖像中的高亮部分被蠶食,讓黑色區域變多。通過膨脹、腐蝕的一系列操作,可將文字區域的輪廓突出,并消除掉一些邊框線條,再通過查找輪廓的方法計算出文字區域的位置出來。主要的步驟如下:
- 讀取圖片,并轉為灰度圖
- 圖片二值化,或先降噪后再二值化,以便簡化處理
- 膨脹、腐蝕操作,突出輪廓、消除邊框線條
- 查找輪廓,去除不符合文字特點的邊框
- 返回文字檢測的邊框結果
通過OpenCV,便能輕松實現以上過程,核心代碼如下:
# -*- coding: utf-8 -*-import cv2 import numpy as np# 讀取圖片 imagePath = '/data/download/test1.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):continueregion.append(box)# 繪制輪廓 for box in region:cv2.drawContours(img, [box], 0, (0, 255, 0), 2)cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()該圖像處理過程如下圖所示:
可以看到最終成功將圖像中的文字區域檢測出來了。
這種方法的特點是計算簡單、處理起來非常快,但在文字檢測中的應用場景非常有限,例如如果圖片是拍照的,光線有明有暗或者角度有傾斜、紙張變形等,則該方法需要不斷重新調整才能檢測,而且效果也不會很好,如下圖。例如上面介紹的代碼是針對白底黑字的檢測,如果是深色底白色字則需要重新調整代碼,如果有需要,可再私信我交流。
?
2、簡單場景:MSER+NMS檢測法
MSER(Maximally Stable Extremal Regions,最大穩定極值區域)是一個較為流行的文字檢測傳統方法(相對于基于深度學習的AI文字檢測而言),在傳統OCR中應用較廣,在某些場景下,又快又準。
MSER算法是在2002提出來的,主要是基于分水嶺的思想進行檢測。分水嶺算法思想來源于地形學,將圖像當作自然地貌,圖像中每一個像素的灰度值表示該點的海拔高度,每一個局部極小值及區域稱為集水盆地,兩個集水盆地之間的邊界則為分水嶺,如下圖:
MSER的處理過程是這樣的,對一幅灰度圖像取不同的閾值進行二值化處理,閾值從0至255遞增,這個遞增的過程就好比是一片土地上的水面不斷上升,隨著水位的不斷上升,一些較低的區域就會逐漸被淹沒,從天空鳥瞰,大地變為陸地、水域兩部分,并且水域部分在不斷擴大。在這個“漫水”的過程中,圖像中的某些連通區域變化很小,甚至沒有變化,則該區域就被稱為最大穩定極值區域。在一幅有文字的圖像上,文字區域由于顏色(灰度值)是一致的,因此在水平面(閾值)持續增長的過程中,一開始不會被“淹沒”,直到閾值增加到文字本身的灰度值時才會被“淹沒”。該算法可以用來粗略地定位出圖像中的文字區域位置。
聽起來這個處理過程似乎非常復雜,好在OpenCV中已內置了MSER的算法,可以直接調用,大大簡化了處理過程。
檢測效果如下圖:
檢測后的結果是存在各種不規則的檢測框形狀,通過對這些框的坐標作重新處理,變成一個個的矩形框。如下圖:
核心代碼如下:
# 讀取圖片 imagePath = '/data/download/test2.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方法(Non Maximum Suppression,非極大值抑制),也就是抑制非極大值的元素,即抑制不是最大尺寸的框,相當于去除大框中包含的小框,達到去除重復區域,找到最佳檢測位置的目的。
NMS算法的主要流程如下:
- 將所有框按置信度得分進行排序(如果邊框沒有置信度得分,也可以按坐標進行排序)
- 取其中得分最高的框出來
- 遍歷該框與其余框的重疊面積(IoU)
- 刪除IoU大于某個閾值的框(閾值可按需設定,例如0.3、0.5、0.8等)
- 取下一個得分最高的框出來,重復以上過程
經過以上步驟,最后剩下的就是不包含重疊部分的文本檢測框了。核心代碼如下:
# 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) - 1i = 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]])# 計算重疊面積占對應框的比例,即 IoUw = 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處理后的檢測結果如下圖:
從上圖可以看出,經MSER+NMS后,已能較好地將文字區域檢測、圈出來。
MSER+NMS檢測方法在傳統的OCR應用中使用廣泛,檢測速度也非常快,能滿足一定的文字識別場景。但當在復雜的自然場景中,特別是有復雜背景的,其檢測效果也不盡人意,會將一些無關的因素也檢測出來,如下圖:
以下是MSER檢測+矩形框處理+NMS的完整代碼: 圖片目錄地方需要修改使用。 參考:https://www.jianshu.com/p/b5af24e2f9ff
import cv2 import numpy as npdef non_max_suppression_fast(boxes, overlapThresh):# 空數組檢測if len(boxes) == 0:return []# 將類型轉為floatif 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) - 1i = 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('1501728414965.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)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)# 篩選不重復的矩形框 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.waitKey(0) cv2.destroyAllWindows()?
基于深度學習的AI文字檢測法,可應用于復雜的自然場景中。
?
3、復雜場景:CTPN檢測法
CTPN(Detecting Text in Natural Image with Connectionist Text Proposal Network,基于連接預選框網絡的文本檢測)是基于卷積神經網絡和循環神經網絡的文本檢測方法,其基本做法是生成一系列適當尺寸的文本proposals(預選框)進行文本行的檢測,示意圖如下,具體的技術原理請見之前的文章(文章:大話文本檢測經典模型:CTPN)
CTPN檢測法能適應較為復雜的自然場景,是目前深度學習中作文字檢測的常用方法之一。CTPN的原作者提供該算法的源代碼(https://github.com/tianzhi0549/CTPN),是基于caffe深度學習框架的。大家對tensorflow可能會更加熟悉,于是有人在github上提供了tensorflow版本的CTPN程序(https://github.com/eragonruan/text-detection-ctpn),下面介紹如何使用該程序進行文字檢測。
(1)下載源代碼和模型
① 首先,將tensorflow版本的CTPN程序源代碼下載下來,可直接下載成zip壓縮包或者git克隆
git clone https://github.com/eragonruan/text-detection-ctpn.git② 接下來,進行編譯安裝,執行以下命令
cd utils/bboxchmod +x make.sh./make.sh③ 下載預訓練好的模型,下載地址為 https://pan.baidu.com/s/1BNHt_9fiqRPGmEXPaxaFXw ,下載后的壓縮文件為checkpoints_mlt.zip,新建目錄text-detection-ctpn,將解壓后將 checkpoints_mlt 文件夾放到text-detection-ctpn 目錄中
(2)CTPN文本檢測能力測試
將圖片放到data/demo目錄(默認有自帶測試圖片,如要檢測自己的圖片,則將自己的圖片放于data/demo目錄下),然后執行以下命令,就能使用CTPN進行文字檢測
python ./main/demo.py檢測后的結果存放于 data/res 目錄中,檢測結果由圖片和檢測框位置、置信度分數信息兩種文件組成,如下圖所示:
打開文件后,如下圖所示,可見已較好地將文字檢測出來:
再打開其它圖片,可看到檢測結果如下,檢測效果還不錯,如下圖:
(3)CTPN文本檢測能力封裝
通過對main/demo.py的程序稍微進行改造,就能將CTPN檢測能力封裝后提供給其它程序調用了,核心代碼如下:
# 基于 CTPN 的文字檢測方法 # 輸入:圖片 # 返回:文本框位置和置信度分數 def text_detect(image):with tf.get_default_graph().as_default():# 模型參數定義input_image = tf.placeholder(tf.float32, shape=[None, None, None, 3], name='input_image')input_im_info = tf.placeholder(tf.float32, shape=[None, 3], name='input_im_info')global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)bbox_pred, cls_pred, cls_prob = model.model(input_image)variable_averages = tf.train.ExponentialMovingAverage(0.997, global_step)saver = tf.train.Saver(variable_averages.variables_to_restore())with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 加載模型ckpt_state = tf.train.get_checkpoint_state(checkpoint_dir)model_path = os.path.join(checkpoint_dir, os.path.basename(ckpt_state.model_checkpoint_path))saver.restore(sess, model_path)# 預測文本框位置img = imageh, w, c = img.shapeim_info = np.array([h, w, c]).reshape([1, 3])bbox_pred_val, cls_prob_val = sess.run([bbox_pred, cls_prob],feed_dict={input_image: [img],input_im_info: im_info})textsegs, _ = proposal_layer(cls_prob_val, bbox_pred_val, im_info)scores = textsegs[:, 0]textsegs = textsegs[:, 1:5]textdetector = TextDetector(DETECT_MODE='H')boxes = textdetector.detect(textsegs, scores[:, np.newaxis], img.shape[:2])boxes = np.array(boxes, dtype=np.int)return boxes,scores從以上的檢測結果來看,CTPN檢測法在復雜的自然場景下具有較好的檢測效果。
?
4、復雜場景:SegLink檢測法
雖然CTPN在自然場景下的文字檢測效果還不錯,但CTPN的檢測效果是基于水平方向的,對于非水平的文本檢測效果并不好。在自然場景中,有很多的文本信息都是帶有一定的旋轉、傾斜角度的,例如街道上的廣告牌。接下來介紹的SegLink檢測法能夠實現對旋轉文本的多角度檢測,該模型主要是對通過Segment(切片)、Link(鏈接)實現對文本的檢測,示意圖如下,具體的技術原理請見之前的文章(文章:大話文本檢測經典模型:SegLink)
下面介紹如何使用SegLink來檢測文本。
(1)下載源代碼和模型
① 首先,在github上下載tensorflow版本的SegLink源代碼(https://github.com/dengdan/seglink),可直接下載成zip壓縮包或者git克隆
git clone https://github.com/dengdan/seglink.git② 下載pylib,下載路徑為https://github.com/dengdan/pylib/tree/f7f5c5503fbb3d9593e6ac3bbf0b8508f53ee1cf ,解壓后將src里面的util文件放到pylib目錄下面,然后添加到環境變量,在test_seglink.py的前面加上
import syssys.path.append('/data/PycharmProjects/tensorflow/ocr/seglink/util')或者在當前窗口執行以下命令,或在 /etc/profile,~/.bashrc 文件中添加以下命令
export PYTHONPATH=xx:$PYTHONPATH③ 下載預訓練好的模型(基于SynthText、IC15數據集),作者提供了兩個預訓練好的模型seglink-384(基于384x384的圖片)、seglink-512(基于512x512的圖片),下載地址為 https://pan.baidu.com/s/1slqaYux
④ 安裝依賴包
conda install -c cachemeorg setproctitle#或以下命令#pip install setproctitle⑤ 如果python是使用了python3的,則需要進行以下修改(使用python 2.x的,請忽略)
- 修改test_seglink.py第69行、第133行、第139行、第144行、第145行、第146行,print后面加上括號
- 修改pylib/util/io_.py,修改第11行,將import cPickle as pkl修改為import pickle as pkl
- 修改pylib/util/io_.py,修改第12行,將import commands改為import subprocess as commands
- 修改pylib/util/caffe_.py,修改第29行、第46行、第47行、第50行,在print后面加上括號
- 修改pylib/util/tf.py,修改第41行,將xrange改為range
- 修改config.py,修改第129行,將xrange改為range
- 修改tf_extended/seglink.py,修改第337行、第625行、第626行、第759行、第761行,將xrange改為range
- 修改test_seglink.py,第153行,將print(util.cmd.cmd(cmd))注釋掉
⑥ 修改./tf_extended/seglink.py,第808行,opencv3沒有cv.BoxPoints() 函數,修改如下:
# points = cv2.cv.BoxPoints(bbox)?? #opencv2.4.9points = cv2.boxPoints(bbox)?????? #opencv3.1.0?
(2)SegLink檢測文本測試(文本框坐標)
通過運行以下命令進行測試
./scripts/test.sh 0 GPU_ID CKPT_PATH DATASET_DIR
該命令由三個參數組成,第1個表示GPU,第2個表示模型路徑,第3個表示數據目錄。例如我們使用剛才下載的seglink-384預訓練模型,將要檢測的圖片放到指定的目錄后進行測試(可使用自己的圖片,或使用場景文字圖片數據集ICDAR2015進行測試,下載地址為http://rrc.cvc.uab.es/?ch=4&com=downloads),那么執行的腳本如下:
./scripts/test.sh 0 ./models/seglink-512/model.ckpt-217867? ./dataset/ICDAR2015 /ch4_test_images檢測后,生成了圖片檢測出來的文本框位置(8個坐標點),并存放在txt文件中,如下圖:
從這些檢測的文本框位置結果來看,并不顯性化,不知道在圖片中的實際檢測效果如何。
(3)SegLink檢測文本測試(結果顯性化)
為了能顯性化地展現出文本檢測 的圖片結果,可通過以下命令進行展示,格式為
python visualize_detection_result.py \--image=檢測的圖片所在目錄--det=經過test_seglink.py檢測輸出的文本框位置坐標--output=指定將文本框位置繪制到圖片上的輸出目錄該命令由三個參數組成,第一個表示輸入的圖像,第二個表示輸出檢測結果的文本信息,第三個表示輸出檢測結果的圖像
① 在visualize_detection_result.py添加環境變量
import syssys.path.append('/data/PycharmProjects/tensorflow/ocr/seglink/util')② 如果python是使用了python3的,則對visualize_detection_result.py第65行,print后面加上括號
?
對剛才輸出的檢測結果信息進行可視化展示,調用的命令如下(以ICDAR2015測試圖片集為例,如要使用自己的照片,請替換圖片目錄):
python visualize_detection_result.py \--image=./dataset/ICDAR2015/ ch4_test_images/ ?\--det=./models/seglink-512/model.ckpt-217867/test/icdar2015_test/model.ckpt-217867/seg_link_conf_th_0.800000_0.500000/txt \--output=./dataset/output執行后,可看到直接輸出了檢測后的結果圖片,如下圖:
打開其它圖片,檢測效果如下:
從上面的檢測結果來看,可較好地檢測出自然場景中的文字,特別是其中還有一些帶有一定傾斜或旋轉角度的文字,也能檢測出來。
(4)SegLink文本檢測能力封裝
為了方便在其它程序中調用SegLink的檢測能力,在test_seglink.py, visualize_detection_result.py代碼的基礎上進行封裝改造,就能將SegLink的檢測能力進行封裝提供給其它程序調用,核心代碼如下:
# 基于 SegLink 的文字檢測方法 # 輸入:圖片 # 返回:文本框位置 def text_detect(img):with tf.name_scope('eval'):with tf.variable_scope(tf.get_variable_scope(),reuse=True):# 模型參數image = tf.placeholder(dtype=tf.int32, shape=[None, None, 3])image_shape = tf.placeholder(dtype=tf.int32, shape=[3, ])# 預處理圖片processed_image, _, _, _, _ = ssd_vgg_preprocessing.preprocess_image(image, None, None, None, None,out_shape=config.image_shape,data_format=config.data_format,is_training=False)b_image = tf.expand_dims(processed_image, axis=0)b_shape = tf.expand_dims(image_shape, axis=0)# 預測文本框net = seglink_symbol.SegLinkNet(inputs=b_image, data_format=config.data_format)bboxes_pred = seglink.tf_seglink_to_bbox(net.seg_scores, net.link_scores,net.seg_offsets,image_shape=b_shape,seg_conf_threshold=config.seg_conf_threshold,link_conf_threshold=config.link_conf_threshold)sess_config = tf.ConfigProto(log_device_placement=False, allow_soft_placement=True)sess_config.gpu_options.allow_growth = Truesaver = tf.train.Saver()if util.io.is_dir(checkpoint_dir):checkpoint = util.tf.get_latest_ckpt(checkpoint_dir)else:checkpoint = checkpoint_dirwith tf.Session(config=sess_config) as sess:# 加載模型saver.restore(sess, checkpoint)# 預測文本框image_data = imgimage_bboxes = sess.run([bboxes_pred], feed_dict={image: image_data, image_shape: image_data.shape})bboxes = image_bboxes[0]return bboxes?
5、復雜場景:EAST檢測法
CTPN檢測法、SegLink檢測法是通過先預測proposals(預選框)、segment(切片),然后再回歸、合并等方式實現對文本的檢測,中間過程比較冗長。而接下來介紹的EAST檢測法,則將中間過程縮減為只有FCN(全卷積網絡)、NMS(非極大值抑制)兩個階段,而且輸出結果支持文本行、單詞的多個角度檢測,既高效準確,又能適應多種自然應用場景,如下圖所示,具體的技術原理請見之前的文章(文章:大話文本檢測經典模型:EAST)
下面介紹如何使用EAST來檢測文本。
(1)下載源代碼和模型
① 首先在github上下載EAST的源代碼(https://github.com/argman/EAST),可直接下載成zip壓縮包或者git克隆
git clone https://github.com/argman/EAST.git② 在百度網盤上下載預先訓練好的模型文件(基于ICDAR 2013、ICDAR 2015數據集訓練),下載地址為http://pan.baidu.com/s/1jHWDrYQ
③ 安裝shapely依賴包,執行以下命令
conda install shapely# 或執行以下命令# pip install shapely(2)EAST檢測文本測試(demo頁面)
進入EAST-master目錄,然后執行以下命令,可啟動demo頁面
python run_demo_server.py –checkpoint_path model/east_icdar2015_resnet_v1_50_rbox/頁面默認會加載輸出的結果圖片,首次加載時沒有結果輸出,所以會提示404,這不影響后面的使用。
執行命令后,即可啟動web服務,在瀏覽器中輸入http://localhost:8769,打開demo頁面,如下圖:
點擊“選擇文件”選擇待檢測的圖片,點擊“Submit”提交進行檢測,檢測后將在頁面上返回顯示檢測后的圖片,隨機挑選了其中三張圖片,檢測效果如下圖:
作者還很貼心地提供在在線的demo頁面,讓用戶可直接進行體驗使用,使用方式跟上面的demo頁面一樣,網站鏈接為http://east.zxytim.com/
(3)EAST檢測文本測試(批量檢測)
可通過命令行調用一批圖片批量檢測文本,還是以剛才的ICDAR圖片數據集進行檢測(如果要檢測自己的圖片,請替換數據目錄),命令如下:
python eval.py –test_data_path=/data/work/tensorflow/model/seglink/ICDAR2015/ch4_test_images/ --checkpoint_path=model/east_icdar2015_resnet_v1_50_rbox/ --output_dir=/tmp/east執行該命令后,將會批量讀取圖片進行檢測,并輸出檢測結果,包括圖片中檢測到的文本框位置、檢測結果框住文本后的圖片,如下圖所示:
從上圖也可以看出,EAST也能較好地檢測出自然場景的文字,對其中一些帶有旋轉角度的文字也可準確地檢測出來。
(4)EAST文本檢測能力封裝
為了方便將EAST提供給其它代碼調用,通過對eval.py進行修改,封裝EAST文本檢測的方法,可直接供其它代碼調用,代碼如下:
# 基于 EAST 的文字檢測方法 # 輸入:圖片 # 返回:文本框位置相關信息 def text_detect(img):# 模型路徑checkpoint_path='/data/PycharmProjects/tensorflow/ocr/east/model/east_icdar2015_resnet_v1_50_rbox/'# 模型參數input_images = tf.placeholder(tf.float32, shape=[None, None, None, 3], name='input_images')global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)f_score, f_geometry = model.model(input_images, is_training=False)variable_averages = tf.train.ExponentialMovingAverage(0.997, global_step)saver = tf.train.Saver(variable_averages.variables_to_restore())sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))# 加載模型ckpt_state = tf.train.get_checkpoint_state(checkpoint_path)model_path = os.path.join(checkpoint_path, os.path.basename(ckpt_state.model_checkpoint_path))saver.restore(sess, model_path)# 預測文本框im_resized, (ratio_h, ratio_w) = resize_image(img)score, geometry = sess.run([f_score, f_geometry],feed_dict={input_images: [im_resized[:,:,::-1]]})boxes,_ = detect(score_map=score, geo_map=geometry, timer=collections.OrderedDict([('net', 0),('restore', 0),('nms', 0)]))if boxes is not None:scores = boxes[:,8].reshape(-1)boxes = boxes[:, :8].reshape((-1, 4, 2))boxes[:, :, 0] /= ratio_wboxes[:, :, 1] /= ratio_htext_lines = []if boxes is not None:text_lines = []for box, score in zip(boxes, scores):box = sort_poly(box.astype(np.int32))if np.linalg.norm(box[0] - box[1]) < 5 or np.linalg.norm(box[3]-box[0]) < 5:continuetl = collections.OrderedDict(zip(['x0', 'y0', 'x1', 'y1', 'x2', 'y2', 'x3', 'y3'],map(float, box.flatten())))tl['score'] = float(score)text_lines.append(tl)ret = {'text_lines': text_lines,}return ret?
為方便介紹,以上CTPN、SegLink、EAST的文本檢測能力封裝時,將加載模型、文本框預測、圖片繪制文本框等代碼寫在一起,而在實際生產使用中,一般是將其分開,在后臺啟動OCR服務能力時預先加載模型,然后提供核心的文本檢測、識別能力,而輸出結果是否將文本框繪制到圖片上,則視具體需求場景而定
總結
以上是生活随笔為你收集整理的人工智能学习--文本检测实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器人学习--Gazebo学习--模型库
- 下一篇: 机器人学习--Turtelbot3学习-