상세 컨텐츠

본문 제목

EAST

Coding/Image

by linguana 2021. 6. 3. 15:28

본문

Title: EAST: An Efficient and Accurate Scene Text Detector (2017)

Authors: Xinyu Zhou, Cong Yao, He Wen, Yuzhi Wang, Shuchang Zhou, Weiran He, and Jiajun Liang

초 록

  풍경 텍스트 탐지(STD)를 위한 기존의 접근법은 이미 여러 벤치마크에서 유망한 성능을 보여주고 있다. 하지만, 기존의 접근법들은 종종 도전적인 상황에 직면했을 때 (심지어 심층 신경망 모델을 갖추고 있을 때도) 부족한 부분을 보이는데 이는 전반적인 성능이 다중의 처리 단계와 요소들의 상호작용에 의해 결정되기 때문이다. 본 논문에서 우리는 자연적인 풍경에서 텍스트를 빠르고 정확하게 탐지하는 간단하면서도 강력한 파이프라인을 제안한다. 이 파이프라인은 임의의 기울기와 사각형 모양을 가진 단어 혹은 텍스트 라인을 단 하나의 신경망으로 전체 이미지에서 직접 예측하여 (예를 들면 candidate aggregation 혹은 word partitioning 같은) 중간의 불필요한 단계를 삭제하였다. 우리 파이프라인의 심플함은 로스 함수와 신경망 구조를 설계하는 데 집중할 수 있도록 해준다. ICDAR 2015, COCO-Text, MSRA-TD500을 포함하는 표준적인 데이터셋에 대한 실험은 제안된 알고리즘이 정확도와 효율성에서 모두 SOTA 기법들의 성능을 유의미하게 뛰어넘고 있음을 보여준다. ICDAR 2015 데이터셋에서 제안된 알고리즘은 720 픽셀 크기의 이미지에 대해서 13 FPS의 속도로 F-score 0.7820을 달성하였다.

 

 


Simple Implementation:

** 단순히 저장된 가중치 가져와서 inference만 한 코드임, train 불가 **

src link: (1) OpenCV Text Detection (EAST text detector) - PyImageSearch (2) Deep Learning based Text Detection Using OpenCV (C++/Python) (learnopencv.com)

2018년 8월 20일 포스팅

EAST 모델 특징
(1) 720 픽셀 크기의 이미지에 대해서 실시간 실행 가능(13 FPS)하고
(2) ICDAR2015에서 F-score 0.7820 성능 수행.

OpenCV 3.4.2 혹은 OpenCV 4 이상이어야 함.


EAST 모델 아키텍쳐

모델 아키텍쳐


왜 풍경 텍스트 탐지는 어려운 걸까?

  제한되고 조절된 환경에서 텍스트 탐지하는 것은 전형적으로 지식(heuristic)에 기반한 접근법으로 가능하다. (gradient에 대한 정보를 이용하거나, 텍스트가 일반적으로 문단으로 묶이거나 글자가 하나의 수평선에 나타난다는 사실을 이용하는 방법 등) 이러한 지식 기반 접근법의 사례로는 여권에서 글자를 추출하는 것이 있다. 다음 링크 참고: Detecting machine-readable zones in passport images - PyImageSearch

  하지만 자연적인 풍경 텍스트를 탐지하는 것은 다른 영역이고, 훨씬 더 도전적인 과제이다.

1. 파일 구조

<그림 1> 파일 구조는 이렇게 만들자

참고: text_detection_video.py는 따로 정리하지 않았다. 원하면 src link에서 확인하자.


2. weight 저장된 pb 다운로드 받기

https://www.dropbox.com/s/r2ingd0l3zt8hxs/frozen_east_text_detection.tar.gz?dl=1

cmd에서 다음과 같이 tar.gz 압축파일을 해제하자.

tar -xvf [filename.tar] -C [PATH]

압축을 해제하면 .pb 파일이 지정한 경로에 만들어진다.


3. text_detection.py

파이썬 코드는 아래에 정리하였다.

cmd 실행 예시를 따라 한 번 실행해보자.

더보기
# import the necessary packages
from imutils.object_detection import non_max_suppression
import numpy as np
import argparse
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str,
	help="path to input image")
ap.add_argument("-east", "--east", type=str,
	help="path to input EAST text detector")
ap.add_argument("-c", "--min-confidence", type=float, default=0.5,
	help="minimum probability required to inspect a region")
ap.add_argument("-w", "--width", type=int, default=320,
	help="resized image width (should be multiple of 32)")
ap.add_argument("-e", "--height", type=int, default=320,
	help="resized image height (should be multiple of 32)")
args = vars(ap.parse_args())

# load the input image and grab the image dimensions
image = cv2.imread(args["image"])
orig = image.copy()
(H, W) = image.shape[:2]

# set the new width and height and then determine the ratio in change
# for both the width and height
(newW, newH) = (args["width"], args["height"])
rW = W / float(newW)
rH = H / float(newH)

# resize the image and grab the new image dimensions
image = cv2.resize(image, (newW, newH))
(H, W) = image.shape[:2]

# define the two output layer names for the EAST detector model that
# we are interested -- the first is the output probabilities and the
# second can be used to derive the bounding box coordinates of text
layerNames = [
	"feature_fusion/Conv_7/Sigmoid",
	"feature_fusion/concat_3"]

# load the pre-trained EAST text detector
print("[INFO] loading EAST text detector...")
net = cv2.dnn.readNet(args["east"])

# construct a blob from the image and then perform a forward pass of
# the model to obtain the two output layer sets
blob = cv2.dnn.blobFromImage(image, 1.0, (W, H),
	(123.68, 116.78, 103.94), swapRB=True, crop=False)
start = time.time()
net.setInput(blob)
(scores, geometry) = net.forward(layerNames)
end = time.time()

# show timing information on text prediction
print("[INFO] text detection took {:.6f} seconds".format(end - start))

# grab the number of rows and columns from the scores volume, then
# initialize our set of bounding box rectangles and corresponding
# confidence scores
(numRows, numCols) = scores.shape[2:4]
rects = []
confidences = []

# loop over the number of rows
for y in range(0, numRows):
	# extract the scores (probabilities), followed by the geometrical
	# data used to derive potential bounding box coordinates that
	# surround text
	scoresData = scores[0, 0, y]
	xData0 = geometry[0, 0, y]
	xData1 = geometry[0, 1, y]
	xData2 = geometry[0, 2, y]
	xData3 = geometry[0, 3, y]
	anglesData = geometry[0, 4, y]

	# loop over the number of columns
	for x in range(0, numCols):
		# if our score does not have sufficient probability, ignore it
		if scoresData[x] < args["min_confidence"]:
			continue

		# compute the offset factor as our resulting feature maps will
		# be 4x smaller than the input image
		(offsetX, offsetY) = (x * 4.0, y * 4.0)

		# extract the rotation angle for the prediction and then
		# compute the sin and cosine
		angle = anglesData[x]
		cos = np.cos(angle)
		sin = np.sin(angle)

		# use the geometry volume to derive the width and height of
		# the bounding box
		h = xData0[x] + xData2[x]
		w = xData1[x] + xData3[x]

		# compute both the starting and ending (x, y)-coordinates for
		# the text prediction bounding box
		endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
		endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
		startX = int(endX - w)
		startY = int(endY - h)

		# add the bounding box coordinates and probability score to
		# our respective lists
		rects.append((startX, startY, endX, endY))
		confidences.append(scoresData[x])

# apply non-maxima suppression to suppress weak, overlapping bounding
# boxes
boxes = non_max_suppression(np.array(rects), probs=confidences)

# loop over the bounding boxes
for (startX, startY, endX, endY) in boxes:
	# scale the bounding box coordinates based on the respective
	# ratios
	startX = int(startX * rW)
	startY = int(startY * rH)
	endX = int(endX * rW)
	endY = int(endY * rH)

	# draw the bounding box on the image
	cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 255, 0), 2)

# show the output image
cv2.imshow("Text Detection", orig)
cv2.waitKey(0)


"""
cmd 실행 예시
$ python text_detection.py --image images/lebron_james.jpg \
	--east frozen_east_text_detection.pb
[INFO] loading EAST text detector...
[INFO] text detection took 0.142082 seconds
"""

4. 실행 결과

<그림 2> 실행 결과

결과가 그렇게 좋지 않다. 아마도 한국어에 훈련된 pb 가중치가 아니어서 그런 것 같다.


Reference

Code:

[1] owseaman/Text-Detection-in-an-Image: Text Detection in an Image using Pytesseract and EAST Text Detection (github.com) Good: simple code (only 1 python file); Bad: cannot figure out the model, can only use for inference

[2] kurapan/EAST: Implementation of EAST scene text detector in Keras (github.com) Good: 데이터셋(ICDAR2015)도 다운로드 받을 수 있고, 모델 구조도 알 수 있음

[3] REAL-Time-Scene-Text-Recognition/text_detection.py at master · themechanicalcoder/REAL-Time-Scene-Text-Recognition (github.com)

Paper:

paperswithcode: EAST: An Efficient and Accurate Scene Text Detector | Papers With Code

Original paper: 

EAST.pdf
3.83MB

 

 

 

 

'Coding > Image' 카테고리의 다른 글

ICDAR 2019  (0) 2021.06.08
[DMQA Open Seminar] Scene Text Detection and Recognition  (0) 2021.06.08
Real-Time STD with DB  (0) 2021.05.31
PP-OCR  (0) 2021.05.31
Multimodal Information Bottleneck (Image-to-Speech)  (0) 2021.05.28

관련글 더보기