-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
232 lines (180 loc) · 6.73 KB
/
Copy pathmain.py
File metadata and controls
232 lines (180 loc) · 6.73 KB
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
import pigpio
import time
import cv2 as cv
import numpy as np
import threading
import random
from pygame import mixer
pi = pigpio.pi();
mixer.init()
sound1 = mixer.Sound('./wav/01.wav')
sound2 = mixer.Sound('./wav/02.wav')
sound3 = mixer.Sound('./wav/03.wav')
sound4 = mixer.Sound('./wav/04.wav')
sound5 = mixer.Sound('./wav/05.wav')
scream6 = mixer.Sound('./wav/06.wav')
scream7 = mixer.Sound('./wav/07.wav')
scream8 = mixer.Sound('./wav/08.wav')
scream9 = mixer.Sound('./wav/09.wav')
warnSound = mixer.Sound('./wav/10.wav')
sounds = [sound1, sound2, sound3, sound4, sound5]
screams = [scream6, scream7, scream8, scream9]
mouth_open = 34
mouth_closed = 150
servo1 = 12
servo2 = 13
motion_detected = False
exitProg = False
currentChannel = None
movement_persistent_counter = 0
# Minimum length of time where no motion is detected it should take
#(in program cycles) for the program to declare that there is no movement
MOVEMENT_DETECTED_PERSISTENCE = 50
def setupPins():
pi.write(servo1, 0);
pi.write(servo2, 0);
pi.set_PWM_frequency(servo1, 200);
pi.set_PWM_frequency(servo2, 200);
def open_mouth():
pi.set_PWM_dutycycle(servo1, mouth_open);
pi.set_PWM_dutycycle(servo2, mouth_open);
time.sleep(0.5)
pi.write(servo1, 0);
pi.write(servo2, 0);
def close_mouth():
pi.set_PWM_dutycycle(servo1, mouth_closed);
pi.set_PWM_dutycycle(servo2, mouth_closed);
time.sleep(0.5)
pi.write(servo1, 0);
pi.write(servo2, 0);
def waitForSoundFinish():
global currentChannel
while currentChannel.get_busy():
time.sleep(0.01)
currentChannel = None
def playSound(sound):
global currentChannel
if currentChannel == None :
currentChannel = sound.play()
x = threading.Thread(target=waitForSoundFinish)
x.start()
def motion():
global motion_detected
previous_detected = motion_detected
motion_detected = True;
print("motion")
if previous_detected == False:
playSound(warnSound)
else :
global screams
scream = random.choice(screams)
playSound(scream)
global movement_persistent_counter
movement_persistent_counter = MOVEMENT_DETECTED_PERSISTENCE
x = threading.Thread(target=open_mouth)
x.start();
def still():
global motion_detected
motion_detected = False
x = threading.Thread(target=close_mouth)
x.start()
print("No Movement Detected")
def cameraDetectionThread():
cap = cv.VideoCapture(0)
kernel = np.ones((5, 5))
first_frame = None
next_frame = None
delay_counter = 0
global movement_persistent_counter
#MOTION DETECTION
# Number of frames to pass before changing the frame to compare the current
# frame against
FRAMES_TO_PERSIST = 10
# Minimum boxed area for a detected motion to count as actual motion
# Use to filter out noise or small objects
MIN_SIZE_FOR_MOVEMENT = 2000
try:
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
transient_movement_flag = False
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Blur it to remove camera noise (reducing false positives)
gray = cv.GaussianBlur(gray, (21, 21), 0)
# If the first frame is nothing, initialise it
if first_frame is None: first_frame = gray
delay_counter += 1
# Otherwise, set the first frame to compare as the previous frame
# But only if the counter reaches the appriopriate value
# The delay is to allow relatively slow motions to be counted as large
# motions if they're spread out far enough
if delay_counter > FRAMES_TO_PERSIST:
delay_counter = 0
first_frame = next_frame
# Set the next frame to compare (the current frame)
next_frame = gray
# Compare the two frames, find the difference
frame_delta = cv.absdiff(first_frame, next_frame)
thresh = cv.threshold(frame_delta, 25, 255, cv.THRESH_BINARY)[1]
# Fill in holes via dilate(), and find contours of the thesholds
thresh = cv.dilate(thresh, None, iterations = 2)
cnts, _ = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# loop over the contours
for c in cnts:
# Save the coordinates of all found contours
(x, y, w, h) = cv.boundingRect(c)
# If the contour is too small, ignore it, otherwise, there's transient
# movement
if cv.contourArea(c) > MIN_SIZE_FOR_MOVEMENT:
transient_movement_flag = True
# Draw a rectangle around big enough movements
cv.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# The moment something moves momentarily, reset the persistent
# movement timer.
if transient_movement_flag == True:
motion()
# As long as there was a recent transient movement, say a movement
# was detected
if movement_persistent_counter > 0:
if movement_persistent_counter % 10 == 0 :
print( "Movement Detected " + str(movement_persistent_counter) )
movement_persistent_counter -= 1
if movement_persistent_counter == 0 :
still()
# Convert the frame_delta to color for splicing
frame_delta = cv.cvtColor(frame_delta, cv.COLOR_GRAY2BGR)
# Splice the two video frames together to make one long horizontal one
cv.imshow("frame", np.hstack((frame_delta, frame)))
if cv.waitKey(1) == ord('q'):
cap.release()
cv.destroyAllWindows()
global exitProg
exitProg = True
break
finally :
cap.release()
def exitProgram():
close_mouth()
global pi
pi.stop()
setupPins();
camThread = threading.Thread(target=cameraDetectionThread)
camThread.start()
while exitProg == False :
#pick random sounds and wait a random amount
#do not block motion detection
if motion_detected == False :
sleepAmount = random.uniform(2,8)
time.sleep(sleepAmount)
sound = random.choice(sounds)
playSound(sound)
else :
time.sleep(0.1)
exitProgram()