├── app
├── run.py
├── labels.txt
├── __init__.py
├── deer
│ ├── 2.jpg
│ ├── thumbnail
│ │ └── 2.jpg
│ └── .thumbnail
│ │ └── 2.jpg
├── views.pyc
├── __init__.pyc
├── static
│ ├── logo.png
│ ├── images
│ │ └── 2.jpg
│ ├── style.css
│ └── stylesheets
│ │ └── style.css
├── __pycache__
│ ├── harpu.cpython-35.pyc
│ ├── views.cpython-35.pyc
│ ├── views.cpython-38.pyc
│ ├── __init__.cpython-35.pyc
│ ├── __init__.cpython-38.pyc
│ ├── process.cpython-35.pyc
│ └── process.cpython-38.pyc
├── templates
│ ├── photo.html
│ ├── layout.html
│ ├── photo_dir.html
│ ├── confirm.html
│ ├── template.html
│ ├── name.html
│ ├── timer.html
│ ├── deleteall.html
│ ├── restore.html
│ ├── mode.html
│ ├── species.html
│ ├── index.html
│ └── recentactivity.html
├── demomode.py
├── process.py
├── harpu.py
└── views.py
├── run.py
├── params.json
├── README.md
├── boarbuster.py
└── harpu.py
/app/run.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | app.run(debug=True)
3 |
--------------------------------------------------------------------------------
/run.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | app.run(host='', port=80)
3 |
--------------------------------------------------------------------------------
/app/labels.txt:
--------------------------------------------------------------------------------
1 | sheep
2 | hog
3 | turkey
4 | whitetail deer
5 | aoudad
6 | black bear
7 | raccoon
8 |
--------------------------------------------------------------------------------
/app/__init__.py:
--------------------------------------------------------------------------------
1 | from flask import Flask
2 |
3 | app = Flask(__name__)
4 | from app import views
5 |
6 |
--------------------------------------------------------------------------------
/app/deer/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/deer/2.jpg
--------------------------------------------------------------------------------
/app/views.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/views.pyc
--------------------------------------------------------------------------------
/app/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__init__.pyc
--------------------------------------------------------------------------------
/app/static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/static/logo.png
--------------------------------------------------------------------------------
/params.json:
--------------------------------------------------------------------------------
1 | {"name": "Wifi", "timer": "12", "never_feed": ["Whitetail Deer", "Hogs"], "feed": ["Whitetail Deer", "Hogs"]}
--------------------------------------------------------------------------------
/app/deer/thumbnail/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/deer/thumbnail/2.jpg
--------------------------------------------------------------------------------
/app/static/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/static/images/2.jpg
--------------------------------------------------------------------------------
/app/deer/.thumbnail/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/deer/.thumbnail/2.jpg
--------------------------------------------------------------------------------
/app/__pycache__/harpu.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/harpu.cpython-35.pyc
--------------------------------------------------------------------------------
/app/__pycache__/views.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/views.cpython-35.pyc
--------------------------------------------------------------------------------
/app/__pycache__/views.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/views.cpython-38.pyc
--------------------------------------------------------------------------------
/app/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/app/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/app/__pycache__/process.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/process.cpython-35.pyc
--------------------------------------------------------------------------------
/app/__pycache__/process.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Supernova1024/PhotoView-Raspberrypi-Flask-master/HEAD/app/__pycache__/process.cpython-38.pyc
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Flask Web Control System for Raspberry Pi 4
2 |
3 | This is the real-time animal detection algorithm. It is restoring the images and information to mysql database.
--------------------------------------------------------------------------------
/app/templates/photo.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block body %}
3 |
4 | DELETE
5 | {% endblock %}
6 |
--------------------------------------------------------------------------------
/app/demomode.py:
--------------------------------------------------------------------------------
1 | import os
2 | from shutil import copyfile
3 |
4 |
5 | os.system('sudo pkill -9 -f harpu.py')
6 | copyfile('/home/pi/demo/demo.py', '/home/pi/harpu.py')
7 | os.system('lxterminal -e python /home/pi/harpu.py')
8 | demomessage = "Machine Now in Demo Mode"
9 | print ("Done")
10 |
--------------------------------------------------------------------------------
/app/templates/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
 }})
6 |
Your Images
7 |
8 |
9 | {% for message in get_flashed_messages() %}
10 |
{{ message }}
11 | {% endfor %}
12 | {% block body %}{% endblock %}
13 |
14 |
--------------------------------------------------------------------------------
/app/templates/photo_dir.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block body %}
3 |
4 |
15 |
 }})
16 |
Recent Activity
17 | {% if dates %}
18 |
21 | {% endif %}
22 | {% if not dates %}
23 |
There is no record
24 | {% else %}
25 | {% for date in dates %}
26 |
27 |
28 |
29 | | {{ date }} |
30 | {% for zone in timezones %}
31 | {{ zone }} |
32 | {% endfor %}
33 |
34 |
35 |
36 | {% for animal in animals %}
37 |
38 | | {{ animal }} |
39 | {% for timezone in timezones %}
40 | {{ message[date][animal][timezone] }} |
41 | {% endfor%}
42 |
43 | {% endfor %}
44 |
45 |
46 | {% endfor %}
47 | {% endif %}
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/static/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | .button{
2 | background-color: #6b8e23;
3 | border: none;
4 | color: white;
5 | padding: 15px 20px;
6 | text-align: center;
7 | text-decoration: none;
8 | display: inline-block;
9 | font-size: 16px;
10 | width: 100%;
11 | }
12 |
13 | .message{
14 | color: #FF6600;
15 | text-align: center;
16 | font-size: 16px;
17 | }
18 |
19 | .heading{
20 | padding-top: 20px;
21 | font: 24px arial, sans-serif;
22 | text-align: center;
23 | color: #808080;
24 | }
25 |
26 | hr {
27 | display: block;
28 | margin-left: auto;
29 | margin-right: auto;
30 | border-style: inset;
31 | border-width: 1px;
32 | color: #D3D3D3;
33 | }
34 |
35 | body {
36 | color: #000000;
37 | font: 16px arial, sans-serif;
38 | text-align: center;
39 | }
40 |
41 |
42 | /* -------------------- Page Styles (not required) */
43 | div { margin: 20px; }
44 |
45 | button.submit, a.submit {
46 | background-color: #4CAF50; /* Green */
47 | border: none;
48 | color: white;
49 | padding: 15px 32px;
50 | text-align: center;
51 | text-decoration: none;
52 | display: inline-block;
53 | font-size: 16px;
54 | }
55 |
56 | form#form2 input[type="text"], form#form3 input[type="number"] {
57 | padding: 10px;
58 | border: solid 1px gainsboro;
59 | -webkit-transition: box-shadow 0.3s, border 0.3s;
60 | -moz-transition: box-shadow 0.3s, border 0.3s;
61 | -o-transition: box-shadow 0.3s, border 0.3s;
62 | transition: box-shadow 0.3s, border 0.3s;
63 | display: block;
64 | margin: 0;
65 | width: 200px;
66 | font-family: "Open Sans", sans-serif;
67 | font-size: 18px;
68 | -webkit-appearance: none;
69 | -moz-appearance: none;
70 | appearance: none;
71 | -webkit-box-shadow: none;
72 | -moz-box-shadow: none;
73 | box-shadow: none;
74 | -webkit-border-radius: none;
75 | -moz-border-radius: none;
76 | -ms-border-radius: none;
77 | -o-border-radius: none;
78 | border-radius: none;
79 | }
80 | form#form2 input[type="text"]:focus, form#form2 input[type="text"].focus,
81 | form#form3 input[type="number"]:focus, form#form3 input[type="number"].focus {
82 | border: solid 1px #707070;
83 | -webkit-box-shadow: 0 0 5px 1px #969696;
84 | -moz-box-shadow: 0 0 5px 1px #969696;
85 | box-shadow: 0 0 5px 1px #969696;
86 | }
87 | form#form3 input[type="number"] {
88 | text-align: right;
89 | }
90 |
91 | div.recent_div {
92 | margin-top: 2%;
93 | }
94 | div.recent_title {
95 | font-size: 20px;
96 | }
97 | table th {
98 | background-color: #D5D5D5;
99 | }
100 | table tbody tr{
101 | background-color: #EB2620;
102 | }
103 | table tbody tr:first-child{
104 | background-color: #68D643;
105 | }
106 | table thead tr th {
107 | border-bottom: 1px solid black;
108 | }
109 | table thead tr th:first-child {
110 | background-color: #929292;
111 | }
112 | table tbody tr td:first-child {
113 | border-right: 1px solid black;
114 | }
--------------------------------------------------------------------------------
/boarbuster.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import numpy as np
3 | import tensorflow as tf
4 | import os
5 | os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
6 | import time
7 | import json
8 | import RPi.GPIO as GPIO
9 | import glob
10 |
11 | #Set Up GPIO
12 | GPIO.setwarnings(False)
13 | GPIO.setmode(GPIO.BOARD)
14 |
15 | #Save Photos of Trapped Animals
16 | files = glob.glob("trapped/photo*.jpg")
17 | if files == []:
18 | print "No Previous Image Found: Resetting Image Counter"
19 | hognum = 1000000
20 | else:
21 | files = sorted(files)
22 | hognum = int(os.path.basename(files[-1])[5:-4])
23 | hognum += 1
24 | print "Previous Image Found and Counted - Current Image Number is:"
25 | print hognum
26 |
27 | #Save Photos of Detected Motion
28 | files2 = glob.glob("detected/photo*.jpg")
29 | if files2 == []:
30 | print "No Previous Image Found: Resetting Image Counter"
31 | num = 1000000
32 | else:
33 | files2 = sorted(files2)
34 | num = int(os.path.basename(files2[-1])[5:-4])
35 | num += 1
36 | print "Previous Image Found and Counted - Current Image Number is:"
37 | print num
38 |
39 | #Load Parameters
40 | params = {}
41 | with open('/home/pi/params.json') as data_file:
42 | params = json.load(data_file)
43 |
44 | #print ('=== params ===', params)
45 |
46 | if (params['starttime']) == 'Small':
47 | numcts = 5
48 | if (params['starttime']) == 'Medium':
49 | numcts = 10
50 | if (params['starttime']) == 'Large':
51 | numcts = 15
52 |
53 | # switch camera to video streaming
54 | #cap = cv2.VideoCapture("bbvid1.mpg")
55 | cap = cv2.VideoCapture(0)
56 | a = []
57 | model_dir = ''
58 | #bgsMOG = cv2.createBackgroundSubtractorMOG2(detectShadows = False)
59 | bgsMOG = cv2.createBackgroundSubtractorMOG2(history = 300, varThreshold = 50, detectShadows = False)
60 |
61 | label_lines = [line.rstrip() for line
62 | in tf.gfile.GFile("labels.txt")]
63 |
64 | def create_graph():
65 |
66 | # Creates graph from saved graph_def.pb.
67 | with tf.gfile.FastGFile(os.path.join(
68 | model_dir, 'graph.pb'), 'rb') as f:
69 | graph_def = tf.GraphDef()
70 | graph_def.ParseFromString(f.read())
71 | _ = tf.import_graph_def(graph_def, name='')
72 |
73 | # Download and create graph
74 | create_graph()
75 |
76 | def detect(frame):
77 | with tf.Session() as sess:
78 | softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
79 | cv2.imwrite("current_frame.jpg",frame)
80 |
81 | image_data = tf.gfile.FastGFile("./current_frame.jpg", 'rb').read()
82 | predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
83 |
84 | predictions = np.squeeze(predictions)
85 |
86 | # change n_pred for more predictions
87 | n_pred=1
88 | top_k = predictions.argsort()[-n_pred:][::-1]
89 | for node_id in top_k:
90 | human_string_n = label_lines[node_id]
91 | score = predictions[node_id]
92 | print ('The animal is {} and score is {}'.format(human_string_n, score))
93 | result = 0
94 | if human_string_n in ('Hog') and score > .55:
95 | result = Hog
96 | return result
97 | hog = 0
98 |
99 | # Take Sample Image to Send to Wifi Interface to check camera placement
100 | sample = 0
101 | framecount = 0
102 | while sample == 0:
103 | ret, frame = cap.read()
104 | framecount += 1
105 | if framecount > 400 and sample < 1:
106 | cv2.imwrite("deer/sample.jpg", frame)
107 | print "Sample Image Collected"
108 | sample += 1
109 |
110 | # Motion Detection Portion
111 | while hog < 1:
112 | print "delay start timer 2 min"
113 | GPIO.setup(37, GPIO.OUT)
114 | GPIO.cleanup(37)
115 | time.sleep(10)
116 | GPIO.setup(37, GPIO.OUT)
117 | print "starting control system"
118 | hog = 0
119 | fct = 0
120 | timeout = time.time() + 60
121 | #cap = cv2.VideoCapture(0)
122 | time.sleep(2)
123 | while (hog < 1) and (time.time() < timeout):
124 | ret, frame = cap.read()
125 | fct += 1
126 | if ret and fct > 300:
127 | fgmask = bgsMOG.apply(frame)
128 | # To find the contours of the objects
129 | _, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
130 | #cv2.drawContours(frame,contours,-1,(0,255,0),cv2.cv.CV_FILLED,32)
131 | try: hierarchy = hierarchy[0]
132 | except: hierarchy = []
133 | a = []
134 | for contour, hier in zip(contours, hierarchy):
135 | if (hog < 2) and (time.time() < timeout):
136 | (x, y, w, h) = cv2.boundingRect(contour)
137 | if w > 30 and h > 30:
138 | width = str(w)
139 | height = str(h)
140 | dimension = width + ", " + height
141 | dimension1 = dimension
142 | cv2.rectangle(frame, (x, y), (x + w, y + h), (147, 20, 255), 1)
143 | cv2.putText(frame, dimension1, (x, y + h + 12), 0, 0.5, (147, 20, 255))
144 | (x, y, w, h) = cv2.boundingRect(contour)
145 |
146 | x1 = w / 2
147 | y1 = h / 2
148 | cx = x + x1
149 | cy = y + y1
150 | a.append([cx, cy])
151 | area = cv2.contourArea(contour)
152 | if (len(a) >= numcts) and (hog < 1):
153 |
154 | cv2.imwrite("detected/photo%s.jpg" % num, frame)
155 | num += 1
156 | if detect(frame) == 'Hog':
157 | print ('Alarm! A group of Hogs was detected. please trigger the trap!')
158 | cv2.imwrite("trapped/photo%s.jpg" % hognum, frame)
159 | hognum +=1
160 | #hog += 1
161 | break
162 | else:
163 | break
164 | #cv2.imshow('BGS', fgmask)
165 | cv2.imshow('Ori+Bounding Box', frame)
166 | key = cv2.waitKey(100)
167 | if key == ord('q'):
168 | break
169 | #cap.release()
170 | cv2.destroyAllWindows()
171 | if hog >= 2:
172 | GPIO.setup(13, GPIO.OUT)
173 | print "Releasing Trap"
174 | time.sleep(3)
175 | GPIO.cleanup(13)
176 | print "Done"
177 |
--------------------------------------------------------------------------------
/app/harpu.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import re
3 | import sys
4 | import cv2
5 | import numpy as np
6 | import tensorflow as tf
7 | import time
8 | import os
9 | os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
10 | from threading import Thread
11 | import RPi.GPIO as GPIO
12 | import glob
13 | from PIL import Image
14 | from shutil import copyfile
15 |
16 | # Threaded class for performance improvement
17 | class VideoStream:
18 | def __init__(self, src=0):
19 | self.stream = cv2.VideoCapture(src)
20 | (self.grabbed, self.frame) = self.stream.read()
21 | self.stopped = False
22 |
23 | def start(self):
24 | Thread(target=self.update, args=()).start()
25 | return self
26 |
27 | def update(self):
28 | while True:
29 | if self.stopped:
30 | self.stream.release()
31 | return
32 |
33 | (self.grabbed, self.frame) = self.stream.read()
34 |
35 | def read(self):
36 | # Return the latest frame
37 | return self.frame
38 |
39 | def stop(self):
40 | self.stopped = True
41 |
42 | def create_graph():
43 |
44 | # Creates graph from saved graph_def.pb.
45 | with tf.gfile.FastGFile(os.path.join(
46 | model_dir, 'graph.pb'), 'rb') as f:
47 | graph_def = tf.GraphDef()
48 | graph_def.ParseFromString(f.read())
49 | _ = tf.import_graph_def(graph_def, name='')
50 |
51 | def run(animals_feed='Whitetail Deer', animals_not_feed='Aoudad', timer="5"):
52 | # Define num variable
53 |
54 | files = glob.glob(animals_feed + "/" + animals_feed + "*.jpg")
55 | if files == []:
56 | print ("No Previous Image Found: Resetting Image Counter")
57 | num = 1000000
58 | else:
59 | files = sorted(files)
60 | num = int(os.path.basename(files[-1])[4:-4])
61 | num += 1
62 | print ("Previous Image Found and Counted - Current Image Number is:")
63 | print (num)
64 |
65 | model_dir=''
66 |
67 | label_lines = [line.rstrip() for line
68 | in tf.gfile.GFile("labels.txt")]
69 |
70 | #Set up Pins for Motion Sensors
71 | GPIO.setwarnings(False)
72 | GPIO.setmode(GPIO.BOARD)
73 | GPIO.setup(29, GPIO.IN)
74 | GPIO.setup(31, GPIO.IN)
75 | GPIO.setup(33, GPIO.IN)
76 | GPIO.setup(35, GPIO.IN)
77 |
78 | # Download and create graph
79 | create_graph()
80 |
81 | # Variables declarations
82 | frame_count=0
83 | score=0
84 | start = time.time()
85 | pred=0
86 | last=0
87 | human_string=None
88 | doors=0
89 | #Doors Closing
90 | print ("Doors Closing")
91 | GPIO.setup(16, GPIO.OUT)
92 | GPIO.setup(18, GPIO.OUT)
93 | time.sleep(15)
94 | GPIO.cleanup(16)
95 | GPIO.cleanup(18)
96 | print ("Doors Closed")
97 |
98 | ### THE TIMER VARIABLE FROM THE WEB CONTROL SHOULD BE ENTERED BELOW WHERE THE 5 IS CURRENTLY
99 | timeout = time.time() + timer*60
100 |
101 | # Start tensorflow session
102 | while True:
103 |
104 | #Set up motion sensor variables
105 | ms1=0
106 | ms2=0
107 | ms3=0
108 | ms4=0
109 |
110 | #clean up cameras
111 | GPIO.setup(36, GPIO.OUT)
112 | GPIO.cleanup(36)
113 | GPIO.setup(37, GPIO.OUT)
114 | GPIO.cleanup(37)
115 | GPIO.setup(38, GPIO.OUT)
116 | GPIO.cleanup(38)
117 | GPIO.setup(40, GPIO.OUT)
118 | GPIO.cleanup(40)
119 | print ("Monitoring Motion Sensors")
120 | while ms1 < 5 and ms2 < 5 and ms3 < 5 and ms4 < 5:
121 | if GPIO.input(29):
122 | print("Motion Detected MS1")
123 | ms1 += 1
124 | time.sleep(.2)
125 | if ms1 == 5:
126 | GPIO.setup(37, GPIO.OUT)
127 | print ("Camera 1 Started")
128 | time.sleep(2)
129 | break
130 | if GPIO.input(31):
131 | print("Motion Detected MS2")
132 | ms2 += 1
133 | time.sleep(.2)
134 | if ms2 == 5:
135 | GPIO.setup(36, GPIO.OUT)
136 | print ("Camera 2 Started")
137 | time.sleep(2)
138 | break
139 | if GPIO.input(33):
140 | print("Motion Detected MS3")
141 | ms3 += 1
142 | time.sleep(.2)
143 | if ms3 == 5:
144 | GPIO.setup(38, GPIO.OUT)
145 | print ("Camera 3 Started")
146 | time.sleep(2)
147 | break
148 | if GPIO.input(35):
149 | print("Motion Detected MS4")
150 | ms4 += 1
151 | time.sleep(.2)
152 | if ms4 == 5:
153 | GPIO.setup(40, GPIO.OUT)
154 | print ("Camera 4 Started")
155 | time.sleep(2)
156 | break
157 | if time.time() > timeout and doors == 1:
158 | print ("Timer Expired: Securing Machine - Resetting Timer")
159 | print ("Closing Doors")
160 | GPIO.setup(16, GPIO.OUT)
161 | GPIO.setup(18, GPIO.OUT)
162 | time.sleep(10)
163 | GPIO.cleanup(16)
164 | GPIO.cleanup(18)
165 | print ("Doors Closed")
166 | GPIO.cleanup(36)
167 | GPIO.cleanup(37)
168 | GPIO.cleanup(38)
169 | GPIO.cleanup(40)
170 | print ("Resetting Timer")
171 | doors = 0
172 |
173 | vs = VideoStream(src=0)
174 | vs.start()
175 | print ("Camera Started")
176 | with tf.Session() as sess:
177 | softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
178 | scans = 0
179 | while scans < 5:
180 | frame = vs.read()
181 | frame_count+=1
182 | # Only run every 5 frames
183 | if frame_count%10==0:
184 |
185 | # Save the image as the fist layer of inception is a DecodeJpeg
186 | cv2.imwrite("current_frame.jpg",frame)
187 |
188 | image_data = tf.gfile.FastGFile("./current_frame.jpg", 'rb').read()
189 | predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
190 |
191 | predictions = np.squeeze(predictions)
192 |
193 | # change n_pred for more predictions
194 | n_pred=1
195 | top_k = predictions.argsort()[-n_pred:][::-1]
196 | for node_id in top_k:
197 | human_string_n = label_lines[node_id]
198 | score = predictions[node_id]
199 |
200 | print (scans)
201 | scans += 1
202 | print('%s (score = %.2f)' % (human_string_n, score))
203 |
204 | ### BELOW IS WHERE THE TARGET SPECIES VARIABLE SHOULD IN A SERIES
205 | if human_string_n in (animals_feed) and score > .8:
206 | copyfile("/home/pi/current_frame.jpg", "/home/pi/" + animals_feed + "/" + animals_feed + "%s.jpg" % num)
207 | try:
208 | im = Image.open("/home/pi/" + animals_feed + "/" + animals_feed + "%s.jpg" % num)
209 | except IOError:
210 | print ("File Corrupted")
211 | os.remove("/home/pi/" + animals_feed + "/" + animals_feed + "%s.jpg" % num)
212 | print (animals_feed + " Detected")
213 | print ('Confidence %.2F%%' % (score * 100))
214 | num += 1
215 | scans = 0
216 | ##### THE TIMER VARIABLE FROM THE WEB CONTROL SHOULD BE ENTERED BELOW WHERE THE 5 IS CURRENTLY
217 | timeout = time.time() + timer*60
218 | if doors == 0:
219 | print ("Doors Opening")
220 | GPIO.setup(13, GPIO.OUT)
221 | GPIO.setup(15, GPIO.OUT)
222 | time.sleep(10)
223 | GPIO.cleanup(13)
224 | GPIO.cleanup(15)
225 | print ("Doors Open")
226 | doors = 1
227 | ### BELOW IS WHERE THE NON TARGET SPECIES VARIABLE SHOULD IN A SERIES
228 | if human_string_n in (animals_not_feed) and score > .8:
229 | #print "Shocker Activated"
230 | #Turn On Shocker
231 | #GPIO.setup(32, GPIO.OUT)
232 | #GPIO.setup(22, GPIO.OUT)
233 | print ("Doors Closing")
234 | GPIO.setup(16, GPIO.OUT)
235 | GPIO.setup(18, GPIO.OUT)
236 | time.sleep(10)
237 | GPIO.cleanup(16)
238 | GPIO.cleanup(18)
239 | time.sleep(180)
240 | #GPIO.cleanup(22)
241 | #GPIO.cleanup(32)
242 | doors = 0
243 | os.remove("/home/pi/current_frame.jpg")
244 | # if the 'q' key is pressed, stop the loop
245 | if cv2.waitKey(1) & 0xFF == ord("q"):break
246 |
247 | vs.stop()
248 | print ("Closing Camera")
249 | time.sleep(2)
250 |
251 | if __name__ == '__main__':
252 | run()
--------------------------------------------------------------------------------
/app/views.py:
--------------------------------------------------------------------------------
1 | from flask_mysqldb import MySQL
2 | from flask import Flask, request, session, g, redirect, url_for, \
3 | abort, render_template, flash, send_from_directory
4 | from contextlib import closing
5 | from app import app
6 | import os
7 | from shutil import copyfile
8 | from os import listdir, mkdir
9 | from os.path import isdir, join, dirname, exists, splitext
10 | from PIL import Image
11 | import subprocess
12 | from app.process import read, fixup, updating, read_conf, nested_dict
13 | import time
14 |
15 | # app = Flask(__name__)
16 | mysql = MySQL()
17 | # MySQL Configuration
18 | app.config['MYSQL_USER'] = 'root'
19 | app.config['MYSQL_PASSWORD'] = 'password'
20 | app.config['MYSQL_DB'] = 'raspberrypi'
21 | app.config['MYSQL_HOST'] = 'localhost'
22 | mysql.init_app(app)
23 |
24 | # from app.harpu import run
25 |
26 | app.config.update(dict(
27 | PHOTO_DIR='/home/pi/deer/',
28 | #PHOTO_DIR='static/images/',
29 | THUMB_SIZE=(300, 300)
30 | ))
31 | app.config.from_envvar('PHOTOVIEWER_SETTINGS', silent=True)
32 |
33 |
34 | @app.route('/')
35 | @app.route('/index')
36 | @app.route('/index/', methods=['POST'])
37 | def index():
38 | return render_template('index.html')
39 |
40 |
41 | @app.route('/mode/', methods=['POST'])
42 | def mode():
43 | data = read()
44 | modelist = ["Demo Mode", "Demo Mode with Shocker", "Standard Mode", "Standard Mode with Shocker"]
45 | modemessage = 'Please select the machine mode below. Demo mode only operates one camera for demonstration purposes. Standard mode is normal operation of all cameras and sensors.'
46 | return render_template('mode.html', modelist=modelist, mode=data['mode'], message=modemessage);
47 |
48 | @app.route('/machinemode/', methods=['POST'])
49 | def machinemode():
50 | mode = request.form["mode"]
51 | fixup('mode', mode)
52 | time.sleep(1)
53 | modewarning = "Machine Mode Confirmed"
54 | os.system('sudo pkill -9 -f harpu.py')
55 | subprocess.Popen(['lxterminal', '-e', 'sudo', 'python', 'harpu.py'])
56 | return render_template('savesettings.html', message=modewarning)
57 |
58 | @app.route('/delete_activities/', methods=['POST'])
59 | def delete_activities():
60 | cur = mysql.connection.cursor()
61 | cur.execute('''DELETE FROM `records` WHERE 1''')
62 | mysql.connection.commit()
63 | deletemessage = 'All Records were Deleted.'
64 | return render_template('confirm.html', message=deletemessage)
65 |
66 | @app.route('/species/', methods=['POST'])
67 | def species():
68 | speciesmessage = "Please Select the Species that you wish for the machine to feed and the Species that wish the machine to never feed."
69 | feed = ["Whitetail Deer", "Hog", "Aoudad"]
70 | never_feed = ["Aoudad", "Whitetail Deer", "Hog", "Raccoon", "Black Bear"]
71 | data = read()
72 | return render_template('species.html', fdata=feed, ndata=never_feed, feed=data['feed'], never_feed=data['never_feed'], message=speciesmessage)
73 |
74 | @app.route('/activity/', methods=['POST'])
75 | def activity():
76 | recentactivity = "Recent Activity"
77 | animals = ['Whitetail Deer', 'Hog', 'Black Bear']
78 | timezones = [
79 | '12AM - 3AM',
80 | '3AM - 6AM',
81 | '6AM - 9AM',
82 | '9AM - 12PM',
83 | '12PM - 3PM',
84 | '3PM - 6PM',
85 | '6PM - 9PM',
86 | '9PM - 12AM'
87 | ]
88 | data_item = [[0 for k in range(3)] for j in range(8)]
89 | cur = mysql.connection.cursor()
90 | print ('connected !!')
91 | cur.execute('''SELECT * FROM records''')
92 | results = [dict(animal=row[1], date=row[3], timezone=row[4]) for row in cur.fetchall()]
93 | datelist = []
94 | for item in results:
95 | if item['date'] in datelist:
96 | pass
97 | else:
98 | datelist.append(item['date'])
99 |
100 | recentactivity = nested_dict(3, int)
101 | for date in datelist:
102 | for animal in animals:
103 | for timezone in timezones:
104 | recentactivity[date][animal][timezone] = 0
105 | for item in results:
106 | recentactivity[item['date']][item['animal']][item['timezone']] += 1
107 | print ("recentactivity", recentactivity)
108 |
109 | return render_template('recentactivity.html',
110 | dates=datelist,
111 | timezones=timezones,
112 | animals=animals,
113 | message=recentactivity)
114 |
115 | @app.route('/name/', methods=['POST'])
116 | def name():
117 | name = read_conf()
118 | print ('======= data ======', name)
119 | namemessage = "Please enter a name for the machine, this will also be your WIFI Network Name. After Clicking Save your machine will reboot."
120 | return render_template('name.html', name=name, message=namemessage)
121 |
122 | @app.route('/timer/', methods=['POST'])
123 | def timer():
124 | data = read()
125 | timermessage = "Please enter the number of whole minutes that you wish the machine to stay open after seeing a target animal."
126 | return render_template('timer.html', timer=data['timer'], message=timermessage)
127 |
128 | @app.route('/ftime/', methods=['POST'])
129 | def ftime():
130 | data = read()
131 | sTime = ["24HR", "4AM", "5AM", "6AM", "7AM", "8AM", "9AM", "10AM"]
132 | eTime = ["24HR", "4PM", "5PM", "6PM", "7PM", "8PM", "9PM", "10PM"]
133 | ftimemessage = "Please select when you would like the feeder to start and stop feeding. If you would like it to always feed, select 24HR on both options."
134 | return render_template('feedtime.html', sTime=sTime, eTime=eTime, startTime=data['starttime'], endTime=data['endtime'], message=ftimemessage)
135 |
136 | @app.route('/feedtime/', methods=['POST'])
137 | def feedtime():
138 | starttime = request.form["starttime"]
139 | endtime = request.form["endtime"]
140 | start = str(starttime)
141 | end = str(endtime)
142 | fixup('starttime', starttime)
143 | fixup('endtime', endtime)
144 | time.sleep(1)
145 | if start == '24HR' and end == '24HR':
146 | feedtimewarning = "Machine will feed 24 hours per day."
147 | else:
148 | feedtimewarning = "Machine will Feed from "+ start + ":00 to " + end + ":00"
149 | os.system('sudo pkill -9 -f harpu.py')
150 | subprocess.Popen(['lxterminal', '-e', 'sudo', 'python', 'harpu.py'])
151 | return render_template('savesettings.html', message=feedtimewarning)
152 |
153 | @app.route('/restore/', methods=['POST'])
154 | def restore():
155 | restorewarning = 'The Factory Restore will reset the machine completely to factory settings this includes your WIFI name. This will also reboot your machine.'
156 | return render_template('restore.html', message=restorewarning)
157 |
158 | @app.route('/confirmrestore/', methods=['POST'])
159 | def confirmrestore():
160 | os.system('sudo pkill -9 -f harpu.py')
161 | os.system('sudo rm -rf deer')
162 | os.system('mkdir deer')
163 | os.system('sudo cp /home/pi/paramsdefault.json /home/pi/params.json')
164 | name = 'SpeciesSpecific'
165 | var_key = ['ssid']
166 | var_value = [name]
167 | what_to_change = dict(zip(var_key, var_value))
168 | print ('what', what_to_change)
169 | updating('/etc/hostapd/hostapd.conf', what_to_change)
170 | time.sleep(2)
171 | os.system('sudo reboot')
172 |
173 | @app.route('/cancelrestore/', methods=['POST'])
174 | def cancelrestore():
175 | cancelmessage = 'Restoration Cancelled, Machine not Restored'
176 | return render_template('index.html', message=cancelmessage)
177 |
178 | @app.route('/imgdelete/', methods=['POST'])
179 | def imgdelete():
180 | deletewarning = 'This will delete all photos from the machine. Please either Confirm or Cancel below'
181 | return render_template('deleteall.html', message=deletewarning)
182 |
183 | @app.route('/canceldelete/', methods=['POST'])
184 | def canceldelete():
185 | candelmessage = 'Delete Cancelled, No Images Were Deleted'
186 | return render_template('index.html', message=candelmessage)
187 |
188 | @app.route('/deleteall/', methods=['POST'])
189 | def deleteall():
190 | os.system('sudo pkill -9 -f harpu.py')
191 | os.system('sudo rm -rf deer')
192 | os.system('mkdir deer')
193 | os.system('sudo pkill -9 -f harpu.py')
194 | subprocess.Popen(['lxterminal', '-e', 'sudo', 'python', 'harpu.py'])
195 | deletemessage = 'All Images were Deleted, Please allow time for machine to restart'
196 | return render_template('confirm.html', message=deletemessage)
197 |
198 | # Added by Lee Yam Keng - 09/19/2017
199 | @app.route('/define_feeds/', methods=['POST'])
200 | def define_feeds():
201 | animals_feed = request.form.getlist("feed")
202 | animals_not_feed = request.form.getlist("never_feed")
203 | print ('animals_not_feed', animals_not_feed)
204 | fixup('feed', animals_feed)
205 | fixup('never_feed', animals_not_feed)
206 | time.sleep(1)
207 | os.system('sudo pkill -9 -f harpu.py')
208 | subprocess.Popen(['lxterminal', '-e', 'sudo', 'python', 'harpu.py'])
209 | return render_template('savesettings.html')
210 |
211 | @app.route('/define_name/', methods=['POST'])
212 | def define_name():
213 | name = request.form["name"]
214 | print ('name', name)
215 | fixup('name', name)
216 | var_key = ['ssid']
217 | var_value = [name]
218 | what_to_change = dict(zip(var_key, var_value))
219 | print ('what', what_to_change)
220 | updating('/etc/hostapd/hostapd.conf', what_to_change)
221 | time.sleep(2)
222 | os.system('sudo reboot')
223 |
224 | @app.route('/define_timer/', methods=['POST'])
225 | def define_timer():
226 | timer = request.form["timer"]
227 | fixup('timer', timer)
228 | time.sleep(1)
229 | os.system('sudo pkill -9 -f harpu.py')
230 | subprocess.Popen(['lxterminal', '-e', 'sudo', 'python', 'harpu.py'])
231 | return render_template('savesettings.html')
232 | @app.route('/delete/