Foreword¶
If readers have used image recognition APIs from Baidu, such as Baidu’s fine-grained image recognition interface, they should be familiar with the process. Here, we’ll omit considerations for security and other aspects. The general process of this interface is: we upload images to Baidu’s server, the server converts these images into vector data, and finally, this data is passed to a deep learning prediction interface (e.g., PaddlePaddle’s prediction interface) to obtain the prediction result, which is then returned to the client. This is just a simplified flow; the actual complexity is far greater, but we only need to understand this to build our own image recognition interface.
Understanding Flask¶
Installing Flask is straightforward with a single command:
pip install flask
We also use flask_cors, so install this library as well:
pip install flask_cors
Create a paddle_server.py file and write a simple program to learn how to use the Flask framework. First, import the required libraries:
import os
import uuid
import numpy as np
import paddle.fluid as fluid
from PIL import Image
from flask import Flask, request
from flask_cors import CORS
from werkzeug.utils import secure_filename
Write a hello_world() function. Use @app.route('/') to specify the access path, and return the string Welcome to PaddlePaddle:
# Root path, returns a string
@app.route('/')
def hello_world():
return 'Welcome to PaddlePaddle'
Start the service. On Ubuntu, you may need to run the program as root:
if __name__ == '__main__':
# Start the service and specify the port number
app.run(port=80)
Access http://127.0.0.1 in your browser, and you’ll see the previously defined string:
Welcome to PaddlePaddle
To predict images, uploading images is essential. Let’s learn how to use Flask to upload images:
- secure_filename ensures the uploaded file name is correctly retrieved.
- /upload specifies the access address for this function.
- methods=['POST'] restricts this path to POST requests only.
- f = request.files['img'] reads the file with the form name “img”.
- f.save(img_path) saves the file to the specified path.
# Upload file
@app.route('/upload', methods=['POST'])
def upload_file():
f = request.files['img']
# Set the save path
save_father_path = 'images'
img_path = os.path.join(save_father_path, str(uuid.uuid1()) + secure_filename(f.filename).split('.')[-1])
if not os.path.exists(save_father_path):
os.makedirs(save_father_path)
f.save(img_path)
return 'success, save path: ' + img_path
Start the service again:
if __name__ == '__main__':
# Start the service and specify the port number
app.run(port=80)
Create an index.html file and write a form to submit to the upload path http://127.0.0.1/upload with enctype="multipart/form-data" and method="post":
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Prediction</title>
</head>
<body>
<!--Form to upload images-->
<form action="http://127.0.0.1/upload" enctype="multipart/form-data" method="post">
Select an image to upload: <input type="file" name="img"><br>
<input type="submit" value="Upload">
</form>
</body>
</html>
Open the webpage, select an image, and click “Upload”. A success message will appear with the saved path, e.g.:
success, save path: images/65d7661a-3892-11e9-a7b7-f44d30185f58.jpg
Prediction Service¶
Add an image preprocessing function to paddle_server.py. This function takes the saved image path, preprocesses the image, and returns the processed data:
# Preprocess the image
def load_image(file):
img = Image.open(file)
# Resize the image to a uniform size
img = img.resize((224, 224), Image.ANTIALIAS)
# Convert to numpy array
img = np.array(img).astype(np.float32)
# Convert to CHW format
img = img.transpose((2, 0, 1))
# Convert to BGR and normalize
img = img[(2, 1, 0), :, :] / 255.0
img = np.expand_dims(img, axis=0)
return img
The following is the PaddlePaddle code using the prediction code from the article PaddlePaddle From Beginner to Expert - Custom Image Dataset Recognition:
# Create an executor
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# Path to save the prediction model
save_path = 'infer_model/'
# Load inference program, input variable names, and target variables from the model
[infer_program, feeded_var_names, target_var] = fluid.io.load_inference_model(dirname=save_path, executor=exe)
The core code of this backend service accepts uploaded images, performs prediction, and returns results:
@app.route('/infer', methods=['POST'])
def infer():
f = request.files['img']
# Save the uploaded image
save_father_path = 'images'
img_path = os.path.join(save_father_path, str(uuid.uuid1()) + '.' + secure_filename(f.filename).split('.')[-1])
if not os.path.exists(save_father_path):
os.makedirs(save_father_path)
f.save(img_path)
# Start image prediction
img = load_image(img_path)
result = exe.run(
program=infer_program,
feed={feeded_var_names[0]: img},
fetch_list=target_var
)
# Get the label with the highest probability
lab = np.argsort(result)[0][0][-1]
# Define category names
names = ['苹果', '哈密瓜', '胡萝卜', '樱桃', '黄瓜', '西瓜']
# Format and return the result
r = '{"label":%d, "name":"%s", "possibility":%f}' % (lab, names[lab], result[0][0][lab])
print(r)
return r
Start the service again:
if __name__ == '__main__':
# Start the service and specify the port number
app.run(port=80)
Update index.html to add a form for the prediction interface:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Prediction</title>
</head>
<body>
<!--Form to call the server's prediction interface-->
<form action="http://127.0.0.1/infer" enctype="multipart/form-data" method="post">
Select an image to predict: <input type="file" name="img"><br>
<input type="submit" value="Predict">
</form>
</body>
</html>
After uploading and clicking “Predict”, the server returns a JSON string with the label, name, and probability, e.g.:
{"label":1, "name":"哈密瓜", "possibility":0.982786}
GitHub Repository¶
GitHub Repository: https://github.com/yeyupiaoling/LearnPaddle2/tree/master/note14
Previous Chapter: PaddlePaddle From Beginner to Expert - Thirteen - Custom Image Data Generation¶
Next Chapter: PaddlePaddle From Beginner to Expert - Fifteen - Deploying Prediction Models to Android Phones¶
References¶
- https://blog.csdn.net/qq_33200967/article/details/79571511
- http://blog.csdn.net/u011054333/article/details/70151857