-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathplate-live.py
179 lines (143 loc) · 5.93 KB
/
plate-live.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
#!/usr/bin/env python3
"""
Scan IP Camera stream for license plates.
If plate seen, save image, position, time/date
Ignore repeated detection of a plate if it is not moving
J.Beale 7-JAN-2020
"""
import cv2
import sys
import json
import math
from datetime import datetime
from openalpr import Alpr
import regex as re # $ pip install regex
WINDOW_NAME = 'openalpr'
CFILE="/home/john/CAM8/openalpr.conf"
fullInterval = 1.0 # seconds between full-frame saves
bRatioThresh = 1.3 # brightness step-change ratio threshold
mThresh = 5 # motion vector threshold (pixels)
fPrefix = "Pt_"
fPrefix2 = "D8_"
CNAME = 'DH8' # camera name for output file
UTYPE = "rtsp://"
UPASS = "user:password"
IPADD = "192.168.1.28"
PORT = "554"
# URL2 = "/cam/realmonitor?channel=1&subtype=0" # Dahua IP Camera, MAIN channel
URL2 = "/cam/realmonitor?channel=1&subtype=2" # Dahua IP Cameras, subchannel B
vidname= UTYPE + UPASS + "@" + IPADD + ":" + PORT + URL2
def main():
lastSaveTime = datetime.now() # initialize last-image-save-time to prog. start time
alpr = Alpr("us", CFILE, "/usr/share/openalpr/runtime_data/")
if not alpr.is_loaded():
print('Error loading OpenALPR')
sys.exit(1)
alpr.set_top_n(1)
cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_AUTOSIZE)
cv2.setWindowTitle(WINDOW_NAME, 'OpenALPR video test')
# =========== now have a loaded instance of alpr; do stuff here
cam = cv2.VideoCapture(vidname) # open a video file or stream
img_w = int(cam.get(3)) # input image width
img_h = int(cam.get(4)) # input image height
print ("Image w,h = %d %d" % (img_w, img_h))
prlist = re.compile(r"\L<plates>",
plates=['7WXY20Z', '7WXYZ02', 'WXY202', '7WXY202', 'WXY20Z', 'WXYZ02',
'WXYZ0Z', '7WXY2Q2'])
save = True # always save the first image, for reference
lastPstring = "" # haven't seen any plates yet
lastGarageDoor = True # assume we're starting with door closed
lastBright = 0.0 # average brightness of previous frame
lastXcent = 0
lastYcent = 0
mvec=0
# ================== MAIN LOOP =====================================
while ( True ):
ret, img = cam.read()
if not ret:
print('VidepCapture.read() failed. Exiting...')
sys.exit(1)
ttnow = datetime.now() # local real time when this frame was received
avgbright = img.mean() # average of all pixels (float)
# print(avgbright)
cv2.imshow(WINDOW_NAME, img) # show camera image
results = alpr.recognize_ndarray(img)
# print(".",end='')
# print(results)
jsonRes = (json.dumps(results, indent=2))
jsonS = json.loads(jsonRes)
rlist = results['results']
pcount = len(rlist) # how many plates we have found
# print("Length = %d" % len(rlist) )
if (pcount < 1):
# print("No plates found, bright: %5.2f" % avgbright )
pstring = "" # null plate (nothing found)
else:
for i, plate in enumerate(rlist):
cor1x = int(jsonS["results"][0]["coordinates"][0]["x"])
cor1y = int(jsonS["results"][0]["coordinates"][0]["y"])
cor2x = int(jsonS["results"][0]["coordinates"][2]["x"])
cor2y = int(jsonS["results"][0]["coordinates"][2]["y"])
xcent = (cor1x + cor2x) / 2
ycent = (cor1y + cor2y) / 2
dx = xcent - lastXcent
dy = ycent - lastYcent
mvec = math.sqrt(dx*dx + dy*dy) # motion vector in pixels
pcrop = img[cor1y:cor2y, cor1x:cor2x] # crop of image containing plate
cv2.imshow("plate", pcrop) # show just the plate
p = plate['candidates'][0]
pstring = p['plate'].upper() # characters on license plate
# if (pstring != "7WXY202") and (pstring != "WXY202"):
if prlist.search(pstring): # is this the usual garage-door view?
garageDoor = True
else:
garageDoor = False
# here: pstring holds the LP characters, or ""
bRatio = (avgbright+0.01) / (lastBright+0.01)
if (bRatio < 1.0):
bRatio = 1/bRatio
if (bRatio > bRatioThresh):
bChange = True
else:
bChange = False
if (mvec > mThresh):
motion = True
else:
motion = False
tnows = ttnow.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] # time to msec
if bChange :
print("Brightness change: %5.3f , %s" % (avgbright,tnows))
# save = not garageDoor # save image if normal garage-door view not seen
save = motion # save image if motion of plate detected
if (pstring==""):
save = False # but don't save image if no plate
if (pstring != lastPstring):
print("# Nothing: brightness %5.3f , %s" % (avgbright,tnows))
if save :
print("%d,%d , %d,%d , " % (cor1x,img_h-cor1y,cor2x,img_h-cor2y),end='')
print('%s , %5.2f , %5.2f , %5.2f , %s' % (pstring, p['confidence'], avgbright, mvec, tnows ))
tnowf = ttnow.strftime("%Y-%m-%d_%H%M%S_%f")[:-3] # filename time to msec
fname3 = fPrefix + tnowf + "_" + str(i) + ".jpg" # full-size image
# cv.imwrite(fname3, img) # save current image
cv2.imwrite(fname3, pcrop) # save current image
# print("saved: " + fname3)
tSince = (ttnow - lastSaveTime).total_seconds()
# print("seconds since last save = %5.3f" % tSince)
if (tSince > fullInterval):
fname4 = fPrefix2 + tnowf + "_" + str(i) + ".jpg" # full-size image
cv2.imwrite(fname4, img) # save full image
lastSaveTime = ttnow
save = False
lastXcent = xcent
lastYcent = ycent
lastPstring = pstring # remember what we saw before
lastGarageDoor = garageDoor
lastBright = avgbright # remember last avg brightness
c = cv2.waitKey(1) & 0xFF # get input char if any
if c == ord('q'):
sys.exit(1)
# close up and quit
alpr.unload()
# ======================================================
if __name__ == "__main__":
main()