rajkhanke commited on
Commit
5a32907
·
verified ·
1 Parent(s): 3f2746e

Upload 3 files

Browse files
Files changed (4) hide show
  1. .gitattributes +1 -0
  2. alarn_tune.mp3 +3 -0
  3. templates/index.html +250 -0
  4. yolo11n.pt +3 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ alarn_tune.mp3 filter=lfs diff=lfs merge=lfs -text
alarn_tune.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:22fdba64b8d71c233e8659af532b588d7ee216bb4567c73ca87a7c71df97f293
3
+ size 228700
templates/index.html ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Farm Intrusion & Livestock System</title>
7
+ <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
8
+ <meta http-equiv="Pragma" content="no-cache" />
9
+ <meta http-equiv="Expires" content="0" />
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ :root {
13
+ --primary-color: #2ecc71; --primary-dark: #27ae60; --secondary-color: #1e8449;
14
+ --accent-color: #3498db; --background-color: #f5f5f5; --card-color: #ffffff;
15
+ --text-color: #333333; --text-light: #7f8c8d; --border-color: #e0e0e0;
16
+ --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --border-radius: 8px;
17
+ }
18
+ * { margin: 0; padding: 0; box-sizing: border-box; }
19
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--background-color); color: var(--text-color); display: flex; flex-direction: column; min-height: 100vh; }
20
+ .header { background-color: var(--primary-color); color: white; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; box-shadow: var(--shadow); }
21
+ .header h1 { font-size: 1.5rem; margin: 0; font-weight: 600; }
22
+ .container { display: flex; flex: 1; }
23
+ .sidebar { width: 350px; background-color: var(--card-color); border-right: 1px solid var(--border-color); padding: 1.5rem; overflow-y: auto; box-shadow: 2px 0 5px rgba(0,0,0,0.05); }
24
+ .main-content { flex: 1; padding: 2rem; overflow-y: auto; display: flex; flex-direction: column; gap: 1.5rem; }
25
+ .section-title { color: var(--primary-dark); font-size: 1.2rem; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid var(--primary-color); }
26
+ .card { background-color: var(--card-color); border-radius: var(--border-radius); box-shadow: var(--shadow); padding: 1.5rem; margin-bottom: 1.5rem; border-top: 4px solid var(--primary-color); }
27
+ .video-container { position: relative; overflow: hidden; border-radius: var(--border-radius); background-color: #000; box-shadow: var(--shadow); }
28
+ .video-feed { width: 100%; border-radius: var(--border-radius); display: block; }
29
+ .status { position: absolute; top: 15px; right: 15px; background-color: rgba(0,0,0,0.6); color: white; padding: 0.5rem 0.75rem; border-radius: 20px; font-size: 0.9rem; display: flex; align-items: center; gap: 8px; }
30
+ .status-dot { height: 10px; width: 10px; background-color: var(--primary-color); border-radius: 50%; display: inline-block; animation: pulse 1.5s infinite; }
31
+ @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }
32
+ .detection-list { list-style: none; margin-top: 0.5rem; }
33
+ .detection-item { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem; border-bottom: 1px solid var(--border-color); }
34
+ .detection-item:last-child { border-bottom: none; }
35
+ .detection-count { background-color: var(--primary-color); color: white; padding: 2px 10px; border-radius: 12px; font-size: 0.9rem; font-weight: bold; }
36
+ .alert-info { background-color: rgba(46, 204, 113, 0.1); border-left: 4px solid var(--primary-color); padding: 1rem; margin-top: 1rem; border-radius: 4px; display: flex; align-items: center; gap: 10px; }
37
+ .alert-info i { color: var(--primary-color); font-size: 1.2rem; }
38
+ #graph { min-height: 250px; }
39
+ @media (max-width: 992px) { .container { flex-direction: column; } .sidebar { width: 100%; border-right: none; border-bottom: 1px solid var(--border-color); } }
40
+ @media (max-width: 576px) { .header { padding: 1rem; } .main-content, .sidebar { padding: 1rem; } }
41
+ </style>
42
+ </head>
43
+ <body>
44
+ <header class="header">
45
+ <h1><i class="fas fa-video"></i>Farm Intrusion & Livestock Detection</h1>
46
+ <div id="current-time"></div>
47
+ </header>
48
+
49
+ <div class="container">
50
+ <div class="sidebar">
51
+ <h2 class="section-title">Detection Summary</h2>
52
+ <div class="card">
53
+ <h3 class="section-title">Location</h3>
54
+ <div id="location-info">Requesting location access...</div>
55
+ </div>
56
+ <div class="card">
57
+ <h3 class="section-title">Detected Objects</h3>
58
+ <ul id="class-list" class="detection-list">
59
+ <li class="detection-item">Awaiting data...</li>
60
+ </ul>
61
+ </div>
62
+ <div class="card">
63
+ <h3 class="section-title">Detection Graph</h3>
64
+ <div id="bar-graph" style="min-height:180px;"></div>
65
+ <div id="line-graph" style="min-height:180px;margin-top:20px;"></div>
66
+ <div id="pie-graph" style="min-height:180px;margin-top:20px;"></div>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="main-content">
71
+ <div class="card">
72
+ <h2 class="section-title">Live Camera Feed</h2>
73
+ <div class="video-container">
74
+ <img class="video-feed" src="{{ url_for('video_feed') }}" alt="Live Video Feed">
75
+ <div class="status"><span class="status-dot"></span>Live</div>
76
+ </div>
77
+ <div class="alert-info">
78
+ <i class="fas fa-bell"></i>
79
+ <p>If a person is detected, an automated call will be initiated and a Telegram alert will be sent.</p>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
86
+ <script>
87
+ document.addEventListener('DOMContentLoaded', function() {
88
+ // --- TIME UPDATE ---
89
+ const timeElement = document.getElementById('current-time');
90
+ function updateTime() {
91
+ timeElement.textContent = new Date().toLocaleTimeString();
92
+ }
93
+ setInterval(updateTime, 1000);
94
+ updateTime();
95
+
96
+ // --- LOCATION HANDLING ---
97
+ const locationInfo = document.getElementById('location-info');
98
+ function sendLocationToServer(lat, lon) {
99
+ fetch('/set_location', {
100
+ method: 'POST',
101
+ headers: { 'Content-Type': 'application/json' },
102
+ body: JSON.stringify({ latitude: lat, longitude: lon })
103
+ })
104
+ .then(response => response.json())
105
+ .then(data => {
106
+ if (data.status === 'success' || data.location) {
107
+ locationInfo.innerHTML = `<b>Address:</b> ${data.location}<br><b>Latitude:</b> ${data.latitude}<br><b>Longitude:</b> ${data.longitude}`;
108
+ } else {
109
+ locationInfo.textContent = `Lat: ${lat}, Lon: ${lon}`;
110
+ }
111
+ })
112
+ .catch(() => {
113
+ locationInfo.textContent = 'Could not send location to server.';
114
+ });
115
+ }
116
+
117
+ if (navigator.geolocation) {
118
+ navigator.geolocation.getCurrentPosition(
119
+ (position) => {
120
+ sendLocationToServer(position.coords.latitude, position.coords.longitude);
121
+ },
122
+ () => {
123
+ locationInfo.textContent = 'Location access denied.';
124
+ }
125
+ );
126
+ } else {
127
+ locationInfo.textContent = 'Geolocation is not supported by this browser.';
128
+ }
129
+
130
+ // --- DATA FETCHING AND UI UPDATES ---
131
+ const classList = document.getElementById('class-list');
132
+
133
+ async function fetchAndUpdateDashboard() {
134
+ try {
135
+ const response = await fetch('/object_stats');
136
+ const data = await response.json();
137
+ updateClassList(data.object_counts);
138
+ updateGraph(data.object_counts);
139
+ // Update location info with full details if available
140
+ if (data.location && data.latitude && data.longitude) {
141
+ locationInfo.innerHTML = `<b>Address:</b> ${data.location}<br><b>Latitude:</b> ${data.latitude}<br><b>Longitude:</b> ${data.longitude}`;
142
+ }
143
+ } catch (error) {
144
+ classList.innerHTML = '<li class="detection-item">Error loading data</li>';
145
+ }
146
+ }
147
+
148
+ function updateClassList(counts) {
149
+ classList.innerHTML = '';
150
+ const objects = Object.keys(counts);
151
+
152
+ if (objects.length === 0) {
153
+ classList.innerHTML = '<li class="detection-item">No objects detected</li>';
154
+ return;
155
+ }
156
+
157
+ objects.forEach(className => {
158
+ const li = document.createElement('li');
159
+ li.className = 'detection-item';
160
+ li.innerHTML = `<span>${className.charAt(0).toUpperCase() + className.slice(1)}</span><span class="detection-count">${counts[className]}</span>`;
161
+ classList.appendChild(li);
162
+ });
163
+ }
164
+
165
+ // --- GRAPH STATE ---
166
+ let timeSeries = [];
167
+ let timeLabels = [];
168
+ let breakdowns = [];
169
+
170
+
171
+ function updateGraph(counts) {
172
+ const classNames = Object.keys(counts);
173
+ const objectCounts = Object.values(counts);
174
+ const now = new Date().toLocaleTimeString();
175
+
176
+ // Save for time-series (limit to 4 bins)
177
+ timeLabels.push(now);
178
+ timeSeries.push(objectCounts.reduce((a, b) => a + b, 0));
179
+ breakdowns.push(classNames.map((c, i) => `${counts[c]} ${c}`).join(", "));
180
+ if (timeLabels.length > 4) {
181
+ timeLabels.shift();
182
+ timeSeries.shift();
183
+ breakdowns.shift();
184
+ }
185
+
186
+ // Bar chart (top)
187
+ const barData = [{
188
+ x: classNames.map(name => name.charAt(0).toUpperCase() + name.slice(1)),
189
+ y: objectCounts,
190
+ type: 'bar',
191
+ marker: { color: 'rgba(46, 204, 113, 0.8)' }
192
+ }];
193
+ const barLayout = {
194
+ margin: { t: 20, r: 20, l: 40, b: 40 },
195
+ xaxis: { title: 'Detected Objects' },
196
+ yaxis: { title: 'Count', dtick: 1, tickformat: 'd' },
197
+ font: { family: 'Segoe UI, sans-serif' },
198
+ paper_bgcolor: 'transparent',
199
+ plot_bgcolor: 'transparent',
200
+ };
201
+ Plotly.newPlot('bar-graph', barData, barLayout, { responsive: true, displayModeBar: false });
202
+
203
+ // Line chart (middle)
204
+ const lineData = [{
205
+ x: [...timeLabels],
206
+ y: [...timeSeries],
207
+ type: 'scatter',
208
+ mode: 'lines+markers',
209
+ name: 'Total Objects',
210
+ hovertemplate: '%{y} objects<br>%{text}',
211
+ text: breakdowns,
212
+ line: { color: 'rgba(39, 174, 96, 1)', width: 3 },
213
+ marker: { color: 'rgba(39, 174, 96, 1)', size: 8 }
214
+ }];
215
+ const lineLayout = {
216
+ margin: { t: 20, r: 20, l: 40, b: 40 },
217
+ xaxis: { title: 'Time', tickmode: 'array', tickvals: [...timeLabels], ticktext: [...timeLabels], automargin: true },
218
+ yaxis: { title: 'Total Object Count', dtick: 1, tickformat: 'd' },
219
+ font: { family: 'Segoe UI, sans-serif' },
220
+ paper_bgcolor: 'transparent',
221
+ plot_bgcolor: 'transparent',
222
+ hovermode: 'closest',
223
+ };
224
+ Plotly.newPlot('line-graph', lineData, lineLayout, { responsive: true, displayModeBar: false });
225
+
226
+ // Pie chart (bottom)
227
+ const pieData = [{
228
+ labels: classNames.map(name => name.charAt(0).toUpperCase() + name.slice(1)),
229
+ values: objectCounts,
230
+ type: 'pie',
231
+ textinfo: 'label+percent',
232
+ insidetextorientation: 'radial',
233
+ marker: { colors: ['#2ecc71', '#27ae60', '#3498db', '#1e8449', '#e67e22', '#e74c3c'] }
234
+ }];
235
+ const pieLayout = {
236
+ margin: { t: 20, r: 20, l: 40, b: 40 },
237
+ font: { family: 'Segoe UI, sans-serif' },
238
+ paper_bgcolor: 'transparent',
239
+ plot_bgcolor: 'transparent',
240
+ };
241
+ Plotly.newPlot('pie-graph', pieData, pieLayout, { responsive: true, displayModeBar: false });
242
+ }
243
+
244
+ // Initial call and set interval to fetch every 1 second
245
+ fetchAndUpdateDashboard();
246
+ setInterval(fetchAndUpdateDashboard, 1000);
247
+ });
248
+ </script>
249
+ </body>
250
+ </html>
yolo11n.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0ebbc80d4a7680d14987a577cd21342b65ecfd94632bd9a8da63ae6417644ee1
3
+ size 5613764