django init
This commit is contained in:
parent
1e26ffe8a6
commit
e4395ccc4f
2
.gitignore
vendored
2
.gitignore
vendored
@ -0,0 +1,2 @@
|
|||||||
|
.gitignore
|
||||||
|
/node_modules
|
0
bibrecognition/bibrecognition/__init__.py
Normal file
0
bibrecognition/bibrecognition/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
BIN
bibrecognition/bibrecognition/__pycache__/urls.cpython-37.pyc
Normal file
BIN
bibrecognition/bibrecognition/__pycache__/urls.cpython-37.pyc
Normal file
Binary file not shown.
BIN
bibrecognition/bibrecognition/__pycache__/wsgi.cpython-37.pyc
Normal file
BIN
bibrecognition/bibrecognition/__pycache__/wsgi.cpython-37.pyc
Normal file
Binary file not shown.
16
bibrecognition/bibrecognition/asgi.py
Normal file
16
bibrecognition/bibrecognition/asgi.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for bibrecognition project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bibrecognition.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
120
bibrecognition/bibrecognition/settings.py
Normal file
120
bibrecognition/bibrecognition/settings.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
"""
|
||||||
|
Django settings for bibrecognition project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 3.0.2.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.0/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/3.0/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = '__q^s(i^&vo%n&ybt0i&nk09(=9mt6^9#!l(v3_gjtfca^bp-8'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'bibrecognition.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'bibrecognition.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_L10N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/3.0/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
21
bibrecognition/bibrecognition/urls.py
Normal file
21
bibrecognition/bibrecognition/urls.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"""bibrecognition URL Configuration
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/3.0/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
]
|
16
bibrecognition/bibrecognition/wsgi.py
Normal file
16
bibrecognition/bibrecognition/wsgi.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for bibrecognition project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bibrecognition.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
0
bibrecognition/db.sqlite3
Normal file
0
bibrecognition/db.sqlite3
Normal file
21
bibrecognition/manage.py
Normal file
21
bibrecognition/manage.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bibrecognition.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
322
main.py
322
main.py
@ -3,172 +3,188 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import Image
|
import Image
|
||||||
from cv2 import cv2
|
from cv2 import cv2
|
||||||
import pytesseract
|
import pytesseract
|
||||||
|
import argparse
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from imutils.object_detection import non_max_suppression
|
from imutils.object_detection import non_max_suppression
|
||||||
|
|
||||||
|
|
||||||
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
|
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
|
||||||
faceCascade = cv2.CascadeClassifier('haarcascade/haarcascade_frontalface_default.xml')
|
faceCascade = cv2.CascadeClassifier(
|
||||||
|
'haarcascade/haarcascade_frontalface_default.xml')
|
||||||
def findText(img, i):
|
|
||||||
# @TODO
|
|
||||||
# make ROI from found texts and return a array of imgs. Then try recon text by pytesseract
|
|
||||||
image = img
|
|
||||||
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) = (320, 320)
|
|
||||||
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('./EAST/frozen_east_text_detection.pb')
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
net.setInput(blob)
|
|
||||||
(scores, geometry) = net.forward(layerNames)
|
|
||||||
|
|
||||||
# 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] < 0.5:
|
|
||||||
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_"+str(i), orig)
|
|
||||||
|
|
||||||
|
|
||||||
# MAIN PROGRAM
|
def decode_predictions(scores, geometry):
|
||||||
|
# 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 = []
|
||||||
|
|
||||||
image = cv2.imread('imgs/bib_01.jpg')
|
# loop over the number of rows
|
||||||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
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]
|
||||||
|
|
||||||
faces = faceCascade.detectMultiScale(
|
# loop over the number of columns
|
||||||
gray,
|
for x in range(0, numCols):
|
||||||
scaleFactor=1.1,
|
# if our score does not have sufficient probability,
|
||||||
minNeighbors=5,
|
# ignore it
|
||||||
minSize=(30, 30)
|
if scoresData[x] < args["min_confidence"]:
|
||||||
)
|
continue
|
||||||
|
|
||||||
faceNumber = len(faces)
|
# compute the offset factor as our resulting feature
|
||||||
# print('znaleziono '+str(faceNumber)+' twarzy \n')
|
# maps will be 4x smaller than the input image
|
||||||
ROI = [0] * faceNumber
|
(offsetX, offsetY) = (x * 4.0, y * 4.0)
|
||||||
|
|
||||||
for (x, y, w, h) in faces:
|
# extract the rotation angle for the prediction and
|
||||||
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
|
# then compute the sin and cosine
|
||||||
|
angle = anglesData[x]
|
||||||
|
cos = np.cos(angle)
|
||||||
|
sin = np.sin(angle)
|
||||||
|
|
||||||
i = 0
|
# use the geometry volume to derive the width and height
|
||||||
for (x, y, w, h) in faces:
|
# of the bounding box
|
||||||
x = int( x - (3*w/4) )
|
h = xData0[x] + xData2[x]
|
||||||
y = int(y + 1.5*h)
|
w = xData1[x] + xData3[x]
|
||||||
w = int(2.5*w)
|
|
||||||
h = int(3.5*h)
|
|
||||||
if x < 0:
|
|
||||||
x = 1
|
|
||||||
# cv2.rectangle(image, (x, y), (x+w, y+h), (0, 0, 255), 2)
|
|
||||||
# print('y = '+str(y)+', y+h = '+str(y+h)+', x = '+str(x)+', x+w = '+str(x+w)+'\n')
|
|
||||||
crop_img = image[y:y+h, x:x+w]
|
|
||||||
ROI[i] = crop_img
|
|
||||||
# cv2.imshow("cropped_"+str(i), crop_img[i])
|
|
||||||
i = i + 1
|
|
||||||
|
|
||||||
i = 0
|
# compute both the starting and ending (x, y)-coordinates
|
||||||
for x in ROI:
|
# for the text prediction bounding box
|
||||||
findText(x, i)
|
endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
|
||||||
# x = cv2.cvtColor(x,cv2.COLOR_BGR2GRAY)
|
endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
|
||||||
# kernel = np.ones((1,1), np.uint8)
|
startX = int(endX - w)
|
||||||
# x = cv2.dilate(x, kernel, iterations = 1)
|
startY = int(endY - h)
|
||||||
# x = cv2.erode(x, kernel, iterations=1)
|
|
||||||
# x = cv2.adaptiveThreshold(x, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
|
|
||||||
|
|
||||||
# cv2.imshow("Text Detection_"+str(i), orig)
|
# add the bounding box coordinates and probability score
|
||||||
# cv2.imshow("cropped_"+str(i), x)
|
# to our respective lists
|
||||||
# cv2.imwrite("cropped_"+str(i)+"_thres.jpg", x)
|
rects.append((startX, startY, endX, endY))
|
||||||
# result = pytesseract.image_to_string(Image.open("cropped_"+str(i)+"_thres.jpg"))
|
confidences.append(scoresData[x])
|
||||||
# print(result)
|
|
||||||
i = i + 1
|
|
||||||
|
|
||||||
cv2.imshow("Faces found", image)
|
# return a tuple of the bounding boxes and associated confidences
|
||||||
cv2.waitKey()
|
return (rects, confidences)
|
||||||
|
|
||||||
#print(pytesseract.image_to_string(Image.open('imgs/bib_01.jpg')))
|
|
||||||
|
# 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="nearest multiple of 32 for resized width")
|
||||||
|
ap.add_argument("-e", "--height", type=int, default=320,
|
||||||
|
help="nearest multiple of 32 for resized height")
|
||||||
|
ap.add_argument("-p", "--padding", type=float, default=0.0,
|
||||||
|
help="amount of padding to add to each border of ROI")
|
||||||
|
args = vars(ap.parse_args())
|
||||||
|
|
||||||
|
# load the input image and grab the image dimensions
|
||||||
|
image = cv2.imread(args["image"])
|
||||||
|
orig = image.copy()
|
||||||
|
(origH, origW) = 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 = origW / float(newW)
|
||||||
|
rH = origH / 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)
|
||||||
|
net.setInput(blob)
|
||||||
|
(scores, geometry) = net.forward(layerNames)
|
||||||
|
|
||||||
|
# decode the predictions, then apply non-maxima suppression to
|
||||||
|
# suppress weak, overlapping bounding boxes
|
||||||
|
(rects, confidences) = decode_predictions(scores, geometry)
|
||||||
|
boxes = non_max_suppression(np.array(rects), probs=confidences)
|
||||||
|
|
||||||
|
# initialize the list of results
|
||||||
|
results = []
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# in order to obtain a better OCR of the text we can potentially
|
||||||
|
# apply a bit of padding surrounding the bounding box -- here we
|
||||||
|
# are computing the deltas in both the x and y directions
|
||||||
|
dX = int((endX - startX) * args["padding"])
|
||||||
|
dY = int((endY - startY) * args["padding"])
|
||||||
|
|
||||||
|
# apply padding to each side of the bounding box, respectively
|
||||||
|
startX = max(0, startX - dX)
|
||||||
|
startY = max(0, startY - dY)
|
||||||
|
endX = min(origW, endX + (dX * 2))
|
||||||
|
endY = min(origH, endY + (dY * 2))
|
||||||
|
|
||||||
|
# extract the actual padded ROI
|
||||||
|
roi = orig[startY:endY, startX:endX]
|
||||||
|
|
||||||
|
# in order to apply Tesseract v4 to OCR text we must supply
|
||||||
|
# (1) a language, (2) an OEM flag of 4, indicating that the we
|
||||||
|
# wish to use the LSTM neural net model for OCR, and finally
|
||||||
|
# (3) an OEM value, in this case, 7 which implies that we are
|
||||||
|
# treating the ROI as a single line of text
|
||||||
|
config = ("-l eng --oem 1 --psm 7")
|
||||||
|
text = pytesseract.image_to_string(roi, config=config)
|
||||||
|
|
||||||
|
# add the bounding box coordinates and OCR'd text to the list
|
||||||
|
# of results
|
||||||
|
results.append(((startX, startY, endX, endY), text))
|
||||||
|
|
||||||
|
# sort the results bounding box coordinates from top to bottom
|
||||||
|
results = sorted(results, key=lambda r: r[0][1])
|
||||||
|
|
||||||
|
# loop over the results
|
||||||
|
for ((startX, startY, endX, endY), text) in results:
|
||||||
|
# display the text OCR'd by Tesseract
|
||||||
|
print("OCR TEXT")
|
||||||
|
print("========")
|
||||||
|
print("{}\n".format(text))
|
||||||
|
|
||||||
|
# strip out non-ASCII text so we can draw the text on the image
|
||||||
|
# using OpenCV, then draw the text and a bounding box surrounding
|
||||||
|
# the text region of the input image
|
||||||
|
text = "".join([c if ord(c) < 128 else "" for c in text]).strip()
|
||||||
|
output = orig.copy()
|
||||||
|
cv2.rectangle(output, (startX, startY), (endX, endY),
|
||||||
|
(0, 0, 255), 2)
|
||||||
|
cv2.putText(output, text, (startX, startY - 20),
|
||||||
|
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)
|
||||||
|
|
||||||
|
# show the output image
|
||||||
|
cv2.imshow("Text Detection", output)
|
||||||
|
cv2.waitKey(0)
|
||||||
|
3634
package-lock.json
generated
Normal file
3634
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user