Added functionality to take screenshots during stream

This commit is contained in:
Floris 2022-05-05 07:08:12 -04:00
parent 9b27f5d8b4
commit 7c940fba67
5 changed files with 83 additions and 32 deletions

4
.gitignore vendored
View File

@ -44,3 +44,7 @@ dev.env
#_pycache #_pycache
__pycache__/ __pycache__/
#image_files
*.jpg
*.jpeg
*.png

View File

@ -6,7 +6,7 @@ Create your own live stream from a Raspberry Pi using the Pi camera module. Buil
The Pi streams the output of the camera module over the web via Flask. Devices connected to the same network would be able to access the camera stream via The Pi streams the output of the camera module over the web via Flask. Devices connected to the same network would be able to access the camera stream via
``` ```
<raspberry_pi_ip:5000> <raspberry_pi_ip:5000>
``` ```
## Screenshots ## Screenshots
@ -24,12 +24,12 @@ The Pi streams the output of the camera module over the web via Flask. Devices c
Install the following dependencies to create camera stream. Install the following dependencies to create camera stream.
``` ```
sudo apt-get update sudo apt-get update
sudo apt-get upgrade sudo apt-get upgrade
sudo apt-get install libatlas-base-dev sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev sudo apt-get install libjasper-dev
sudo apt-get install libqtgui4 sudo apt-get install libqtgui4
sudo apt-get install libqt4-test sudo apt-get install libqt4-test
sudo apt-get install libhdf5-dev sudo apt-get install libhdf5-dev
@ -39,10 +39,9 @@ sudo pip3 install opencv-contrib-python
sudo pip3 install imutils sudo pip3 install imutils
sudo pip3 install opencv-python sudo pip3 install opencv-python
``` ```
Note: This installation of opencv may take a while depending on your pi model. Note: This installation of opencv may take a while depending on your pi model.
OpenCV alternate installation (in the event of failed opencv builds): OpenCV alternate installation (in the event of failed opencv builds):
@ -79,7 +78,7 @@ Go the end of the and add the following (from above):
sudo python3 /home/pi/pi-camera-stream-flask/main.py sudo python3 /home/pi/pi-camera-stream-flask/main.py
``` ```
This would cause the following terminal command to auto-start each time the Raspberry Pi boots up. This in effect creates a headless setup - which would be accessed via SSH. This would cause the following terminal command to auto-start each time the Raspberry Pi boots up. This in effect creates a headless setup - which would be accessed via SSH.
Note: make sure SSH is enabled. Note: make sure SSH is enabled.
## More Projects / Next Steps ## More Projects / Next Steps

View File

@ -2,16 +2,19 @@
#Date: 27.09.20 #Date: 27.09.20
#Desc: This scrtipt script.. #Desc: This scrtipt script..
import cv2 import cv2 as cv
from imutils.video.pivideostream import PiVideoStream from imutils.video.pivideostream import PiVideoStream
import imutils import imutils
import time import time
from datetime import datetime
import numpy as np import numpy as np
class VideoCamera(object): class VideoCamera(object):
def __init__(self, flip = False): def __init__(self, flip = False, file_type = ".jpg", photo_string= "stream_photo"):
self.vs = PiVideoStream().start() self.vs = PiVideoStream(resolution=(1920, 1080), framerate=30).start()
self.flip = flip self.flip = flip # Flip frame vertically
self.file_type = file_type # image type i.e. .jpg
self.photo_string = photo_string # Name to save the photo
time.sleep(2.0) time.sleep(2.0)
def __del__(self): def __del__(self):
@ -24,5 +27,13 @@ class VideoCamera(object):
def get_frame(self): def get_frame(self):
frame = self.flip_if_needed(self.vs.read()) frame = self.flip_if_needed(self.vs.read())
ret, jpeg = cv2.imencode('.jpg', frame) ret, jpeg = cv.imencode(self.file_type, frame)
return jpeg.tobytes() self.previous_frame = jpeg
return jpeg.tobytes()
# Take a photo, called by camera button
def take_picture(self):
frame = self.flip_if_needed(self.vs.read())
ret, image = cv.imencode(self.file_type, frame)
today_date = datetime.now().strftime("%m%d%Y-%H%M%S") # get current time
cv.imwrite(str(self.photo_string + "_" + today_date + self.file_type), frame)

11
main.py
View File

@ -5,8 +5,6 @@
# import the necessary packages # import the necessary packages
from flask import Flask, render_template, Response, request from flask import Flask, render_template, Response, request
from camera import VideoCamera from camera import VideoCamera
import time
import threading
import os import os
pi_camera = VideoCamera(flip=False) # flip pi camera if upside down. pi_camera = VideoCamera(flip=False) # flip pi camera if upside down.
@ -30,9 +28,12 @@ def video_feed():
return Response(gen(pi_camera), return Response(gen(pi_camera),
mimetype='multipart/x-mixed-replace; boundary=frame') mimetype='multipart/x-mixed-replace; boundary=frame')
# Take a photo when pressing camera button
@app.route('/picture')
def take_picture():
pi_camera.take_picture()
return "None"
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', debug=False) app.run(host='0.0.0.0', debug=False)

View File

@ -25,7 +25,7 @@ body {
text-align: center; text-align: center;
padding: 14px 16px; padding: 14px 16px;
text-decoration: none; text-decoration: none;
font-size: 17px; font-size: 17px;
} }
.navbar a:hover { .navbar a:hover {
@ -43,7 +43,7 @@ body {
} }
.camera-movement{ .camera-movement{
float: none; float: none;
position: absolute; position: absolute;
top: 50%; top: 50%;
@ -60,7 +60,7 @@ i.fa {
border-radius: 60px; border-radius: 60px;
box-shadow: 0px 0px 2px #888; box-shadow: 0px 0px 2px #888;
padding: 0.5em 0.6em; padding: 0.5em 0.6em;
} }
@ -79,12 +79,12 @@ button {
overflow: hidden; overflow: hidden;
outline:none; outline:none;
} }
//CSS //CSS
.camera-bg { .camera-bg {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
/* Preserve aspet ratio */ /* Preserve aspet ratio */
min-width: 100%; min-width: 100%;
@ -132,11 +132,11 @@ body {
<div class="main" id="newpost"> <div class="main" id="newpost">
<img class="camera-bg" style="width: 100%; height:80%; background-attachment: fixed;" id="bg" class="center" src="{{ url_for('video_feed') }}"> <img class="camera-bg" style="width: 100%; height:80%; background-attachment: fixed;" id="bg" class="center" src="{{ url_for('video_feed') }}">
<!--<img class="camera-bg" style="width: 100%; height:80%; background-attachment: fixed;" id="bg" class="center" src="https://www.psdbox.com/wp-content/uploads/2011/01/security-camera-photoshop-effect.jpg">--> <!--<img class="camera-bg" style="width: 100%; height:80%; background-attachment: fixed;" id="bg" class="center" src="https://www.psdbox.com/wp-content/uploads/2011/01/security-camera-photoshop-effect.jpg">-->
</div> </div>
<div class="top-right-logo"> <div class="top-right-logo">
<a></a>Raspberry Pi - Camera Stream </a> <a></a>Arya Stream </a>
</div> </div>
@ -144,20 +144,29 @@ body {
<div class="ignoreCall"> <div class="ignoreCall">
<a id=decline class="but_def"> <a id=decline class="but_def">
<button id="button"> <button id="button">
<i style="background: red; color: white;" class="fa fa-times fa-2x" aria-hidden="true"></i> <i style="background: red; color: white;" class="fa fa-times fa-2x" aria-hidden="true"></i>
</button> </button>
</a> </a>
</div>
<div class="picture">
<a href=# id=take-picture class="picture_class">
<button id="take-picture-button" onclick="take_picture()">
<i style="background: blue; color: white;" class="fa fa-camera fa-2x" aria-hidden="true"></i>
</button>
</a>
</div> </div>
</div> </div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
// stop stream - called when pressing red X
var button = document.getElementById('button'); var button = document.getElementById('button');
button.onclick = function() { button.onclick = function() {
@ -169,9 +178,36 @@ button.onclick = function() {
div.style.display = 'block'; div.style.display = 'block';
} }
}; };
// Take and save a photo, call picture function in main.py
$(function() {
$('a#take-picture').on('click', function(e) {
e.preventDefault()
$.getJSON('/picture',
function(data) {
//do nothing
});
return false;
});
});
</script>
<script type="text/javascript">
// take picture
var button = document.getElementById('take-pica-button');
button.onclick = function() {
var div = document.getElementById('newpost');
if (div.style.display !== 'none') {
div.style.display = 'none';
}
else {
div.style.display = 'block';
}
};
</script> </script>
</body> </body>
</html> </html>