99 lines
3.1 KiB
Python
99 lines
3.1 KiB
Python
"""
|
|
Requirements Step by Step:
|
|
sudo apt update
|
|
sudo apt install libjpeg62-turbo-dev python3-prctl python3-picamera2 python3-libcamera libcamera-apps libcamera-dev
|
|
python3 -m venv --system-site-packages env
|
|
source env/bin/activate
|
|
pip install flask pillow
|
|
"""
|
|
|
|
from flask import Flask, Response
|
|
from picamera2 import Picamera2
|
|
from PIL import Image
|
|
import io
|
|
import base64
|
|
import serial
|
|
import time
|
|
import cv2
|
|
|
|
s = serial.Serial('/dev/ttyACM1', 115200, timeout=1) # serielle verbindung zum ESP aufbauen
|
|
time.sleep(2)
|
|
|
|
'''
|
|
Kamera Konfigurieren mit einem Format von 640x480
|
|
'''
|
|
picam2 = Picamera2()
|
|
config = picam2.create_preview_configuration(main={"size": (640, 480)})
|
|
picam2.configure(config)
|
|
picam2.start()
|
|
|
|
MAX_RAW = 1200
|
|
MAX_B64 = 1200
|
|
|
|
# TODO: map image to MAX_B64
|
|
|
|
def encode_image_to_b64_with_limit(img: Image.Image, max_b64: int = 1024, scale_step: float = 0.9, initial_quality: int = 30, min_quality: int = 5) -> str:
|
|
quality = initial_quality
|
|
working_img = img.copy()
|
|
|
|
while True:
|
|
buf = io.BytesIO()
|
|
working_img.save(buf, format="JPEG", quality=quality, optimize=True)
|
|
jpeg_bytes = buf.getvalue()
|
|
|
|
b64 = base64.b64encode(jpeg_bytes).decode("utf-8")
|
|
|
|
if len(b64) <= max_b64 or (working_img.width < 2 or working_img.height < 2):
|
|
return b64
|
|
|
|
|
|
# if len(jpeg_bytes) <= MAX_RAW:
|
|
# return jpeg_bytes
|
|
|
|
new_w = max(1, int(working_img.width * scale_step))
|
|
new_h = max(1, int(working_img.height * scale_step))
|
|
working_img = working_img.resize((new_w, new_h), Image.LANCZOS)
|
|
|
|
if quality > min_quality:
|
|
quality = max(min_quality, int(quality * scale_step))
|
|
|
|
def init_serial():
|
|
global s
|
|
s = None
|
|
while s is None:
|
|
try:
|
|
s = serial.Serial('/dev/ttyACM1', 115200, timeout=1)
|
|
except Exception:
|
|
time.sleep(1)
|
|
continue
|
|
|
|
def gen():
|
|
global s
|
|
while True:
|
|
arr = picam2.capture_array("main") # Einen frame holen
|
|
img = Image.fromarray(arr).convert("L") # Bild in Graustufen umwandeln
|
|
# TODO: skip config with 640x480
|
|
img = img.resize((640, 480), Image.LANCZOS)
|
|
|
|
b64 = encode_image_to_b64_with_limit(img, MAX_B64) # Bildqualität reduzieren bis es eine Größe von maximal MAX_B64 (1200) hat
|
|
print("Image_b64 size: " + str(len(b64)))
|
|
|
|
try:
|
|
s.write(("{\"type\":\"image\",\"data\":\"" + b64 + "\"}\n").encode("utf-8")) # Frame als JSON-String an den ESP verschicken
|
|
# s.write((b64 + "\n").encode("utf-8"))
|
|
except Exception:
|
|
'''
|
|
War das schreiben über seriell nicht möglich wird ein erneuter Verbindungsaufbau versucht bis die Verbindung wieder steht.
|
|
Es wird davon ausgegangen das wir die Verbindung verloren haben und deswegen das schreiben nicht möglich war.
|
|
'''
|
|
init_serial()
|
|
time.sleep(0.1)
|
|
|
|
if __name__ == "__main__":
|
|
# app.run(host="0.0.0.0", port=1234, threaded=True)
|
|
try:
|
|
gen()
|
|
except KeyboardInterrupt:
|
|
serial.close()
|
|
print("Uebertragung beenden")
|