在本教程中,您將學(xué)習如何使用EAST文本檢測器在自然場(chǎng)景下檢測文本。
本教程的主要目的是教讀者利用OpenCV和EAST文本檢測器來(lái)檢測文本。
運行環(huán)境:
EAST文本檢測器需要OpenCV3.4.2或更高版本,有需要的讀者可以先安裝OpenCV。
主要內容:
教程第一部分分析為何在自然場(chǎng)景下進(jìn)行文本檢測的挑戰性是如此之高。
接下來(lái)簡(jiǎn)要探討EAST文本檢測器,為何使用,算法新在何處,并附上相關(guān)論文供讀者參考。
最后提供 Python + OpenCV文本檢測實(shí)現方式,供讀者在自己的應用中使用。
為何在自然場(chǎng)景下進(jìn)行文本檢測的挑戰性是如此之高
由于光照條件、圖片質(zhì)量以及目標非線(xiàn)性排列等因素的限制,自然場(chǎng)景下的文本檢測任務(wù)難度較大
受約束的受控環(huán)境中的文本檢測任務(wù)通??梢允褂没趩l(fā)式的方法來(lái)完成,比如利用梯度信息或文本通常被分成段落呈現,并且字符一般都是成直線(xiàn)排列等信息。
但自然場(chǎng)景下文本檢測則不同,而且更具挑戰性。
由于廉價(jià)數碼相機和智能手機的普及,我們需要高度關(guān)注圖像拍攝時(shí)的條件。Celine Mancas-Thillou和Bernard Gosselin在其2017年發(fā)表的優(yōu)秀論文《自然場(chǎng)景文本理解》中描述了的自然場(chǎng)景文本檢測面對的主要挑戰:
圖像/傳感器噪音:手持式相機的傳感器噪音通常要高于傳統掃描儀。此外,廉價(jià)相機通常會(huì )介入原始傳感器的像素以產(chǎn)生真實(shí)的顏色。
視角:自然場(chǎng)景中的文本存在不平行的觀(guān)測角度問(wèn)題,使文本更難以識別。
模糊:不受控制的環(huán)境下,文本往往會(huì )變模糊,尤其是如果最終用戶(hù)使用的智能手機的拍攝穩定性不足時(shí),問(wèn)題就更明顯。
照明條件:我們無(wú)法對自然場(chǎng)景圖像中的照明條件做出任何假設??赡茉诮咏诎档臈l件下,相機上的閃光燈可能會(huì )亮起,也可能在艷陽(yáng)高照的條件下,使整個(gè)圖像趨于飽和。
分辨率:每臺圖像捕捉設備都是不同的,可能存在分辨率過(guò)低的攝像機拍出的圖像。
非紙質(zhì)對象:大多數(但不是全部)紙張是不反光的。而自然場(chǎng)景中的文字可能是反光的,比如徽標,標志等。
非平面目標:想象文字印在瓶子上的情況,瓶子表面上的文本會(huì )扭曲和變形。雖然我們自己仍可以輕松地“檢測”并閱讀文本,但算法做起來(lái)就會(huì )很困難。我們需要能夠處理這種情況的用例。
處理條件未知:我們不能使用任何先驗信息來(lái)為算法提供關(guān)于文本所在位置的“線(xiàn)索”。
OpenCV’sEAST文本檢測器甚至可以識別模糊圖片中的文字
EAST深度學(xué)習文本檢測器
EAST文本檢測器全卷積網(wǎng)絡(luò )結構
EAST是一種基于深度學(xué)習的文本探測器,即高效、準確的場(chǎng)景文本檢測(Efficient and Accurate Scene Text detectionpipeline)。更重要的是,深度學(xué)習模型是端對端的,因此可能繞開(kāi)一般文本識別器用的計算成本高昂的子算法,比如候選對象聚合和詞匯分割等。
項目結構
首先使用Tree終端命令來(lái)瀏覽項目結構:
1$ tree --dirsfirst
2.
3├── images
4│ ├── car_wash.png
5│ ├── lebron_james.jpg
6│ └── sign.jpg
7├── frozen_east_text_detection.pb
8├── text_detection.py
9└── text_detection_video.py
10
111 directory, 6 files
在images/ 目錄下已有三張樣圖,讀者可以自己添加更多圖片。
我們使用兩個(gè).py 文件:
text_detection.py : 檢測靜態(tài)圖像中的文本
text_detection_video.py : 檢測網(wǎng)絡(luò )攝像頭或輸入圖像文件中的文本
兩個(gè)腳本都使用EAST模型 ( frozen_east_text_detection.pb )
注意事項
本文中介紹的實(shí)例基于OpenCV的官方C++實(shí)例,在轉換為Python的過(guò)程中可能會(huì )遇見(jiàn)一些問(wèn)題。
比如,Python中沒(méi)有Point2f 和 RotatedRect函數,所以不能完全再現C++環(huán)境下的實(shí)現。
其次,NMSBoxes函數不返回Python綁定的任何值,最終導致OpenCV報錯。 NMSBoxes函數可以在OpenCV3.4.2中使用,但我無(wú)法對其進(jìn)行詳盡的測試。
使用OpenCV實(shí)現文本檢測器的構建
在開(kāi)始之前,我想再次指出,您至少需要在系統上安裝OpenCV 3.4.2(或OpenCV 4)才能使用OpenCV的EAST文本檢測器,因此如果您還沒(méi)有安裝OpenCV 3.4.2或更高版本,請參閱后文的OpenCV安裝指南。
接下來(lái),安裝或升級你的系統中的imutils 。
1$ pip install --upgrade imutils
此時(shí),系統設置已經(jīng)完成,打開(kāi) text_detection.py ,輸入以下代碼:
1# import the necessary packages
2from imutils.object_detection import non_max_suppression
3import numpy as np
4import argparse
5import time
6import cv2
7
8# construct the argument parser and parse the arguments
9ap = argparse.ArgumentParser()
10ap.add_argument('-i', '--image', type=str,
11 help='path to input image')
12ap.add_argument('-east', '--east', type=str,
13 help='path to input EAST text detector')
14ap.add_argument('-c', '--min-confidence', type=float, default=0.5,
15 help='minimum probability required to inspect a region')
16ap.add_argument('-w', '--width', type=int, default=320,
17 help='resized image width (should be multiple of 32)')
18ap.add_argument('-e', '--height', type=int, default=320,
19 help='resized image height (should be multiple of 32)')
20args = vars(ap.parse_args())
首先,我們在第2-6行導入所需的包和模塊。注意,我們從imutils.object_detection導入NumPy,OpenCV和non_max_suppression實(shí)現。
然后我們繼續解析第9-20行的五個(gè)命令行參數:
--image:輸入圖像的路徑。
--east:EAST場(chǎng)景文本檢測器模型文件路徑。
--min-confidence:確定文本的概率閾值??蛇x,默認值= 0.5。
--width:調整后的圖像寬度 - 必須是32的倍數??蛇x,默認值= 320。
--height:調整后的圖像高度 - 必須是32的倍數??蛇x,默認值= 320。
重要提示:EAST文本要求輸入圖像尺寸為32的倍數,因此如果您選擇調整圖像的寬度和高度值,請確保這兩個(gè)值是32的倍數!
然后加載圖像并調整大?。?/span>
22# load the input image and grab the image dimensions
23image = cv2.imread(args['image'])
24orig = image.copy()
25(H, W) = image.shape[:2]
26
27# set the new width and height and then determine the ratio in change
28# for both the width and height
29(newW, newH) = (args['width'], args['height'])
30rW = W / float(newW)
31rH = H / float(newH)
32
33# resize the image and grab the new image dimensions
34image = cv2.resize(image, (newW, newH))
35(H, W) = image.shape[:2]
第23和24行加載并復制輸入圖像。
第30行和第31行確定原始圖像尺寸與新圖像尺寸的比率(基于為--width和--height提供的命令行參數)。
然后我們調整圖像大小,忽略縱橫比(第34行)。
為了使用OpenCV和EAST深度學(xué)習模型執行文本檢測,我們需要提取兩層的輸出特征映射:
37# define the two output layer names for the EAST detector model that
38# we are interested -- the first is the output probabilities and the
39# second can be used to derive the bounding box coordinates of text
40layerNames = [
41 'feature_fusion/Conv_7/Sigmoid',
42 'feature_fusion/concat_3']
我們在40-42行構建了layerNames的表:
第一層是我們的輸出sigmoid激活,它給出了包含文本或不包含文本的區域的概率。
第二層是表示圖像“幾何”的輸出要素圖。我們使用它來(lái)導出輸入圖像中文本的邊界框坐標。
加載OpenCV的EAST文本檢測器:
44# load the pre-trained EAST text detector
45print('[INFO] loading EAST text detector...')
46net = cv2.dnn.readNet(args['east'])
47
48# construct a blob from the image and then perform a forward pass of
49# the model to obtain the two output layer sets
50blob = cv2.dnn.blobFromImage(image, 1.0, (W, H),
51 (123.68, 116.78, 103.94), swapRB=True, crop=False)
52start = time.time()
53net.setInput(blob)
54(scores, geometry) = net.forward(layerNames)
55end = time.time()
56
57# show timing information on text prediction
58print('[INFO] text detection took {:.6f} seconds'.format(end - start))
我們使用cv2.dnn.readNet將神經(jīng)網(wǎng)絡(luò )加載到內存中,方法是將路徑傳遞給EAST檢測器作為第46行的參數。
然后我們通過(guò)將其轉換為第50行和第51行的blob來(lái)準備我們的圖像。要了解有關(guān)此步驟的更多信息,請參閱深度學(xué)習:OpenCV的blobFromImage如何工作。
要預測文本,我們可以簡(jiǎn)單地將blob設置為輸入并調用net.forward(第53和54行)。這些行被抓取時(shí)間戳包圍,以便我們可以在第58行打印經(jīng)過(guò)的時(shí)間。
通過(guò)將layerNames作為參數提供給net.forward,我們指示OpenCV返回我們感興趣的兩個(gè)特征映射:
輸出幾何圖用于導出輸入圖像中文本的邊界框坐標
類(lèi)似地,分數圖包含文本的給定區域的概率:
我們需要逐一循環(huán)這些值:
60# grab the number of rows and columns from the scores volume, then
61# initialize our set of bounding box rectangles and corresponding
62# confidence scores
63(numRows, numCols) = scores.shape[2:4]
64rects = []
65confidences = []
66
67# loop over the number of rows
68for y in range(0, numRows):
69 # extract the scores (probabilities), followed by the geometrical
70 # data used to derive potential bounding box coordinates that
71 # surround text
72 scoresData = scores[0, 0, y]
73 xData0 = geometry[0, 0, y]
74 xData1 = geometry[0, 1, y]
75 xData2 = geometry[0, 2, y]
76 xData3 = geometry[0, 3, y]
77 anglesData = geometry[0, 4, y]
我們首先抓取score的維度(第63行),然后初始化兩個(gè)列表:
rects:存儲文本區域的邊界框(x,y)坐標
置信度:存儲與每個(gè)邊界框相關(guān)的概率
我們稍后將對這些區域使用non-maximasuppression。
在第68行開(kāi)始循環(huán)。
第72-77行提取當前行的分數和幾何數據y。
接下來(lái),我們遍歷當前所選行的每個(gè)列索引:
79# loop over the number of columns
80 for x in range(0, numCols):
81 # if our score does not have sufficient probability, ignore it
82 if scoresData[x] <>'min_confidence']:
83 continue
84
85 # compute the offset factor as our resulting feature maps will
86 # be 4x smaller than the input image
87 (offsetX, offsetY) = (x * 4.0, y * 4.0)
88
89 # extract the rotation angle for the prediction and then
90 # compute the sin and cosine
91 angle = anglesData[x]
92 cos = np.cos(angle)
93 sin = np.sin(angle)
94
95 # use the geometry volume to derive the width and height of
96 # the bounding box
97 h = xData0[x] + xData2[x]
98 w = xData1[x] + xData3[x]
99
100 # compute both the starting and ending (x, y)-coordinates for
101 # the text prediction bounding box
102 endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
103 endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
104 startX = int(endX - w)
105 startY = int(endY - h)
106
107 # add the bounding box coordinates and probability score to
108 # our respective lists
109 rects.append((startX, startY, endX, endY))
110 confidences.append(scoresData[x])
對于每一行,我們開(kāi)始循環(huán)第80行的列。
我們需要通過(guò)忽略概率不高的區域來(lái)過(guò)濾弱文本檢測(第82行和第83行)。
當圖像通過(guò)網(wǎng)絡(luò )時(shí),EAST文本檢測器自然地減少了體積大小——我們的體積實(shí)際上比輸入圖像小4倍,所以我們乘以4,使坐標回到原始圖像。
我已經(jīng)包含了如何在第91-93行提取角度數據;然而,正如我在前一節中提到的,不能像在C++中那樣構造一個(gè)旋轉的邊界框——如果你想要處理這個(gè)任務(wù),那么從第91行角度開(kāi)始將是你的第一步。
第97-105行派生出文本區域的邊框坐標。
然后我們分別更新rects和confi數據庫列表(第109行和第110行)。
最后一步是將非最大值抑制應用于我們的邊界框以抑制弱重疊邊界框,然后顯示結果文本預測:
112# apply non-maxima suppression to suppress weak, overlapping bounding
113# boxes
114boxes = non_max_suppression(np.array(rects), probs=confidences)
115
116# loop over the bounding boxes
117for (startX, startY, endX, endY) in boxes:
118 # scale the bounding box coordinates based on the respective
119 # ratios
120 startX = int(startX * rW)
121 startY = int(startY * rH)
122 endX = int(endX * rW)
123 endY = int(endY * rH)
124
125 # draw the bounding box on the image
126 cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 255, 0), 2)
127
128# show the output image
129cv2.imshow('Text Detection', orig)
130cv2.waitKey(0)
正如我在上一節中提到的,我無(wú)法在我的OpenCV 4安裝(cv2.dnn.NMSBoxes)中使用非最大值抑制,因為Python綁定沒(méi)有返回值,最終導致OpenCV出錯。我無(wú)法完全在OpenCV 3.4.2中進(jìn)行測試,因此它可以在v3.4.2中運行。
相反,我使用了imutils包中提供的非最大值抑制實(shí)現(第114行)。結果仍然很好;但是,我無(wú)法將我的輸出與NMSBoxes函數進(jìn)行比較,看它們是否相同。
第117-126行循環(huán)遍歷邊界框,將坐標縮放到原始圖像尺寸,并將輸出繪制到orig圖像。直到按下一個(gè)按鍵為止,原始圖像將一直顯示(129-130行)。
最后一個(gè)實(shí)驗需要注意的是,我們的兩個(gè)嵌套for循環(huán)用于循環(huán)第68-110行上的分數和幾何體(geometry volume),這是一個(gè)很好的例子,說(shuō)明你可以利用Cython極大地加快pipeline的速度。我已經(jīng)用OpenCV和Python演示了Cython在快速優(yōu)化“for”像素循環(huán)中的強大功能。
OpenCV文本檢測器結果
在終端可以執行一下命令(注意兩個(gè)命令行參數):
1$ python text_detection.py --image images/lebron_james.jpg \
2 --east frozen_east_text_detection.pb
3[INFO] loading EAST text detector...
4[INFO] text detection took 0.142082 seconds
結果應該如下圖所示:
文本檢測器成功識別出籃球巨星勒布朗·詹姆斯球衣上的文字
詹姆斯身上有三個(gè)文本區域。
現在讓我們嘗試檢測業(yè)務(wù)標志的文本:
1$ python text_detection.py --image images/car_wash.png \
2 --east frozen_east_text_detection.pb
3[INFO] loading EAST text detector...
4[INFO] text detection took 0.142295 seconds
使用EAST文本檢測器很容易識別出路邊洗車(chē)店的招牌文字
最后,我們將嘗試一個(gè)路標:
1$ python text_detection.py --image images/sign.jpg \
2 --east frozen_east_text_detection.pb
3[INFO] loading EAST text detector...
4[INFO] text detection took 0.141675 seconds

基于Python和OpenCV的場(chǎng)景文本檢測器和EAST文本檢測器成功檢測出西班牙語(yǔ)的停車(chē)指示路牌
該場(chǎng)景中包含一個(gè)西班牙的停車(chē)標志?!癆LTO”可以準確的被OpenCV和EAST識別出來(lái)。
如你所知,EAST非常精確,且相對較快,平均每張圖片耗時(shí)約0.14秒。
OpenCV在視頻中進(jìn)行文本檢測
我們可以基于上述工作,進(jìn)一步使用OpenCV在視頻中進(jìn)行文本檢測。
開(kāi)啟text_detection_video.py,然后插入如下代碼:
1# import the necessary packages
2from imutils.video import VideoStream
3from imutils.video import FPS
4from imutils.object_detection import non_max_suppression
5import numpy as np
6import argparse
7import imutils
8import time
9import cv2
首先,我們導入一些包。我們將使用VideoStream訪(fǎng)問(wèn)網(wǎng)絡(luò )攝像頭并用FPS來(lái)為這個(gè)腳本測試每秒幀數。其他內容與前一節相同。
為方便起見(jiàn),定義一個(gè)新函數來(lái)為我們的預測函數進(jìn)行解碼 - 它將被重用于每個(gè)幀并使循環(huán)更清晰:
11def decode_predictions(scores, geometry):
12 # grab the number of rows and columns from the scores volume, then
13 # initialize our set of bounding box rectangles and corresponding
14 # confidence scores
15 (numRows, numCols) = scores.shape[2:4]
16 rects = []
17 confidences = []
18
19 # loop over the number of rows
20 for y in range(0, numRows):
21 # extract the scores (probabilities), followed by the
22 # geometrical data used to derive potential bounding box
23 # coordinates that surround text
24 scoresData = scores[0, 0, y]
25 xData0 = geometry[0, 0, y]
26 xData1 = geometry[0, 1, y]
27 xData2 = geometry[0, 2, y]
28 xData3 = geometry[0, 3, y]
29 anglesData = geometry[0, 4, y]
30
31 # loop over the number of columns
32 for x in range(0, numCols):
33 # if our score does not have sufficient probability,
34 # ignore it
35 if scoresData[x] <>'min_confidence']:
36 continue
37
38 # compute the offset factor as our resulting feature
39 # maps will be 4x smaller than the input image
40 (offsetX, offsetY) = (x * 4.0, y * 4.0)
41
42 # extract the rotation angle for the prediction and
43 # then compute the sin and cosine
44 angle = anglesData[x]
45 cos = np.cos(angle)
46 sin = np.sin(angle)
47
48 # use the geometry volume to derive the width and height
49 # of the bounding box
50 h = xData0[x] + xData2[x]
51 w = xData1[x] + xData3[x]
52
53 # compute both the starting and ending (x, y)-coordinates
54 # for the text prediction bounding box
55 endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
56 endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
57 startX = int(endX - w)
58 startY = int(endY - h)
59
60 # add the bounding box coordinates and probability score
61 # to our respective lists
62 rects.append((startX, startY, endX, endY))
63 confidences.append(scoresData[x])
64
65 # return a tuple of the bounding boxes and associated confidences
66 return (rects, confidences)
在第11行,我們定義decode_prediction函數。該函數用于提取:
文本區域的邊界框坐標;
文本區域檢測的概率。
這個(gè)專(zhuān)用函數將使代碼更易于閱讀和管理。
讓我們來(lái)解析命令行參數:
68# construct the argument parser and parse the arguments
69ap = argparse.ArgumentParser()
70ap.add_argument('-east', '--east', type=str, required=True,
71 help='path to input EAST text detector')
72ap.add_argument('-v', '--video', type=str,
73 help='path to optinal input video file')
74ap.add_argument('-c', '--min-confidence', type=float, default=0.5,
75 help='minimum probability required to inspect a region')
76ap.add_argument('-w', '--width', type=int, default=320,
77 help='resized image width (should be multiple of 32)')
78ap.add_argument('-e', '--height', type=int, default=320,
79 help='resized image height (should be multiple of 32)')
80args = vars(ap.parse_args())
69-80行代碼中命令行參數解析:
--east:EAST場(chǎng)景文本檢測器模型文件路徑。
--video:輸入視頻的路徑(可選)。如果提供了視頻路徑,那么網(wǎng)絡(luò )攝像頭將不會(huì )被使用。
--Min-confidence:確定文本的概率閾值(可選)。default=0.5。
--width:調整圖像寬度(必須是32的倍數,可選)。default=320。
--Height:調整圖像高度(必須是32的倍數,可選)。default=320。
與上一節中僅使用圖像的腳本(就命令行參數而言)的不同之處在于,用視頻替換了圖像參數。
接下里,我們將進(jìn)行重要的初始化工作:
82# initialize the original frame dimensions, new frame dimensions,
83# and ratio between the dimensions
84(W, H) = (None, None)
85(newW, newH) = (args['width'], args['height'])
86(rW, rH) = (None, None)
87
88# define the two output layer names for the EAST detector model that
89# we are interested -- the first is the output probabilities and the
90# second can be used to derive the bounding box coordinates of text
91layerNames = [
92 'feature_fusion/Conv_7/Sigmoid',
93 'feature_fusion/concat_3']
94
95# load the pre-trained EAST text detector
96print('[INFO] loading EAST text detector...')
97net = cv2.dnn.readNet(args['east'])
第84-86行上的高度、寬度和比率初始化將允許我們稍后適當地縮放邊界框。
我們定義了輸出層的名稱(chēng),并在第91-97行加載了預先訓練好的EAST文本檢測器。
下面的代碼設置了我們的視頻流和每秒幀數計數器:
99# if a video path was not supplied, grab the reference to the web cam
100if not args.get('video', False):
101 print('[INFO] starting video stream...')
102 vs = VideoStream(src=0).start()
103 time.sleep(1.0)
104
105# otherwise, grab a reference to the video file
106else:
107 vs = cv2.VideoCapture(args['video'])
108
109# start the FPS throughput estimator
110fps = FPS().start()
我們的視頻流設置為:
一個(gè)攝像頭(100-103行)
或一個(gè)視頻文件(106-107行)
我們在第110行初始化每秒幀計數器,并開(kāi)始循環(huán)傳入幀:
112# loop over frames from the video stream
113while True:
114 # grab the current frame, then handle if we are using a
115 # VideoStream or VideoCapture object
116 frame = vs.read()
117 frame = frame[1] if args.get('video', False) else frame
118
119 # check to see if we have reached the end of the stream
120 if frame is None:
121 break
122
123 # resize the frame, maintaining the aspect ratio
124 frame = imutils.resize(frame, width=1000)
125 orig = frame.copy()
126
127 # if our frame dimensions are None, we still need to compute the
128 # ratio of old frame dimensions to new frame dimensions
129 if W is None or H is None:
130 (H, W) = frame.shape[:2]
131 rW = W / float(newW)
132 rH = H / float(newH)
133
134 # resize the frame, this time ignoring aspect ratio
135 frame = cv2.resize(frame, (newW, newH))
我們從113行開(kāi)始在視頻/攝像頭框架上進(jìn)行循環(huán)。
我們的框架調整了大小,保持了縱橫比(第124行)。從129-132行中獲取維度并計算比例。然后我們再次調整幀的大小(必須是32的倍數),這一次忽略了長(cháng)寬比,因為我們已經(jīng)存儲了用于安全維護(safe keeping)的比率(第135行)。
推理和繪制文本區域邊框發(fā)生在以下幾行:
137# construct a blob from the frame and then perform a forward pass
138 # of the model to obtain the two output layer sets
139 blob = cv2.dnn.blobFromImage(frame, 1.0, (newW, newH),
140 (123.68, 116.78, 103.94), swapRB=True, crop=False)
141 net.setInput(blob)
142 (scores, geometry) = net.forward(layerNames)
143
144 # decode the predictions, then apply non-maxima suppression to
145 # suppress weak, overlapping bounding boxes
146 (rects, confidences) = decode_predictions(scores, geometry)
147 boxes = non_max_suppression(np.array(rects), probs=confidences)
148
149 # loop over the bounding boxes
150 for (startX, startY, endX, endY) in boxes:
151 # scale the bounding box coordinates based on the respective
152 # ratios
153 startX = int(startX * rW)
154 startY = int(startY * rH)
155 endX = int(endX * rW)
156 endY = int(endY * rH)
157
158 # draw the bounding box on the frame
159 cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 255, 0), 2)
在這一代碼塊中:
創(chuàng )建一個(gè)blob并通過(guò)網(wǎng)絡(luò )傳遞文本區域(第139-142行);
解碼預測并應用NMS(第146行和第147行)。使用之前在這個(gè)腳本中定義的decode_forecasts函數和imutils non_max_suppression函數。
循環(huán)包圍框并在框架上繪制它們(150-159行)。這涉及到按前面收集的比率縮放方框。
而后我們將關(guān)閉框架處理循環(huán)以及腳本本身:
161# update the FPS counter
162 fps.update()
163
164 # show the output frame
165 cv2.imshow('Text Detection', orig)
166 key = cv2.waitKey(1) & 0xFF
167
168 # if the `q` key was pressed, break from the loop
169 if key == ord('q'):
170 break
171
172# stop the timer and display FPS information
173fps.stop()
174print('[INFO] elasped time: {:.2f}'.format(fps.elapsed()))
175print('[INFO] approx. FPS: {:.2f}'.format(fps.fps()))
176
177# if we are using a webcam, release the pointer
178if not args.get('video', False):
179 vs.stop()
180
181# otherwise, release the file pointer
182else:
183 vs.release()
184
185# close all windows
186cv2.destroyAllWindows()
我們在循環(huán)的每次迭代中更新fps計數器(第162行),以便當我們跳出循環(huán)時(shí)可以計算和顯示計時(shí)(第173-175行)。
我們在第165行顯示了EAST文本檢測的輸出,并處理按鍵(第166-170行)。如果“q”鍵代表“退出”,并被按下,我們將跳出循環(huán),繼續清理和釋放指針。
視頻文本檢測結果
要使用OpenCV對視頻進(jìn)行文本檢測,請務(wù)必點(diǎn)擊本文底部“下載內容”鏈接獲取相應資源。
而后,打開(kāi)終端并執行以下命令(將會(huì )開(kāi)啟攝像頭,因為通過(guò)命令行參數不提供- -video):
1$ python text_detection_video.py --east frozen_east_text_detection.pb
2[INFO] loading EAST text detector...
3[INFO] starting video stream...
4[INFO] elasped time: 59.76
5[INFO] approx. FPS: 8.85
代碼下載及原文鏈接:
https://www.pyimagesearch.com/2018/08/20/opencv-text-detection-east-text-detector/
聯(lián)系客服