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!
Related
I'm currently trying to code something that will let websites view my webcam. I'm roughly following the tutorial linked on this website, except using Python and pygame instead of Processing.
At the moment, my code is grabbing a pygame image (which was originally a SimpleCV image), attempting to convert it into jpg format, and send it over websockets to the client where it will display it inside an img tag. However, I can't seem to figure out how to convert a pygame image into jpg and get it to display properly on the web browser.
This is my code for the server, which uses Flask and gevent:
#!/usr/bin/env python
import base64
import cStringIO
import time
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from flask import Flask, request, render_template
import pygame
pygame.init()
import SimpleCV as scv
app = Flask(__name__)
cam = scv.Camera(0)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/camera')
def camera():
if request.environ.get('wsgi.websocket'):
ws = request.environ['wsgi.websocket']
while True:
image = cam.getImage().flipHorizontal().getPGSurface()
data = cStringIO.StringIO()
pygame.image.save(image, data)
ws.send(base64.b64encode(data.getvalue()))
time.sleep(0.5)
if __name__ == '__main__':
http_server = WSGIServer(('',5000), app, handler_class=WebSocketHandler)
http_server.serve_forever()
This is my HTML file:
<!DOCTYPE HTML>
<html>
<head>
<title>Flask/Gevent WebSocket Test</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
if ("WebSocket" in window) {
cam = new WebSocket("ws://" + document.domain + ":5000/camera");
cam.onmessage = function (msg) {
$("#cam").attr('src', 'data:image/jpg;base64,' + msg.data);
};
cam.onerror = function(e) {
console.log(e);
}
} else {
alert("WebSocket not supported");
}
});
</script>
</head>
<body>
<img id="cam" src="" width="640" height="480" />
</body>
</html>
These are the specific lines that I think I'm having trouble with:
while True:
image = cam.getImage().flipHorizontal().getPGSurface()
data = cStringIO.StringIO()
pygame.image.save(image, data)
ws.send(base64.b64encode(data.getvalue()))
time.sleep(0.5)
Currently, if I try and run my code, going to localhost:5000 will display an invalid jpg image. It also becomes really laggy if I try running it on Firefox, but that may be an unrelated issue that I can debug later.
I've checked and made sure that the pygame image is a valid one, since I'm converting it from another library, and also checked that I was using websockets correctly by sending text data back and forth.
I've also tried calling pygame.image.to_string to try and convert the pygame surface into RGB format, but that also doesn't work.
What am I doing wrong?
Using the underlying PIL image, we can write to a file-like object, read back and base-64 encode it:
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from flask import Flask, request
from time import sleep
from cStringIO import StringIO
import pygame
pygame.init()
import SimpleCV as scv
app = Flask(__name__)
cam = scv.Camera(0)
#app.route('/camera')
def camera():
if request.environ.get('wsgi.websocket'):
ws = request.environ['wsgi.websocket']
while True:
fp = StringIO()
image = cam.getImage().flipHorizontal().getPIL()
image.save(fp, 'JPEG')
ws.send(fp.getvalue().encode("base64"))
#fp.close() << benchmark and memory tests needed
sleep(0.5)
if __name__ == '__main__':
http_server = WSGIServer(('',5000), app, handler_class=WebSocketHandler)
http_server.serve_forever()
I'm fighting with the same issue and the problem is a double codification. In the Python file, you have to remove the line "ws.send(base64.b64encode(data.getvalue()))" and send the image without encoded. Then in the js file, your script will make the codification and that all.
I am making a web app that generates a QR code using input from the user and saves it into a specified file. After the QR code is saved, It should display the generated QR code in a small box next to the input box.
I am attempting to do this by having a GET submit button that goes to this route but I receive an error every time I click it.
The first block of code is for receiving the input and making a QR code out of it, and the second is my attempt to send back the finished PNG and display it.
Python Code:
#app.route('/', methods= ['POST'])
def textfield():
text = request.form['text']
processed_text = text
if processed_text == '':
flash("Please enter a value!")
else:
QR(processed_text)
return render_template('base.html')
#app.route('/QR', methods= ['GET'])
def QRimage(text):
im = Image.open(f'{text}.png')
data = io.BytesIO()
im.save(data, "PNG")
encoded_img_data = base64.b64encode(data.getvalue())
img_data = encoded_img_data.decode('utf-8')
return render_template('base.html', value=img_data)
Here is the HTML to attempt to display the image:
<img id="picture" src="data:image/jpeg;base64,{{ img_data }}">
And the GET button that routes to /QR:
<form action="/QR" method="GET">
<button type="submit" type="button">QR Button</button>
Flask looks for static files in the static folder which is the default.
use flask.send_from_directory(directory, filename, **options) if you want to serve files from another directory. This is a secure way to quickly expose static files.
#app.route('/QR', methods= ['GET'])
def QRimage(text):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename);
Reference:
API — Flask Documentation (1.1.x) (2021). Available at: https://flask.palletsprojects.com/en/1.1.x/api/#flask.send_from_directory (Accessed: 24 April 2021).
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.
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.
I use cv.CaptureFromCAM in a Django app, but my script block a this command.Without Django, it works and I can see my webcam turns on.
Here's my script :
import cv, Image
def takePhoto():
"""Return a PIL img"""
print "Taking photo"
cv_img = cv.QueryFrame( cv.CaptureFromCAM(0) )
pil_img = Image.fromstring("L", cv.GetSize(cv_img), cv_img.tostring())
return pil_img
If someone know why I can't use a method like cv.CaptureFromCAM in Django's scripts ?
PS : I already tried to decompose in several lines...
Resolved :
I put cv.CaptureFromCAM in a var settings.py for launch it at website start up.
I access to that var for take a photo, example :
In settings.py:
CAM = cv.CaptureFromCAM(0)
In views.py:
from django.http import HttpResponse
import cv, Image
def instantPhoto(request) :
cv_img = cv.QueryFrame( CAM[0] )
pil_img = Image.fromstring("RGB", cv.GetSize(cv_img), cv_img.tostring())
response = HttpResponse(mimetype="image/png")
pil_img.save(response, "PNG")
return response