Python Flask app posting an image and using cv2.imread function - python

I made a small python app for face recognition and now I am converting it into a flask application.
#app.route('/save', methods=['POST'])
def save_image():
if request.method == 'POST':
if 'imageFile' not in request.files:
return {"detail": "No file found"}, 400
image = request.files['imageFile']
imageFileName = secure_filename(image.filename)
image.save('./images/' + imageFileName)
image = cv2.imread('./images/' + imageFileName)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
face_encoding = face_recognition.face_encodings(image)[0]
np.savetxt('./encodings/' + request.form['indexNumber'] + '.csv', face_encoding, delimiter=',')
return 'saving image'
In the above code I have saved the image posted to the server and read it again using cv2.imread and have later used it to create the face encoding. What I want is to do this without saving the image in the server. Is there a way to directly read the image posted and use like above?

Related

Flask Image Upload Generating a Border

I'm uploading image in Flask and after uploading the image is getting a black border. I'm using the image further in Processing and after processing the border is visible in white color, I tried the same Image processing code on a image taken directly from folder and not uploaded through flask and it working correctly and no borders are formed. Can Someone please suggest what to do ?
Here is my code of flask to upload file, form type is multipart form :
#app.route('/success', methods = ['POST'])
def success():
if request.method == 'POST':
f = request.files['file']
f.save(f.filename)
... next logic

Object Detection Flask App cuasing image overwrites in consecutive requests

I'm trying to implement an object detection web app using flask.
The flow of my app is:
The user will upload an image.
The image will get saved to a directory ('/static/uploads' folder)
A function called 'get_images' will read the image, load the object detector model, and finally write the image with detection at the specified folder ('/static/detections/')
A template called 'uploaded.html' will then display the uploaded image from the upload directory, and also the image with detections from detections directory.
The app runs fine when ran for the first time and when the server is launched again. But if I try to upload another image after running detection on the first image, the image with detections get overwritten with the previous image but its name is preserved, ultimately resulting in the first image with detections being displayed again and again. My flask app (app.py) code is as follows:
app = Flask(__name__)
UPLOAD_FOLDER = './static/uploads/'
DETECTION_FOLDER = './static/detections/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['DETECTION_FOLDER'] = DETECTION_FOLDER
# app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
# app.config['TEMPLATES_AUTO_RELOAD'] = True
#app.route("/")
def index():
return render_template("index.html")
#app.route("/about")
def about():
return render_template("about.html")
#app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
# create a secure filename
filename = secure_filename(f.filename)
print(filename)
# save file to /static/uploads
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
print(filepath)
f.save(filepath)
print(filepath)
get_image(filepath,filename)
return render_template("uploaded.html", display_detection = filename, fname = filename)
if __name__ == '__main__':
app.run(port=4000, debug=True)
Function get_image() is a method of file app_helper.py and is ultimately performing a cv2.imwrite on the image with detections. I thought the problem might be with this section of the code as this is the only place where any 'writing' is done. So, I ran the app_helper.py function multiple times, and not once the images were overwritten (in the '/static/detections/' folder).
I'm including some images to explain my concern better,
Page after running the first detection looks like this
'/static/detections/' folder after first run
'/static/uploads/' folder after uploading my 2nd image
As soon I run the detector, this is what happens in the '/static/detections/' folder, though the file name is preserved
And since the new file name (phone.jpg) is now associated with same image as 'phone2.jpg' the detection image doesn't not change. I kept repeating this, and any new image I uploaded - it got overwritten by 'phone2.jpg'!
I repeat, I tried running get_images() method separately - even after running it on multiple images NO SUCH OVERWRITES took place. For ref, get_images() method is a slight modification of this code. ('Uploaded.html' relies on the filename to display images, which is being maintained here)
e.g. get_images('/data/images/kite.jpg','kite.jpg')
ps- I also tried adding,
# app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
# app.config['TEMPLATES_AUTO_RELOAD'] = True
also, after the first execution, I emptied the uploads and detections folder to check if that helps,
But these didn't work.
Kindly help me out, I want my app to bear multiple runs (of upload and detect) without such issues.
Thank you.

How do I save a image using a flask API then return it to my React App can use it

I am trying to use my Flask API to save an image to the database OR just a file system but this is something I have never done and am getting nowhere with it.
I would like to be able to return the image back when the route is called and be able to use it in my ReactJS Application using just a img tag.
All I have been able to find is how to save the image to the Database and then download it using a route. I need to be able to return it. (It works just not what I need.)
Here is what that was:
#app.route('/img-upload', methods=['POST'])
def img_upload():
file = request.files['image']
newFile = Mealplan(name=file.filename, data=file.read())
db.session.add(newFile)
db.session.commit()
return jsonify({"Done!" : "The file has been uploaded."})
#app.route('/get-mealplan-image/<given_mealplan_id>')
def download_img(given_mealplan_id):
file_data = MealPlan.query.filter_by(id=given_mealplan_id).first()
return send_file(BytesIO(file_data.data), attachment_filename=file_data.name, as_attachment=True)
Save the files on the file system will be a more proper method. Here is a minimal example:
from flask import send_from_directory
basedir = os.path.abspath(os.path.dirname(__file__))
uploads_path = os.path.join(basedir, 'uploads') # assume you have created a uploads folder
#app.route('/img-upload', methods=['POST'])
def upload_image():
f = request.files['image']
f.save(os.path.join(uploads_path , f.filename)) # save the file into the uploads folder
newFile = Mealplan(name=f.filename) # only save the filename to database
db.session.add(newFile)
db.session.commit()
return jsonify({"Done!" : "The file has been uploaded."})
#app.route('/images/<path:filename>')
def serve_image(filename):
return send_from_directory(uploads_path, filename) # return the image
In your React app, you can use the filename to build to the image URL: /images/hello.jpg
Update:
If you can only get the id, the view function will be similar:
#app.route('/get-mealplan-image/<given_mealplan_id>')
def download_img(given_mealplan_id):
file_data = MealPlan.query.filter_by(id=given_mealplan_id).first()
return send_from_directory(uploads_path, file_data.name)

how can I open an image of FileStorage type in Pillow

in my flask app after receiving POST request and running the code
image = request.files['image']
image variable have type
<FileStorage: 'image.png' ('image/png')>
how can i convert it to Pillow image or open with Image.open() ?
FileStorage is not image type but only wrapper on normal files like PNG/JPG/PDF/Excel/etc. which flask uses to keep information about original files and which gives you direct access to original file - probably as file handler - and Pillow can use it directly to read image (without saving to file, and without using io.Bytes to create file image in memory)
image = request.files['image']
img = Image.open(image) # load with Pillow
print(img.size) # show image size (width, height)
img = img.convert('L') # convert to greyscale
img.save('output.png') # save it
#draw = ImageDraw.Draw(img) # create object to draw figures or text on image
All modules/functions which can use file handler instead of filename (to read file) should read from FileStorage without problem.
EDIT:
Minimal working code - tested with images .png, .jpg, .webp
from flask import Flask, request, render_template_string
from PIL import Image
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
print(request.files)
if request.files:
image = request.files['image']
# pillow
img = Image.open(image)
print(img.size)
img = img.convert('L') # greyscale
img.save('output.png')
return render_template_string('''<form method="POST" enctype="multipart/form-data">
<input type="file" name="image"/>
<button type="submit">Submit</button>
</form>''')
if __name__ == '__main__':
app.run(debug=True)
#furas thank you! Your tip on image.seek(0) worked for me, this was the cause of my issue. My pointer was at the end of file when I was trying to access it after verifying.

Converting base64 to .jpg file, then saving in Django database

def upload_image(request):
if request.is_ajax and request.POST:
image = request.POST.get('image')
image_name = request.POST.get('image_name')
imgdata = base64.b64decode(image + '==')
extension = image_name.split('.')[1].lower()
image_name = '{}_{}_profile_image.{}'.format(request.user.first_name, request.user.last_name, extension)
with open(image_name, "wb") as image_file:
image_file.write(imgdata)
upload = ProfileImage(
file=image_file,
user = request.user.username
)
upload.save()
data = {
}
return JsonResponse(data)
I am trying to crop images in Django using Croppie.js. The images are then uploaded to an S3 bucket.
I have the cropping working and it is returning the image cropped as a base64 string. I decoded it and write it to a new image file so that it could be then saved in the database.
When it it gets to upload.save() I am getting the error.
AttributeError: '_io.BufferedWriter' object has no attribute '_committed'
I'm not sure what the problem is. This is my first time working with base64 images and im not sure if im missing something when i'm converting back to a file or what is going on.
I was able to find a solution by using ContentFile
from django.core.files.base import ContentFile
def upload_image(request):
if request.is_ajax and request.POST:
image = request.POST.get('image')
image_name = request.POST.get('image_name')
extension = image_name.split('.')[1].lower()
image_name = '{}_{}_profile_image.{}'.format(request.user.first_name, request.user.last_name, extension)
imgStr = image.split(';base64')
data = ContentFile(base64.b64decode(imgStr[1]), name=image_name)
upload = Upload(
file=data,
user = request.user.username
)
# Saves upload to S3 bucket
upload.save()
data = {
}
return JsonResponse(data)
It converts the base64 string to a file that is readable by django.

Categories