`Although it is an article on Mac environment, the procedure is the same for Windows environment. Please read and try the environment-dependent part. ``
Display streaming video in your browser.
After reading this article to the end, you will be able to:
No. | Overview | keyword |
---|---|---|
1 | REST API | Flask |
2 | OpenCV | cv2 |
Streaming |
---|
environment | Ver. |
---|---|
macOS Catalina | 10.15.6 |
Raspberry Pi 4 Model B 4GB RAM | - |
Raspberry Pi OS (Raspbian) | 10 |
Python | 3.7.3 |
Flask | 1.1.2 |
opencv-python | 4.4.0.42 |
I think that understanding will deepen if you read while actually following the implementation contents and source code. Please use it by all means.
-From Raspberry Pi setup to Python environment installation -Create a remote control car with Raspberry Pi and Python -Create an LCD (16x2) game with Raspberry Pi and Python
command.sh
~$ sudo raspi-config
5 Interfacing Options
P1 Camera
command.sh
~$ sudo reboot
HDF5
HDF5 is a file format and library for storing scientific data.
command.sh
~$ sudo apt-get install -y libhdf5-dev libhdf5-serial-dev libhdf5-103
ATLAS
ATLAS is an approach for the automatic generation and optimization of numerical software.
command.sh
~$ sudo apt-get install -y libatlas-base-dev
JasPer
JasPer is a collection of software (i.e., a library and application programs) for the coding and manipulation of images.
command.sh
~$ sudo apt-get install -y libjasper-dev
command.sh
~$ git clone https://github.com/nsuhara/raspi-streaming.git -b master
command.sh
~$ cd raspi-streaming
~$ python -m venv .venv
~$ source .venv/bin/activate
~$ pip install -r requirements.txt
~$ source config
command.sh
~$ flask run --host=0.0.0.0 --port=5000
command.sh
~$ open "http://{host}:5000/raspi-streaming/api?process=front_end&request=app_form&secret_key=M7XvWE9fSFg3"
command.sh
~$ Control Key + C
target.sh
/app
├── __init__.py
├── apis
│ ├── templates
│ │ └── app_form.html
│ └── views
│ ├── __init__.py
│ ├── back_end_handler.py
│ ├── camera.py
│ ├── front_end_handler.py
│ └── main_handler.py
├── common
│ ├── __init__.py
│ └── utility.py
├── config
│ ├── __init__.py
│ ├── localhost.py
│ └── production.py
└── run.py
front-end
target.sh
/app
└── apis
├── templates
│ └── app_form.html
└── views
└── front_end_handler.py
front_end_handler.py
"""app/apis/views/front_end_handler.py
"""
from flask import jsonify, render_template
from app import secret_key
def handler(req):
"""handler
"""
param1 = req.get('param1')
param2 = req.get('param2')
if param1 == 'app_form':
return _app_form(req=param2)
return jsonify({'message': 'no route matched with those values'}), 200
def _app_form(req):
"""_app_form
"""
if req.get('secret_key', '') != secret_key:
return jsonify({'message': 'no route matched with those values'}), 200
return render_template('app_form.html', secret_key=req.get('secret_key', ''))
app_form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>raspi-streaming</title>
<style type="text/css">
html,
body {
-webkit-user-select: none;
width: 100%;
height: 100%;
}
table {
width: 100%;
height: 100%;
}
table,
td {
border: 1px gray solid;
padding: 10px;
}
img.img-option {
width: 100%;
/* height: 100%; */
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
// nothing to do
</script>
</head>
<body>
<table>
<tr height="5%">
<td>
<h1>raspi-streaming</h1>
</td>
</tr>
<tr>
<td>
<img class="img-option"
src="{{ url_for('raspi-streaming.api', process='back_end', request='video_feed', secret_key=secret_key) }}">
</td>
</tr>
</table>
</body>
</html>
back-end
target.sh
/app
└── apis
└── views
├── back_end_handler.py
└── camera.py
back_end_handler.py
"""app/apis/views/back_end_handler.py
"""
from flask import Response, jsonify
from app import secret_key
from app.apis.views.camera import Camera
def handler(req):
"""handler
"""
param1 = req.get('param1')
param2 = req.get('param2')
if param1 == 'video_feed':
return _video_feed(req=param2)
return jsonify({'message': 'no route matched with those values'}), 200
def _video_feed(req):
"""_video_feed
"""
if req.get('secret_key', '') != secret_key:
return jsonify({'message': 'no route matched with those values'}), 200
return Response(_generator(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame')
def _generator(camera):
"""_generator
"""
while True:
frame = camera.frame()
yield b'--frame\r\n'
yield b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n'
camera.py
"""app/apis/views/camera.py
"""
import cv2
class Camera():
"""Camera
"""
def __init__(self):
self.video_capture = cv2.VideoCapture(-1)
def __del__(self):
self.video_capture.release()
def frame(self):
"""frame
"""
_, frame = self.video_capture.read()
_, image = cv2.imencode('.jpeg', frame)
return image.tobytes()