Introduccion
El aprendizaje automático ya está en todas partes y es casi imposible encontrar software que no lo use directa o indirectamente. Creemos una pequeña aplicación que pueda cargar imágenes a un servidor para su posterior reconocimiento usando ML. Y luego los haremos disponibles a través de una aplicación móvil con búsqueda de texto por contenido.
Usaremos Flask para nuestra API REST, Flutter para aplicaciones móviles y Keras para aprendizaje automático. Usamos MongoDB como una base de datos para almacenar información sobre el contenido de las imágenes, y para información tomamos el modelo ResNet50 ya entrenado. Si es necesario, podemos reemplazar el modelo utilizando los métodos save_model () y load_model () disponibles en Keras. Esto último requerirá aproximadamente 100 MB tras la carga inicial del modelo. Puede leer sobre otros modelos disponibles en la documentación .
Comencemos con el matraz
Si no está familiarizado con Flask, puede crear una ruta en él simplemente agregando el decorador .route ('/') de la aplicación al controlador, donde app es la variable de la aplicación. Un ejemplo:
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!'
Cuando comience y vaya a la dirección predeterminada 127.0.0.1 : 5000 / ¡veremos la respuesta Hello World! Puede leer sobre cómo hacer algo más complicado en la documentación .
Comencemos a crear un backend completo:
import os import tensorflow as tf from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image as img from keras.preprocessing.image import img_to_array import numpy as np from PIL import Image from keras.applications.resnet50 import ResNet50,decode_predictions,preprocess_input from datetime import datetime import io from flask import Flask,Blueprint,request,render_template,jsonify from modules.dataBase import collection as db
Como puede ver, las importaciones contienen tensorflow , que usaremos como backend para keras , así como numpy para trabajar con matrices multidimensionales.
mod = Blueprint('backend', __name__, template_folder='templates', static_folder='./static') UPLOAD_URL = 'http://192.168.1.103:5000/static/' model = ResNet50(weights='imagenet') model._make_predict_function()
En la primera línea creamos un plan para una organización más conveniente de la aplicación. Debido a esto, necesitará usar mod .route ('/') para decorar el controlador. Resnet50 pre-entrenado en imagenet necesita llamar a _make_predict_function () para inicializar. Sin este paso, existe la posibilidad de obtener un error. Y se puede usar otro modelo reemplazando la línea
model = ResNet50(weights='imagenet')
en
model = load_model('saved_model.h5')
Así se verá el controlador:
@mod.route('/predict', methods=['POST']) def predict(): if request.method == 'POST': # , if 'file' not in request.files: return "someting went wrong 1" user_file = request.files['file'] temp = request.files['file'] if user_file.filename == '': return "file name not found ..." else: path = os.path.join(os.getcwd()+'\\modules\\static\\'+user_file.filename) user_file.save(path) classes = identifyImage(path) db.addNewImage( user_file.filename, classes[0][0][1], str(classes[0][0][2]), datetime.now(), UPLOAD_URL+user_file.filename) return jsonify({ "status":"success", "prediction":classes[0][0][1], "confidence":str(classes[0][0][2]), "upload_time":datetime.now() })
En el código anterior, la imagen descargada se pasa al método IdentityImage (file_path) , que se implementa de la siguiente manera:
def identifyImage(img_path): image = img.load_img(img_path, target_size=(224,224)) x = img_to_array(image) x = np.expand_dims(x, axis=0)
Primero, convertimos la imagen a un tamaño de 224 * 224, porque es él quien necesita nuestro modelo. Luego pasamos a los bytes de imagen preprocesados model.predict () . Ahora nuestro modelo puede predecir qué hay en la imagen ( se necesita top = 1 para obtener el resultado más probable).
Guarde los datos recibidos sobre el contenido de la imagen en MongoDB utilizando la función db.addData () . Aquí está el código relevante:
from pymongo import MongoClient from bson import ObjectId client = MongoClient("mongodb://localhost:27017")
Como usamos blueprint, el código para la API se puede colocar en un archivo separado:
from flask import Flask,render_template,jsonify,Blueprint mod = Blueprint('api',__name__,template_folder='templates') from modules.dataBase import collection as db from bson.json_util import dumps @mod.route('/') def api(): return dumps(db.getAllImages())
Como puede ver, usamos json para devolver datos de la base de datos. Puede ver el resultado en la dirección 127.0.0.1 : 5000 / api
Por encima, por supuesto, son solo las piezas de código más importantes. El proyecto completo se puede ver en el repositorio de GitHub . Y más sobre Pymongo se puede encontrar aquí .
Creamos la aplicación Flutter
La versión móvil recibirá imágenes y datos sobre sus contenidos a través de la API REST. Aquí está el resultado:
La clase ImageData encapsula datos de imagen:
import 'dart:convert'; import 'package:http/http.dart' as http; import 'dart:async'; class ImageData {
Aquí obtenemos json, lo convertimos en una lista de objetos ImageData y lo devolvemos a Future Builder usando la función LoadImages ()
Subir imágenes al servidor
uploadImageToServer(File imageFile) async { print("attempting to connecto server......"); var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead())); var length = await imageFile.length(); print(length); var uri = Uri.parse('http://192.168.1.103:5000/predict'); print("connection established."); var request = new http.MultipartRequest("POST", uri); var multipartFile = new http.MultipartFile('file', stream, length, filename: basename(imageFile.path));
Para hacer que Flask esté disponible en la red local, desactive el modo de depuración y busque la dirección ipv4 usando ipconfig . Puede iniciar el servidor local de esta manera:
app.run(debug=False, host='192.168.1.103', port=5000)
A veces, un firewall puede evitar que una aplicación acceda a un host local, luego deberá reconfigurarse o deshabilitarse.
Todo el código fuente de la aplicación está disponible en github . Aquí están los enlaces que lo ayudarán a comprender lo que está sucediendo:
Keras: https://keras.io/
Aleteo: https://flutter.dev/
MongoDB: https://www.tutorialspoint.com/mongodb/
Harvard Python and Flask Course: https://www.youtube.com/watch?v=j5wysXqaIV8&t=5515s (las conferencias 2,3,4 son especialmente importantes)
GitHub: https://github.com/SHARONZACHARIA