I have the following code:
app = Flask(__name__)
@app.route("/")
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('Round time: ', str(
datetime.timedelta(seconds=time_taken))[2:7])
times.append(time_taken)
average = sum(times) / len(times)
print('Average 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)
return render_template('theme1.html', output2=total)
if __name__ == "__main__":
app.run(debug=True)
HTML Code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<meta http-equiv="refresh" content="10" >
<link rel= "stylesheet" href= "{{ url_for('static', filename='styles.css')}}">
</head>
<body>
<div >
<p>{{ output2 }}</p>
</div>
</body>
</html>
I need these values to update every 10 seconds or so, i was recommended to use ajax but i have no clue how to apply this, any help would be really appreciated, the python script uses opencv to detect objects in a live feed, "total" prints the amount of objects as an integer, this is what i am trying to get updated on my web page.
CodePudding user response:
A function will stop when it hits a return statement so your code will stop at the first iteration.
So instead create two routes, first delivers the webpage and second only the data.
create a periodic function in the main webpage which will fetch the data from the second route using get method.
also the http-eqiv=refresh
will refresh the webpage everytime it fetches the new data. But this implementation will not refresh the webpage but still update the webpage dynamically.
As your open cv code is in a loop you can create a generator function which will give the next value on each call. I will leave that to you.
here is my implementation
app = Flask(__name__)
@app.route("/")
def home():
return render_template('theme1.html')
@app.get("/update")
def update():
total = str(random.random()) ## replace this with what you want to send
return total
if __name__ == "__main__":
app.run(debug=True)
<!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>
EDIT: Here's a version with generator functions. This was made in a hurry so there are better ways to do this
app = Flask(__name__)
def output():
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('Round time: ', str(
datetime.timedelta(seconds=time_taken))[2:7])
times.append(time_taken)
average = sum(times) / len(times)
print('Average 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 # Yield the value to get values on demand
@app.route("/")
def home():
return render_template('theme1.html')
gen_total = output() # initate the function out of the scope of update route
@app.get("/update")
def update():
global gen_total # get the global iterator
# return the next value in iterator
return str(next(gen_total))
if __name__ == "__main__":
app.run(debug=True)