OpenCV + flask - show different image, when JSON received - python

I have a simple FLASK web server, which is waiting for the JSON request.
When JSON is received as {"card": "AC"} it will show me the AC.png card image with OpenCV.
That works. But then it should update & show me the JC.png card when any different JSON is received... that's when it freezes. What am I doing wrong?
# app.py
from flask import Flask, request
import cv2
app = Flask(__name__)
img = cv2.imread('AC.png',1)
img2 = cv2.imread('JC.png',1)
#make window fullscreen
# cv2.namedWindow("window", cv2.WND_PROP_FULLSCREEN)
# cv2.setWindowProperty("window",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
#app.route('/webhook', methods=['POST'])
def webhook():
if request.method == 'POST':
#print("Data received from Webhook is: ", request.json)
message = request.json
#print(message["card"])
#When JSON with "AC" received, show AC card
if message["card"] == "AC":
print('first')
cv2.imshow("window", img)
cv2.waitKey(1)
else:
print('second')
cv2.imshow("window", img2) #show JC card
cv2.waitKey(1)
return "Webhook received!"
if __name__ == "__main__":
from waitress import serve
serve(app, host="0.0.0.0", port=8080)
Thanks

Related

Problem when accessing Live Stream multiple times in Flask

I am trying to take a RTSP video input and apply analytics and show it as a live stream. I am using Open CV and PyFlask for this purpose.
I can manage to show the output successfully. However, I am having issues when I try to access the host from multiple devices.
If I access from single device, it's working like a charm but when I try to access from multiple devices at the same time, it's breaking.
RTSP = f'''rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4'''
# importing
import cv2
from flask import Flask, render_template, Response
app= Flask(__name__)
cap= cv2.VideoCapture(RTSP)
def gen_frames():
while True:
success, frame = cap.read()
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield(b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/video')
def video():
return Response(gen_frames(), mimetype = 'multipart/x-mixed-replace; boundary=frame')
if __name__ == "__main__":
app.run(debug = False, host = '0.0.0.0', port = 8018)
Need some expert advice. Thanks in advance.
Note - index.html code is given below:
<!DOCTYPE html>
<html>
<body>
<h1>Live streaming</h1>
<div>
<img src="{{ url_for('video') }}"/>
</div>
</body>
</html>

Close OpenCV camera stream at page close (Flask)

I'm making a simple video stream to browser app on my Rpi.
I would like to know if there is a way to open a camera only when access the flask page and close the camera if page is not seen anymore. I don't want to let camera open whole time.
I was trying something like this, but it would involve button press (POST request) to flask server every time I want to close the tab what is little bit awkward.
from flask import Flask, render_template, Response, request
import cv2
from time import sleep
app = Flask(__name__)
CAMERA = None
def gen_frames():
global CAMERA
CAMERA = cv2.VideoCapture(0)
sleep(3)
CAMERA.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
CAMERA.set(cv2.CAP_PROP_FRAME_HEIGHT, 960)
while True:
success, frame = CAMERA.read()
if not success:
break
else:
_, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
# concat frame one by one and show result
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#app.route('/video_feed')
def video_feed():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
#app.route('/', methods = ['POST', 'GET'])
def index():
global CAMERA
if request.method == 'POST':
if request.form['webcam']:
if CAMERA != None and CAMERA.isOpened():
CAMERA.release()
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)

code works fine locally but when deployed to heroku get "error: (-215:Assertion failed) !image.empty()"

In python I am deploying little basic camera streaming Heroku flask app(full code here. Locally, the code works as expected I am able to see my webcam when I run the code on my computer, when I deploy to Heroku I get this error
error: (-215:Assertion failed) !image.empty()
running heroku logs --tail command this is what I get in the logs
mainly this error
cv2.error: OpenCV(4.2.0) /io/opencv/modules/imgcodecs/src/loadsave.cpp:877: error: (-215:Assertion failed) !image.empty() in function 'imencode'
app code:
from flask import Flask, render_template, request, Response
from camera import VideoCamera
import cv2
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/submit', methods=['POST'])
def submit():
if request.method == 'POST':
password = request.form['password']
if password == 'testing':
return render_template('stream_static.html')
else:
return render_template('index.html', message='wrong or empty password')
#app.route('/static', methods=['POST'])
def play():
return render_template('static.html')
#app.route('/stream', methods=['POST'])
def stream():
return Response(gen(VideoCamera()), mimetype='multipart/x-mixed-replace;boundary=frame')
if __name__ == '__main__':
app.debug = True
app.run()
camera.py code:
import cv2
class VideoCamera(object):
def __init__(self):
self.video = cv2.VideoCapture(0)
def __del__(self):
self.video.release()
def get_frame(self):
success, image = self.video.read()
ret, jpeg = cv2.imencode('.jpg', image)
return jpeg.tobytes()
searching error code online people say to check that its not empty, it's not since the program works as it should(camera streams ok on browser) locally right or is it trying to access the "camera" on the heroku server. If I use this code the heroku deployed app displays video properly. Any help would be appreciated, thank you.

Raspberry Pi freezes when streaming video with Flask

I have this Flask-Socketio app which shows the Raspberry Pi system info like temperature, RAM and Disk space. This app also has a video streaming component VideroStream.py.
I have added VideroStream.py route to index.py using Flask blueprint. When accessing the app in browser RPI freezes and in error log it shows:
> Truncated or oversized response headers received from daemon process
> 'rpiWebServer': /var/www/rpiWebServer.wsgi
Why this is happening?
Is this line correct videoStreamBp = Blueprint('video_stream', __name__) ?
Should I use videopi instead of video_stream?
When I create a standalone app without blueprint and Socketio streaming works perfectly.
UPDATE:
When I remove image src="{{url_for(videopi)}}" page loads without video as expected.
index.py
from flask import Flask, render_template, Response, request
from flask_socketio import SocketIO, emit
from threading import Lock
#for temp
import os
import datetime
import ast
import psutil
app = Flask(__name__)
#for socket
async_mode = None
socketio = SocketIO(app, async_mode=async_mode)
#thread = None
thread1 = None
thread_lock = Lock()
from findPath import findPathBp
app.register_blueprint(findPathBp)
from videoStream import videoStreamBp
app.register_blueprint(videoStreamBp)
# GET RAM info
def getSysInfo():
count = 0
while True:
#RAM
memory = psutil.virtual_memory()
ramAvailable = round(memory.available/1024.0/1024.0,1) # Divide from Bytes -> KB -> MB
ramTotal = round(memory.total/1024.0/1024.0,1)
#Temp
temp = os.popen("vcgencmd measure_temp").readline()
cpuTemp = temp.replace("temp=","")
cpuTemp = cpuTemp.replace("'C","°C")
#DISK
disk = psutil.disk_usage('/')
# Divide from Bytes -> KB -> MB -> GB
diskFree = round(disk.free/1024.0/1024.0/1024.0,1)
diskTotal = round(disk.total/1024.0/1024.0/1024.0,1)
socketio.sleep(1)
count += 1
socketio.emit('sysStat',{'available': ramAvailable, 'total': ramTotal, 'temp': cpuTemp, 'freeDisk': diskFree, 'totalDisk': diskTotal }, namespace='/getSysInfo')
#index route
#app.route("/", methods=['GET', 'POST'])
def index():
return render_template('index.html', result= timeString)
#socket IO
# Get system info
#socketio.on('connect', namespace='/getSysInfo')
def test_connect():
global thread1
with thread_lock:
if thread1 is None:
thread1 = socketio.start_background_task(getSysInfo)
if __name__ == "__main__":
socketio.run(host='192.168.225.47', port=80, debug=True, threaded=True)
videoStream.py
from flask import Blueprint, render_template, Response
videoStreamBp = Blueprint('video_stream', __name__)
# Raspberry Pi camera module (requires picamera package)
from camera_pi import Camera
def gen(camera):
# Video streaming generator function.
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#videoStreamBp.route('/videopi')
def video_stream():
return Response(gen(Camera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
index.html
<div class='fifty'>
<p class='tempConainer'>CPU temperature is: <span id='temp'>Loading..</span></p><br>
<p class='tempConainer'>RAM available: <span id='ramInfo'>Loading..</span></p>
<p class='tempConainer'>RAM total: <span id='ramInfo1'>Loading..</span></p><br>
<p class='tempConainer'>Free disk: <span id='freeDisk'>Loading..</span></p><br>
<p class='tempConainer'>Total disk: <span id='totalDisk'>Loading..</span></p><br>
</div>
<div class='fifty'>
<img src="{{url_for(videopi)}}">
</div>
Finally I found that the src attribute of image was wrong and I changed it to this:
<img src='/videopi'>
Works like a charm.

Running background Celery task in Flask

Problem has been updated to include progress made
I have the following code and my celery tasks kick off fine, I just don't know where I should store the async result so that I can look at it again later
#!/usr/bin/env python
"""Page views."""
from flask import render_template, request
from flask import Flask
from celerytest import add
from time import sleep
app = Flask(__name__)
async_res = []
#app.route('/', methods=['GET', 'POST'])
def run():
if request.method == 'GET':
return render_template("template.html")
else:
form = request.form
n1 = str(form.get("n1"))
n2 = str(form.get("n2"))
aysnc_res = add.delay(n1,n2)
return render_template("loading.html")
#app.route('/loading')
def check_if_complete():
if async_res.ready() == True:
return render_template("template2.html", val=async_res.get())
else:
sleep(5)
return render_template("loading.html")
if __name__ == '__main__':
app.run()
It appears that storing async_res as a global variable in my flask app causes server errors. So what's the best method of storing the result so that I can check on it in my "loading page"
I ended up being able to save the ID of my task in the session dictionary in Flask
See code below:
#!/usr/bin/env python
"""Page views."""
from flask import render_template, request
from flask import Flask
from celerytest import add
from time import sleep
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def run():
if request.method == 'GET':
return render_template("template.html")
else:
form = request.form
n1 = str(form.get("n1"))
n2 = str(form.get("n2"))
aysnc_res = add.delay(n1,n2)
session['TASK_ID'] = async_res.id
return render_template("loading.html")
#app.route('/loading')
def check_if_complete():
aysnc_res = session['TASK_ID']
if async_res.ready() == True:
return render_template("template2.html", val=async_res.get())
else:
sleep(5)
return render_template("loading.html")
if __name__ == '__main__':
app.run()

Categories

Resources