Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Aniket025
GitHub Repository: Aniket025/Medical-Prescription-OCR
Path: blob/master/Model-3/ocr/page.py
426 views
1
# -*- coding: utf-8 -*-
2
"""
3
Crop background and transform perspective from the photo of page
4
"""
5
import numpy as np
6
import cv2
7
from .helpers import *
8
9
def detection(image):
10
""" Finding Page """
11
# Edge detection
12
imageEdges = edgesDet(image, 200, 250)
13
14
# Close gaps between edges (double page clouse => rectangle kernel)
15
closedEdges = cv2.morphologyEx(imageEdges,
16
cv2.MORPH_CLOSE,
17
np.ones((5, 11)))
18
# Countours
19
pageContour = findPageContours(closedEdges, resize(image))
20
# Recalculate to original scale
21
pageContour = pageContour.dot(ratio(image))
22
# Transform prespective
23
newImage = perspImageTransform(image, pageContour)
24
return newImage
25
26
27
def edgesDet(img, minVal, maxVal):
28
""" Preprocessing (gray, thresh, filter, border) + Canny edge detection """
29
img = cv2.cvtColor(resize(img), cv2.COLOR_BGR2GRAY)
30
31
img = cv2.bilateralFilter(img, 9, 75, 75)
32
img = cv2.adaptiveThreshold(img, 255,
33
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
34
cv2.THRESH_BINARY, 115, 4)
35
36
# Median blur replace center pixel by median of pixels under kelner
37
# => removes thin details
38
img = cv2.medianBlur(img, 11)
39
40
# Add black border - detection of border touching pages
41
img = cv2.copyMakeBorder(img, 5, 5, 5, 5,
42
cv2.BORDER_CONSTANT,
43
value=[0, 0, 0])
44
return cv2.Canny(img, minVal, maxVal)
45
46
47
def fourCornersSort(pts):
48
""" Sort corners: top-left, bot-left, bot-right, top-right"""
49
diff = np.diff(pts, axis=1)
50
summ = pts.sum(axis=1)
51
return np.array([pts[np.argmin(summ)],
52
pts[np.argmax(diff)],
53
pts[np.argmax(summ)],
54
pts[np.argmin(diff)]])
55
56
57
def contourOffset(cnt, offset):
58
""" Offset contour because of 5px border """
59
cnt += offset
60
cnt[cnt < 0] = 0
61
return cnt
62
63
64
def findPageContours(edges, img):
65
""" Finding corner points of page contour """
66
# Getting contours
67
im2, contours, hierarchy = cv2.findContours(edges,
68
cv2.RETR_TREE,
69
cv2.CHAIN_APPROX_SIMPLE)
70
71
# Finding biggest rectangle otherwise return original corners
72
height = edges.shape[0]
73
width = edges.shape[1]
74
MIN_COUNTOUR_AREA = height * width * 0.5
75
MAX_COUNTOUR_AREA = (width - 10) * (height - 10)
76
77
maxArea = MIN_COUNTOUR_AREA
78
pageContour = np.array([[0, 0],
79
[0, height],
80
[width, height],
81
[width, 0]])
82
83
for cnt in contours:
84
perimeter = cv2.arcLength(cnt, True)
85
approx = cv2.approxPolyDP(cnt, 0.03 * perimeter, True)
86
87
# Page has 4 corners and it is convex
88
if (len(approx) == 4 and
89
cv2.isContourConvex(approx) and
90
maxArea < cv2.contourArea(approx) < MAX_COUNTOUR_AREA):
91
92
maxArea = cv2.contourArea(approx)
93
pageContour = approx
94
95
# Sort corners and offset them
96
pageContour = fourCornersSort(pageContour[:, 0])
97
return contourOffset(pageContour, (-5, -5))
98
99
100
def perspImageTransform(img, sPoints):
101
""" Transform perspective from start points to target points """
102
# Euclidean distance - calculate maximum height and width
103
height = max(np.linalg.norm(sPoints[0] - sPoints[1]),
104
np.linalg.norm(sPoints[2] - sPoints[3]))
105
width = max(np.linalg.norm(sPoints[1] - sPoints[2]),
106
np.linalg.norm(sPoints[3] - sPoints[0]))
107
108
# Create target points
109
tPoints = np.array([[0, 0],
110
[0, height],
111
[width, height],
112
[width, 0]], np.float32)
113
114
# getPerspectiveTransform() needs float32
115
if sPoints.dtype != np.float32:
116
sPoints = sPoints.astype(np.float32)
117
118
M = cv2.getPerspectiveTransform(sPoints, tPoints)
119
return cv2.warpPerspective(img, M, (int(width), int(height)))
120