Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 33 additions & 102 deletions Templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reconocedor de Cubiertos</title>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
Expand Down Expand Up @@ -49,120 +53,47 @@ <h1>Reconocedor de Cubiertos</h1>
<div class="row">
<div class="video-container col-md-6">
<video id="video" width="640" height="480" autoplay></video>
<canvas id="canvas" hidden></canvas>
</div>
<div class="output-container col-md-4">
<div id="output" class="text-center">Predicción: </div>
<div id="class-prediction" class="text-center">Clase: </div>
<label>Predicción:</label>
<div id="output" class="text-center"></div>
<label>Clase:</label>
<div id="class-prediction" class="text-center"></div>
</div>
</div>
</div>
<script>
const socket = io();
var socket = io();
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const prediccion = document.getElementById('output');
const clase = document.getElementById('class-prediction');

// Manejar mensaje entrante del servidor
socket.on('response', function(response) {
console.log('Received response from server: ' + response);
// Aquí puedes hacer lo que quieras con la respuesta del servidor
socket.on('connect', function () {
console.log('Connected to the server');
});
socket.on('message', function (data) {
prediccion.innerHTML = data.prediccion
clase.innerHTML = data.classes
console.log('Server says: ' + data);
});

// Función para capturar una imagen del video y enviarla al servidor Flask
function captureImage(video) {
// Crear un canvas para capturar la imagen del video
let canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
let context = canvas.getContext('2d');
context.drawImage(video, 0, 0, canvas.width, canvas.height);

// Convertir el canvas a un blob y enviarlo al servidor
canvas.toBlob(function(blob) {
let formData = new FormData();
formData.append('image', blob, 'frame.jpg');

fetch('/predict', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.prediction) {
document.getElementById('output').innerText = `Predicción: ${data.prediction}`;

// Mostrar la predicción de las clases
document.getElementById('class-prediction').innerText = `Clase: ${data.class_prediction}`;
} else if (data.error) {
console.log(data.error);
}
})
.catch(error => {
console.log('Error:', error);
});
}, 'image/jpeg');
}

// Asegurarse de que el navegador soporte getUserMedia
function hasGetUserMedia() {
return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
}

if (hasGetUserMedia()) {
// Accede a la cámara
navigator.mediaDevices.getUserMedia({ video: true })
.then(function(stream) {
let video = document.getElementById('video');
navigator.mediaDevices.getUserMedia({ video: true })
.then((stream) => {
video.srcObject = stream;

// Función para capturar y enviar el video al servidor
function captureAndSend() {
// Crear un canvas para capturar la imagen del video
let canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
let context = canvas.getContext('2d');
context.drawImage(video, 0, 0, canvas.width, canvas.height);

// Convertir el canvas a un blob y enviarlo al servidor
canvas.toBlob(function(blob) {
let formData = new FormData();
formData.append('image', blob, 'frame.jpg');

fetch('/predict', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.prediction) {
document.getElementById('output').innerText = `Predicción: ${data.prediction}`;

// Mostrar la predicción de las clases
document.getElementById('class-prediction').innerText = `Clase: ${data.class_prediction}`;
} else if (data.error) {
console.log(data.error);
}
})
.catch(error => {
console.log('Error:', error);
});
}, 'image/jpeg');

// Continuar capturando y enviando el video en tiempo real
requestAnimationFrame(captureAndSend);
}

// Comenzar a capturar y enviar el video en tiempo real
captureAndSend();
})
.catch(function(error) {
console.log("Error al acceder a la cámara: ", error);
.catch((error) => {
console.error('Error accessing webcam:', error);
});
} else {
alert("getUserMedia() no es compatible con tu navegador");
}

const FPS = 10; // Adjust frame rate as needed
setInterval(() => {
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, 300, 150);
const dataURL = canvas.toDataURL('image/jpeg');
socket.emit('message', dataURL);
}, 1000 / FPS);
</script>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
</body>
</html>
77 changes: 54 additions & 23 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import numpy as np
import tensorflow as tf
from flask_socketio import SocketIO, emit
import base64
from PIL import Image # deben instalar pillow

app = Flask(__name__)
socketio = SocketIO(app)
Expand All @@ -14,32 +16,61 @@
def index():
return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
try:
# Leer la imagen del request
file = request.files['image'].read()
npimg = np.frombuffer(file, np.uint8)
img = cv2.imdecode(npimg, cv2.IMREAD_COLOR)
@socketio.on('connect')
def handle_connect():
print('Client connected')

@socketio.on('message')
def handle_message(data):
# recibimos la imagen en base64
base64_string = ""

if "data:image" in data:
base64_string = data.split(",")[1] # separamos el base64 porque llega en un formato data:image,asdfasdfasdf

image_bytes = base64.b64decode(base64_string) # decodificamos el base64
img = Image.open(io.BytesIO(image_bytes)) # lo volvemos una imagen real, tienen que mirar si el modelo puede recibir la imagen asi o si funciona el codigo que sigue
# Desde aqui no se si funcione porque no tengo como probar esta parte
npimg = np.frombuffer(img, np.uint8)
cv2img = cv2.imdecode(npimg, cv2.IMREAD_COLOR)

# Procesar la imagen (esto depende de tu modelo)
img = cv2.resize(img, (224, 224)) # Ajusta el tamaño según tu modelo
img = img / 255.0 # Normalizar
img = np.expand_dims(img, axis=0)

# Realizar la predicción
y_predicted = model.predict(img)
predicted_label = np.argmax(y_predicted[0]) # Obtener la clase con mayor probabilidad
classes = ['cuchillo', 'tenedor', 'cuchara'] # Ajusta esto según las clases de tu modelo
prediction_text = classes[predicted_label]
# Procesar la imagen (esto depende de tu modelo)
cv2img = cv2.resize(cv2img, (224, 224)) # Ajusta el tamaño según tu modelo
cv2img = cv2img / 255.0 # Normalizar
cv2img = np.expand_dims(cv2img, axis=0)

# Realizar la predicción
y_predicted = model.predict(cv2img)
predicted_label = np.argmax(y_predicted[0]) # Obtener la clase con mayor probabilidad
classes = ['cuchillo', 'tenedor', 'cuchara'] # Ajusta esto según las clases de tu modelo
prediction_text = classes[predicted_label]

socketio.emit('message', {'prediction': prediction_text, 'class_prediction': classes}) # emitimos el mensaje

print('received message: ' + 'ok')

# @app.route('/predict', methods=['POST'])
# def predict():
# try:
# # Leer la imagen del request
# file = request.files['image'].read()
# npimg = np.frombuffer(file, np.uint8)
# img = cv2.imdecode(npimg, cv2.IMREAD_COLOR)

return jsonify({'prediction': prediction_text, 'class_prediction': classes})
except Exception as e:
return jsonify({'error': str(e)})
# # Procesar la imagen (esto depende de tu modelo)
# img = cv2.resize(img, (224, 224)) # Ajusta el tamaño según tu modelo
# img = img / 255.0 # Normalizar
# img = np.expand_dims(img, axis=0)

@socketio.on('message')
def handle_message(message):
print('received message: ' + message)
# # Realizar la predicción
# y_predicted = model.predict(img)
# predicted_label = np.argmax(y_predicted[0]) # Obtener la clase con mayor probabilidad
# classes = ['cuchillo', 'tenedor', 'cuchara'] # Ajusta esto según las clases de tu modelo
# prediction_text = classes[predicted_label]

# return jsonify({'prediction': prediction_text, 'class_prediction': classes})
# except Exception as e:
# return jsonify({'error': str(e)})

if __name__ == '__main__':
socketio.run(app, debug=True)