-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathscan.py
235 lines (188 loc) · 7.56 KB
/
scan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# USAGE
# python scan.py --image images/page.jpg
# import the necessary packages
from dataclasses import dataclass
from typing import Any
from pyimagesearch.transform import four_point_transform
from skimage.filters import threshold_local
import ar_markers as ar
import cv2
import imutils
import numpy as np
import pyzbar.pyzbar as pyzbar
def transform_image(image, paper_dims=(825, 1100), output_image="scannedImage.jpg"):
"""
:param image: image frame
:param paper_dims: dimensions of paper (in pixels) to scale scanned image to
:param output_image: name of file to write new image to
:return: returns transformation matrix
"""
# load the image and compute the ratio of the old height
# to the new height, clone it, and resize it
#ratio = image.shape[0] / 500.0
orig = image.copy()
#image = imutils.resize(image, height=500)
# convert the image to grayscale, blur it, and find edges
# in the image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 75, 200)
# show the original image and the edge detected image
print("STEP 1: Edge Detection")
#cv2.imshow("Image", image)
#cv2.imshow("Edged", edged)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
# find the contours in the edged image, keeping only the
# largest ones, and initialize the screen contour
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]
# loop over the contours
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
# if our approximated contour has four points, then we
# can assume that we have found our screen
if len(approx) == 4:
screenCnt = approx
break
# show the contour (outline) of the piece of paper
print("STEP 2: Find contours of paper")
#cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
#cv2.imshow("Outline", image)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
# apply the four point transform to obtain a top-down
# view of the original image
M, warped, dims = four_point_transform(orig, screenCnt.reshape(4, 2))
#find_markers(warped)
# convert the warped image to grayscale, then threshold it
# to give it that 'black and white' paper effect
# warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
# T = threshold_local(warped, 11, offset=10, method="gaussian")
# warped = (warped > T).astype("uint8") * 255
# show the original and scanned images
print("STEP 3: Apply perspective transform")
#cv2.imwrite(output_image, cv2.resize(warped, paper_dims))
#cv2.imshow("Scanned", cv2.resize(warped, paper_dims))
#cv2.waitKey(0)
print("Done transform initialization")
return M, dims
def find_markers(frame, output_image="markers.jpg"):
"""
:param image_file: filename to read from
:param output_image: name of file to write new images to
"""
markers = ar.detect_markers(frame)
print(frame.shape)
print(markers)
for marker in markers:
marker.highlite_marker(frame)
#cv2.imshow("Markers", frame)
#cv2.waitKey(0)
#cv2.imwrite(output_image, frame)
return markers
def transform_and_markers(image_file, paper_dims=(825, 1100), scanned_output="scanned.jpg",
final_output="scannedMarkers.jpg"):
"""
:param image_file: original image file to read from
:param paper_dims: paper dims to scale to (as used in transform image)
:param scanned_output: output file for image that is scanned but does not have ar markers detected yet
:param final_output: file name for image with ar markers detect
"""
transform_image(image_file, paper_dims, scanned_output)
find_markers(scanned_output, final_output)
def decode(im):
# Find barcodes and QR codes
decodedObjects = pyzbar.decode(im)
# Print results
for obj in decodedObjects:
print('Type : ', obj.type)
print('Data : ', obj.data, '\n')
return decodedObjects
# Display barcode and QR code location
def highlightCodes(im, decodedObjects):
# Loop over all decoded objects
for decodedObject in decodedObjects:
points = decodedObject.polygon
print(points)
# If the points do not form a quad, find convex hull
if len(points) > 4:
hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
hull = list(map(tuple, np.squeeze(hull)))
else:
hull = points
# Number of points in the convex hull
n = len(hull)
# Draw the convext hull
for j in range(0, n):
cv2.line(im, hull[j], hull[(j + 1) % n], (255, 0, 0), 3)
# Display results
return im
def find_qr_code(image_file, output_image='qr_code.jpg'):
im = cv2.imread(image_file)
decodedObjects = decode(im)
im2 = highlightCodes(im, decodedObjects)
cv2.imwrite(output_image, im2)
def transform_and_qr(image_file, paper_dims=(425, 550), scanned_output="scanned.jpg", final_output="scannedQR.jpg"):
transform_image(image_file, paper_dims, scanned_output)
find_qr_code(scanned_output, final_output)
@dataclass(frozen=True)
class TransformMetadata:
transformation_matrix: Any
im_dims: (int, int)
desired_dimensions: (int, int)
def transform_point(point: (int, int), transform_metadata: TransformMetadata):
"""
:param point: point in original plane
:param M: transformation matrix
:return: prints point that point is transformed to in new plane
"""
a = np.array([np.array([point], dtype='float32')])
cur = cv2.perspectiveTransform(a, transform_metadata.transformation_matrix)
x = cur.flatten()[0] * transform_metadata.desired_dimensions[0] / transform_metadata.im_dims[0]
y = cur.flatten()[1] * transform_metadata.desired_dimensions[1] / transform_metadata.im_dims[1]
return x, y
def get_transform_video(video_path, desired_dimensions=(8.5, 11.0)):
cap = cv2.VideoCapture(video_path)
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
cap.set(cv2.CAP_PROP_POS_FRAMES, video_length - 50)
ret, frame = cap.read()
#cv2.imshow("frame", frame)
#cv2.waitKey(0)
m, im_dims = transform_image(frame)
return TransformMetadata(m, im_dims, desired_dimensions)
#transform_and_markers("images/arFour.jpg")
'''
dig_markers = find_markers("images/dig_ar_sample.jpg")
transform_and_markers("images/ar_sample.jpg", (816, 1056))
unaltered_markers = find_markers("images/ar_sample.jpg")
my_mat, dims = transform_image("images/ar_sample.jpg", (816, 1056))
print(transform_point(unaltered_markers[0].center, dims, (816, 1056), my_mat))
'''
#transform_metadata = get_transform_video("test_images/test.mp4")
#print(transform_point((591, 263), transform_metadata))
# transform_point([0, 0], my_mat)
def test_angles(orig_img, video_path):
cap = cv2.VideoCapture(video_path)
true_markers = find_markers(orig_img)
gained = []
#print(true_markers[0].center)
i = 0
while(cap.isOpened()):
i += 1
ret, frame = cap.read()
if not ret:
break
if i % 30 == 0:
transform_and_markers(frame, (816, 1056))
#get_transform_video("images/test_vid.mp4")
#cap = cv2.VideoCapture("images/angles.mp4")
#ret, frame = cap.read()
#cv2.imshow('first', frame)
#cv2.waitKey(0)
#print(cap.get(cv2.CAP_PROP_FPS))
#transform_point([0, 0], my_mat)
#test_angles("images/ar_dig.png", "images/angles.mp4")