I have the following code:
import cv2
import numpy as np
import time
import datetime
from flask import *
import random
from threading import Thread
app = Flask(__name__)
def Tracking():
lower = np.array([35, 192, 65])
upper = np.array([179, 255, 255])
video = cv2.VideoCapture(1, 0)
times = []
total = 0
is_round = False
while True:
success, img = video.read()
image = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(image, lower, upper)
blur = cv2.GaussianBlur(mask, (15, 15), 0)
circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 1, 14,
param1=34, param2=10, minRadius=4, maxRadius=10)
circles = np.uint16(np.around(circles))
if (len(circles[0, :]) == 7) and not is_round:
start_time = time.time()
is_round = True
curr_count = 0
round_total = 0
elif is_round:
if len(circles[0, :]) == 1:
end_time = time.time()
is_round = False
time_taken = end_time - start_time
print('time: ', str(
datetime.timedelta(seconds=time_taken))[2:7])
times.append(time_taken)
average = sum(times) / len(times)
print('Avg time: ', str(
datetime.timedelta(seconds=average))[2:7])
elif len(circles[0, :]) < 7:
curr_count = (7 - round_total) - len(circles[0, :])
total = curr_count
round_total = curr_count
for i in circles[0, :]:
cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 3)
yield total
@app.route("/")
def home():
return render_template('theme1.html')
gen_total = Tracking() # initate the function out of the scope of update route
@app.get("/update")
def update():
global gen_total
return str(next(gen_total))
if __name__ == "__main__":
app.run(debug=True)
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<link rel= "stylesheet" href= "{{ url_for('static', filename='styles.css')}}">
</head>
<body>
<div >
<p id="output"></p>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj 3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script>
function update(){
$.get("/update", function(data){
$("#output").html(data)
});
}
update()
var intervalId = setInterval(function() {
update()
}, 10000);
</script>
</body>
</html>
I am trying to get the variable 'average' to print to the webpage, i have already added 'total' to the webpage but i am not sure how to add average, this variable will not always have a value as a certain thing has to happen before it is given a value, any help would be appriciated. I am also not sure if this has to be converted to a string to be displayed, ajax is used in the html file to update the page every so often.
CodePudding user response:
To yield multiple values from your generator, either use a tuple, list, class, dictionary or other data structure. I'd suggest a dict which is simple but has nice naming semantics. yield dict(total=total, average=average)
.
Since average
is inside of a conditional branch, it's possible that yield
is reached without actually initializing this variable, which is illegal. Set a default value that's unconditionally within scope of the yield
statement so it's guaranteed to have a value.
Finally, return it as JSON to the client rather than text using Flask's jsonify
.
Here's a simplified example you can adapt:
app.py
from flask import Flask, jsonify, render_template
app = Flask(__name__)
def track():
total = 0
average = 0
while True:
if 1 == 1:
average = 2
total = 1
yield dict(total=total, average=average)
@app.route("/")
def home():
return render_template("theme1.html")
@app.get("/update")
def update():
return jsonify(next(gen_total))
if __name__ == "__main__":
gen_total = track()
app.run(debug=True)
templates/theme1.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj 3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
<div >
<p id="average"></p>
<p id="total"></p>
</div>
<script>
function update() {
$.get("/update", function (data) {
$("#average").text("average " data.average);
$("#total").text("total " data.total);
});
}
update();
var intervalId = setInterval(update, 10000);
</script>
</body>
</html>