Passing a cv2 frame from view to template - python

Basically, my django app needs to create an image in a view, and pass that to a template. This is easy for a string, but I can't find a way to do it with an image. I have read many stack overflow threads but none quite like mine, which is surprising.
I was trying variations of this as my view:
views.py:
def index(request):
while (True):
#video_capture = cv2.VideoCapture(0)
#ret, frame = video_capture.read()
img = "D:/Desktop/Tap/bsnsFaces.jpg"
frame = cv2.imread(img)
facesNumber ="Found {0} faces!".format(len(faces))
return render(request, 'result.html', {'p': facesNumber}, {'img': frame})`
With the {'img':frame} part at the end not being anywhere close to right. I tried a few things that I found on SO but nothing worked so far. I know that the image is static but eventually I want this to be a frame captured from a webcam so I can't solve this by using models (or can I?).
Thanks in advance for any advice!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Face detection with Django</title>
<p>{{ p }}</p>
<img src="data:image/jpg;base64, {{ img }}"></img>
</head>
<body>
</body>
</html>

I would suggest base64 encoding the frame and passing that string. That way you can pass the dynamically generated image from the views to the result.html to render. You can then display the base64 image in the result.html.
views.py
import cv2
import base64
def index(request):
#while (True): #Note: This loop is pointless, it will break when you return.
#video_capture = cv2.VideoCapture(0)
#ret, frame = video_capture.read()
img = "D:/Desktop/Tap/bsnsFaces.jpg"
frame = cv2.imread(img)
ret, frame_buff = cv2.imencode('.jpg', frame) #could be png, update html as well
frame_b64 = base64.b64encode(frame_buff)
facesNumber ="Found {0} faces!".format(len(faces))
# Note this was fixed to be one dict with the context variables
return render(request, 'result.html', {'p': facesNumber, 'img': frame_b64})
result.html
<img src="data:image/jpeg;base64, {{img}}"></img>
Just a note based on your while loop, if you want to be updating the page constantly from the webcam, this should be done clientside. Otherwise you will need to be constantly refreshing the page to see image updates. The client (result.html) can poll the server with AJAX for image updates, and refresh itself without actually reloading the entire result.html page.

Related

Trying to put PyTesseract OCR on web

I am using Pytesseract OCR for text detection and I am using a jupyter notebook to run it right now so the output is just popping up as another window. My output for the program is an image. Basically, I am trying to allow the user to input their own image and then the program will output another image on the website.
I am trying to do this but I am getting an error when I try loading the website. Here is my code:
import cv2
import matplotlib.pyplot as plt
from flask import Flask, request, Response
pytesseract.pytesseract.tesseract_cmd = 'C:\\Camera_Flask_App-main\\Tesseract\\tesseract.exe'
def pytess(img):
hImg,wImg,_ = img.shape
boxes = pytesseract.image_to_boxes(img)
for b in boxes.splitlines():
print(b[0])
b = b.split(' ')
x,y,w,h= int(b[1]),int(b[2]),int(b[3]),int(b[4])
cv2.rectangle(img,(x,hImg-y),(w,hImg-h),(0,0,255), 2)
cv2.putText(img,b[0],(x,hImg-y+25), cv2.FONT_HERSHEY_COMPLEX,1,(50,50,255),2)
##Detecting Words
hImg,wImg,_ = img.shape
boxes = pytesseract.image_to_data(img)
for x,b in enumerate(boxes.splitlines()):
if x!=0:
b = b.split()
if len(b)==12:
x,y,w,h= int(b[6]),int(b[7]),int(b[8]),int(b[9])
cv2.rectangle(img,(x,y),(w+x,h+y),(0,0,255), 2)
cv2.putText(img,b[11],(x,y), cv2.FONT_HERSHEY_COMPLEX,1,(50,50,255),2)
return img
# Initialize Flask application
app = Flask(__name__)
# POST request for running OCR
#app.route('/', methods=['GET', 'POST'])
def run_ocr():
image = request.files["image"]
#Read the image via file.stream, returns PIL image (may need to convert)
img = Image.open(image.stream)
# run ocr on image (you will need to update your function to return img)
processed_img = pytess(img)
# prepare image for response
_, img_encoded = cv2.imencode('.png', processed_img)
response = img_encoded.tostring()
# return png img with OCR shown
return Response(response=response, status=200, mimetype='image/png')
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=image>
<input type=submit value=Upload>
</form>
'''
if __name__ == '__main__':
app.run()
This is the error I am getting when I launch the site (not even put any picture):
error image
I got some feedback from another person and he said "You need to make sure that when you send the request you have the format as “multipart/form-data” with the “image” field set as the file" and when I asked him to help me fix the code he said, "I can’t change it here. It isn’t part of the code. Once you deploy the Flask server, it would be in the actual request to the server that you need to distinguish the data format". I am not really sure how to do this.
Can anyone help? Thanks!

Speech synthesis model creates audio but html page returns previous audio

I have a trained model for speech synthesis. It creates audio correctly everytime from textarea in html page and saves it static folder. But sometimes when i return audio from folder it brings the older one. It doesnt happen everytime but i couldnt find solution.
html audio code
{% if my_audio %}
<audio controls>
<source src="{{ url_for('static', filename='a.wav') }}" type="audio/wav"/>
</audio>
{% endif %}
flask code if you needed
from flask import Flask, render_template, request
import inference
app = Flask(__name__)
app.static_folder = 'static'
#app.route("/")
def home():
return render_template("index.html")
#app.route("/sentez", methods = ["POST"])
def sentez():
if request.method == "POST":
metin = request.form["metin"]
created_audio = inference.create_model(metin)
return render_template("index.html", my_audio = created_audio)
if __name__ == "__main__":
app.run();
This issue arises due to the browser fetching the file from its cache instead of the static folder, after the first run. You need to append a parameter to to the audio file's URL (or query string) that would be unique, so that it will fetch a new copy from the static folder. I suggest appending number of milliseconds elapsed, getTime() method does this in JavaScript.
The JavaScript equivalent for changing the source is as follows:
function playAudio() {
var audioFile = new Audio('./a.wav');
//URL is ./a.wav
audioFile.play()
}
change this to
function playAudio() {
var audioFile = new Audio('./a.wav?' + new Date().getTime());
//URL becomes something like ./a.wav?1623483193060
audioFile.play()
}
You can find out how to do the same in Flask for modifying the statement
{{ url_for('static', filename='a.wav') }}

Not able to send webcam video to template(.html) file using StreamingHttpResponse in Django 2.2

I recently started django and I wanted to see the video from the laptop camera to Django 2.2 based web app. I was successful in viewing the cam video by directly sending response to web using function display_livefeed. Following is my code of views.py of app 'camerafeed'
class mycamera(object):
def __init__(self):
self.frames = cv2.VideoCapture(0)
def __del__(self):
self.frames.release()
def get_jpg_frame(self):
is_captured, frame = self.frames.read()
retval, jframe = cv2.imencode('.jpg', frame)
return jframe.tobytes()
def livefeed():
camera_object = mycamera()
while True:
jframe_bytes = camera_object.get_jpg_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + jframe_bytes + b'\r\n\r\n')
#condition(etag_func=None)
def display_livefeed(self):
return StreamingHttpResponse(
livefeed(),
content_type='multipart/x-mixed-replace; boundary=frame'
)
I used path('monitor/', display_livefeed, name='monitor'), to see the video streaming on http://127.0.0.1:8000/monitor/ and it works perfectly >>Image from the streaming video<<
Now I wanted to display on the html template just line it is done here:
https://www.pyimagesearch.com/2019/09/02/opencv-stream-video-to-web-browser-html-page/
but this was done by using Flask. But I wanted to do the same using Django and got stuck. Here is the html file from the above link.
<html>
<head>
<title>Pi Video Surveillance</title>
</head>
<body>
<h1>Pi Video Surveillance</h1>
<img src="{{ url_for('video_feed') }}">
</body>
I tried to do like this using by making this function:
def video_feed(request):
return StreamingHttpResponse(
livefeed(), # Calling livefeed() function
content_type='multipart/x-mixed-replace; boundary=frame'
)
But it able to see the video on html page using path('', homePageView.as_view(), name='home'), and placing code below in views.py
class homePageView(TemplateView):
template_name = 'home.html'
I seen and tried following:
Django StreamingHttpResponse into a Template
Opencv Live Stream from camera in Django Webpage
But may be due to the fact that i am new to all these thing including web development, I might not able to get it done. Kindly help explaining me how to do this.
I am using python 3.7 and django 2.2
I solved it, disable the monitor path from the urlpatterns. I think that the trouble is that two sources are trying to use the camera. Just comment the
path('monitor', views.display_livefeed, name="monitor")
and it works.

How do I output plots from matplotlib to an html template in flask on a ubuntu server?

I am trying to set up a side project on DigitalOcean, and I am using the git framework from https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xvii-deployment-on-linux to get started.
Within this framework, I have added code within one of the flask routes (/explore) in which I generate a plot with matplotlib, and I want to return this plot as an object when I render the template as the return function of this route. I don't need to save the plot if it can be sent to the template without doing so (e.g with io.BytesIO()), but I have been unable to get the syntax correct to use this approach and get the plot to render in the resulting template.
While my attempts with io.BytesIO() have been unsuccessful, if it would help to output the results with that approach, please let me know how to best utilize it, and I will attempt to run this code with the suggested changes and report the results.
Thank you in advance!
I have tried to save the file and send it to the template, as well as sending the file data via BytesIO(), but neither approach has worked for me.
Below is my attempt to save the file to the static directory and send the image to the template, but a solution that works in this environment with io.BytesIO() or similar without saving the file would be even better.
Here is the code that I added to the explore route in /app/main/routes.py to save the plot image to the static directory and return the path to the template:
new_graph_name = url_for('static', filename='tmp_png.png')
plt.savefig(new_graph_name)
return render_template('index.html', url=new_graph_name)
Here is the code that I added to the index.html template:
{% if url %}
<img src={{ url }} alt="Chart" height="42" width="42" />
{% endif %}
In terms of saving the plot and then displaying it, could you try something similar to the code the below? This has worked for me recently.
In routes.py:
#app.route("/")
def index():
new_graph_name = 'tmp_png'
plt.savefig('static/images/' + new_graph_name)
return render_template("index.html", new_graph_name=new_graph_name)
In index.html:
<img src="{{ url_for('static', filename='images/' + new_graph_name + '.png') }}"
With Bytes.IO I think I've tried something like this before:
In routes.py:
import io
from io import BytesIO
import base64
img = io.BytesIO()
fig.savefig(img)
img.seek(0)
buffer = b''.join(img)
b2 = base64.b64encode(buffer)
barplot=b2.decode('utf-8')
I cannot remember how I displayed it in the .html template but could it just be a matter of passing it as a variable?

How to show webcam capture in Plone site using OpenCV?

I am using Plone 4.3. I am trying to create a face recognition system on the Plone site. I need to show webcam captures using a template page. My sample code is below. However, when I run this code, I can't get the captured image in the template file.
sample.py:
class video(BrowserView):
video=ViewPageTemplateFile('video.pt')
def chow(self):
return self.video()
def show_video(self):
import cv2.cv as cv
cv.NamedWindow("camera", 1)
capture = cv.CaptureFromCAM(0)
while True:
img = cv.QueryFrame(capture)
return img
video.pt:
<div id="res">
<!--Here face is url name-->
<img id="draw" tal:attributes="src python:context.absolute_url() + '/face'">
<!--the above line refers to call a method of show_video()-->
</div>
This is a good starting point: http://plone.org/products/collective.takeaportrait (activate the optional OpenCV integration).
Keep in mind that there's a big difference between showing the camera output on the screen (that is simply HTML 5) and performing face recognition server side.

Categories

Resources