# Log TFG En este fichero se irán registrando los avances del mi proyecto de TFG. ## 24-11-2025 Tras haber acabado ya el proyecto de Game Boy, y sus posteriores semanas de evaluación, he logrado encontrar al fin tiempo para poder organizar el TFG. De ahora en adelante intentaré adelantar todos los días algo, aunque sea un poco. También iré registrando el tiempo que dedico al TFG con la herramienta Clockify, la cual también usamos en las asignaturas de 4º. Hoy concretamente he comenzado a redactar los requisitos funcionales, comenzando por los más típicos: Registro, inicio de sesión y guardado de datos (partituras en este caso). También he agregado los requisitos no funcionales que ya tenía claros: Tecnologías del back y el front, y requisitos mínimos de seguridad necesarios para almacenar datos de usuarios. ## 25-11-2025 Creo que ya he agregado todos los requisitos funcionales básicos de la app: Escaneo de partitura, uso del metrónomo y práctica de la partitura. También he agregado la edición y borrado de partituras. ## 26-11-2025 Al principio pensaba que en los requisitos funcionales solo había que incluir las funcionalidades que usa el usuario directamente. Tras consultarlo con mi profesora favorita experta en requisitos (mi madre), he incluido el requisito de detección de compases, que se usa tras escanear una partitura. ## 29-11-2025 Lo de trabajar todos los días al final no ha durado tanto. Entre el aumento de carga de trabajo del ABP y los ensayos para el concierto que tengo hoy con la banda (dentro de 4 horas en el momento que estoy escribiendo esto), no he logrado encontrar tiempo para ponerme con el TFG. Aprovechando que por ahora ya he acabado con mis tareas del ABP, he agregado el requisito funcional de selección de compases antes de practicar, además de varios requisitos no funcionales. ## 30-11-2025 Esto de intentar escribir el log en fin de semana por la tarde se está convirtiendo en una odisea. Aprecio que LaLiga crea que tengo los conocimientos técnicos y las capacidades de retransmitir una señal pirata de un partido de fútbol online, pero esto está empezando a cansar un poco. En cualquier caso, hoy he enviado un correo a mi tutor para informa de los avances. También he enviado un mensaje a los administradores de dos páginas web de partituras de videojuegos que suelo usar ([VGLeadSheets](https://www.vgleadsheets.com) y [NinSheetMusic](https://www.ninsheetmusic.org)) para saber si sería posible integrar una función de búsqueda de sus partituras en la app. En caso de tener una respuesta afirmativa, agregaré los correspondientes requisitos al documento. ## 1-12-2025 Atendiendo a las sugerencias realizadas por mi tutor, he agregado 2 requesitos funcionales nuevos: seleccionar un PDF de una partitura y seleccionar manualmente los compases de una partitura. Sigo a la espera de la respuesta de los administradores de las páginas web de partituras de videojuegos. A pocas horas de que acabé el día he recibido respuesta del administrador de [NinSheetMusic](https://www.ninsheetmusic.org). Por ahora solo me ha dicho que ha estado ocupado últimamente, y que me responderá en cuanto tenga un hueco. ## 3-12-2025 Hoy comienzo ha hacer los mockups con Figma, una herramienta para diseño de interfaces. Investigando sobre qué librería de compnentes de diseño usar, he descubierto que la de Apple tiene una licencia que prohíbe su uso cualquier aplicación que no se ejecute única y exclusivamente en sistemas de Apple. A menos que encuentre una alternativa mejor, para el diseño de la app utilizaré la librería de Google, Material 3, ya que: - Tiene licencia Creative Commons. - Es bastante usada. - Es fiable y está probada. - Viene incluida por defecto en Figma. - Está incluida en Flutter. - Tengo experiencia previa usándola. ~Respecto al administrador de [NinSheetMusic](https://www.ninsheetmusic.org), empiezo a pensar que se le ha olvidado responderme. Este finde le enviaré un recordatorio si aún no me ha dicho nada.~ Qué contento estoy, me acaba de responder y dice que ha hablado con un par de colegas de la página y que estarían encantados de echarme una mano. Aunque dicen que ahora mismo tienen bastante trabajo, así que no me puede prometer nada. También me ha preguntado algunos detalles sobre el proyecto, imagino que para saber cómo pueden ayudarme. También he agregado requisitos no funcionales para la publicación de la app en Play Store y App Store. No estoy seguro de si las llegaré a publicar (especialmente en Apple, ya que tendría que desempolvar un antiguo MacBook que tengo, restaurarlo y rezar para que sirva), pero me gustaría hacerlo. Ah sí, hoy he descubierto que al parecer no solo hay liga los fines de semana, también puede haber entre semana :`). ## 11-12-2025 Perdón por la ausencia de estos días. En esta semana se me ha juntado una carga extra de trabajo del ABP junto a la entrega de una práctica de GC de 3º. Hoy he adelantado un poco los mockups. También me ha vuelto a hablar el administrador de NinSheetMusic. Dice que aún están trabajando en ello, pero que puedo hablarle en cualquier momento, sobretodo si hace varios días que no me dice nada. ## 13-12-2025 Antes de nada, aclarar que me habría gustado adelantar un poco ayer, pero me topé con una cosa muy turbia llamada "Metaprogramación en C++ para videojuegos" que me quitó prácticamente todas las horas del día. Hoy he seguido con los mockups. También he agregado en el apartado de interfaces de usuario un enlace al proyecto de Figma con los mockups. ## 20-12-2025 Al fin, ya se acabó el hito 1 del ABP de 4º. Estos próximos días se los dedicaré completamente al TFG. Hoy he avanzado bastante en los mockups. También he agregado el requisito de recuperar contraseña. ## 21-12-2025 Prácticamente creo que he acabado ya los mockups. Mañana acabaré de pulirlos y enviaré un correo a mi tutor para que les eche un vistazo, y para saber si debo hacer algo más antes de ponerme a implementar. ## 22-12-2025 Ya he acabado la primera versión de los mockups. También he agregado 2 requisitos funcionales nuevos relacionados con la ley de protección de datos europea que acabo de recordar que existe: **Cambio de correo** y **borrado de cuenta**. También he enviado un correo a mi tutor y un mensaje al admin de NinSheetMusic para felicitarle las fiestas y para preguntarle cómo va la cosa. ## 13-01-2026 ¡Feliz año nuevo! Tras unas vacaciones trabajando sin parar en el ABP de 4º para la presentación del hito 1, ya va siendo hora de retomar el TFG. Hoy he estado instalando las herramientas necesarias para el desarrollo del TFG: - **Front**: Flutter SDK. - **Back**: PHP, Composer y Laravel. - **Gestor base de datos**: docker-compose con un contenedor de MariaDB. - **IDE Front**: Android Studio con extensión de Flutter. - **IDE Back**: VSCode con extensión de Laravel. ## 18-01-2026 Hoy he comenzado ya con el primer apartado de la memoria, el de la motivación. ## 19-01-2026 Hoy he finalizado el apartado de motivación y comenzado con el apartado de introducción. ## 26-01-2026 Al fin, se acabó el hito 2 del ABP. Tras un pequeño descanso, volvemos a la acción. Ya he creado los proyectos y repositorios tanto del proyecto del back como del front. También me he instalado Zotero para ayudarme con la bibliografía, y he seguido con el apartado de introducción de la memoria. ## 03-02-2026 He completado (en principio) el apartado de introducción, y he comenzado con el del estado del arte. ## 05-02-2026 He continuado con el apartado del estado del arte. ## 06-02-2026 Hoy he investigado y seguido con el estado del arte. ## 07-02-2026 Hoy he finalizado una primera versión del estado del arte de lectura de partituras a primera vista, y he comenzado con el estado del arte del desarrollo móvil multiplataforma. ## 08-02-2026 He acabado la primera versión del estado del arte de herramientas de desarrollo y aplicaciones similares. Me faltaría probar y poner fotos de las aplicaciones parecidas. ## 09-02-2026 He realizado un último repaso a la memoria antes de enviársela a mi tutor. ## 19-02-2026 He comenzado con el desarrollo del front con Flutter. Principalmente he refrescado un poco la memoria, y he hecho una pantalla con una lista prefinida. ## 28-02-2026 He avanzado más en el desarrollo de la app de móvil. También he tenido hoy un concierto de semana santa con mi banda. Juraría que aún queda un mes para que comience, pero bueno. A lo mejor el cura tenía mal puesta la fecha en el móvil. ## 1-03-2026 He seguido con la app. He implementado ya obtención y escaneo de documentos. He encontrado esto para detectar compases. Es ML y a lo mejor no hace falta, pero por si acaso: https://github.com/OMR-Research/MeasureDetector?tab=readme-ov-file También he descubierto que Apple te pide que "justifiques tu respuesta" si quieres usar elementos como la cámara o el micrófono. ## 2-03-2026 He comenzado a investigar cómo hacer la detección de compases. De momento estoy usando una especie de Wraper de OpenCV para Dart, y probando métodos como la transformada de Hough (aunque aún sin saber del todo qué estoy haciendo realmente). ## 5-04-2026 Marzo fue un mes bastante intensito. Hemos ido a varias ferias a lo largo de toda España: Retroparla (Madrid), Expotaku de Almería y Salón del Manga de Alicante. Por si no fuera poco, también ayer hicimos una presentación de nuestro juego de Game Boy en el museo del videojuego de Ibi. Vamos, que no he parado. Ni voy a parar, porque el 25 de abril nos vamos a Retropolis en Valencia. Hoy al fin he podido ponerme con el TFG. El algoritmo de detección de compases técnicamente funciona, pero hay un pequeño problema: confunde las plicas de las notas con líneas de compás. Para solucionarlo he hecho que solo coja líneas que sean aprox. tan grandes como un cambio de compás (las plicas son menos largas). ## 6-04-2026 He iniciado ya el desarrollo del back. De momento he creado los modelos de partitura y etiqueta, y también las primeras rutas con placeholders. ## 7-04-2026 Hoy he configurado la base de datso MariaDB local de desarrollo, y he creado los métodos CRUD de partituras en el back y front. ## 8-04-2026 Hoy he continuado con la memoria, corrigiendo cosas que tenía pendientes y probando y haciendo capturas de las aplicaciones similares al proyecto. ## 9-04-2026 He creado un proyecto Kanban en GitHub. También he iniciado los apartados de objetivos y metodología. ## 21-04-2026 Ya he vuelto del viaje de fin de curso, así que toca volver a trabajar. He agregado referencias que faltaban a la memoria, y una imagen para visualizar la técnica para practicar el rango ojo-mano. ## 22-04-2026 He completado un poco la memoria y he preparado un orden del día para la reunión con el tutor mañana. ## 23-04-2026 He realizado la reunión con el tutor. Resumen: toca trabajar mucho. ## 24-04-2026 He hecho muchos avances en gestión de recursos entre front y back. ## 30-04-2026 Acabo de darme cuenta de que estos días se me ha olvidado ir escribiendo lo que he ido haciendo. En resumen: Ya hay un metrónomo, pantalla de práctica básica y selección manual de compases básica. Ahora estoy viendo cómo meter un modelo que detecte compases. Voy a ir apuntándome lo que he hecho para el conseguir hacer funcionar el modelo: [Este proyecto](https://github.com/OMR-Research/MeasureDetector) para el modelo. [Esta web](https://netron.app) para ver los nombres: ```sh python -m tf2onnx.convert \ --input 2019-05-16_faster-rcnn-mobilenet-v1.pb \ --inputs image_tensor:0 \ --outputs detection_scores:0,detection_boxes:0,detection_classes:0,num_detections:0 \ --output model.onnx ``` Error tflite: E/tflite ( 4589): Select TensorFlow op(s), included in the given model, is(are) not supported by this interpreter. Make sure you apply/link the Flex delegate before inference. For the Android, it can be resolved by adding "org.tensorflow:tensorflow-lite-select-tf-ops" dependency. See instructions: https://www.tensorflow.org/lite/guide/ops_select ## 01-05-2026 ¡Ya está, al fin funciona! Lo malo es que si quiero que tenga un mínimo de precisión me toca embutir un modelo de 200 MB en la app, lo cual no es que sea la mejor opción... Veré que puedo hacer. ## 03-05-2026 Pues resulta que el TFLite que había mirado como alternativa a ONNX y no funcionaba está sin mantener, y lo nuevo se llama LiteRT. Para usar lo nuevo hay que usar una librería de comunidad llamada flutter_litert. Y encima tras hacer todo el curro para probar lo nuevo ni siquiera funciona, sencillamente crashea. Dejo por aquí lo que he llegado a hacer: class TfliteService { static final TfliteService _singleton = TfliteService._internal(); late Interpreter interpreter; factory TfliteService() => _singleton; TfliteService._internal() { init(); } Future init() async { // Add the Flex Delegate to handle your FlexTensorArrayV3 nodes final options = InterpreterOptions()..addDelegate(await FlexDelegate.create()); interpreter = await Interpreter.fromAsset( 'assets/models/model.tflite', options: options ); } } Future> tfliteTest(File imageFile) async { final service = TfliteService(); // 1. Load and Decode Image final Uint8List imageBytes = await imageFile.readAsBytes(); final img.Image? originalImage = img.decodeImage(imageBytes); if (originalImage == null) return []; final int imageW = originalImage.width; final int imageH = originalImage.height; // 2. Preprocess (Matches your ONNX logic) // Ensure the image is resized to the model's expected size if it's not already! final resizedImage = img.copyResize(originalImage, width: 1024, height: 1024); final Uint8List inputBytes = resizedImage.getBytes( order: img.ChannelOrder.rgb, ); // Shape: [1, H, W, 3] var input = inputBytes.reshape([1, 1024, 1024, 3]); // 3. Prepare Output Buffers // Most MobileNet Object Detectors return 100 or 600 detections. // We need to check the model's output shapes. // [1, 100, 4] for boxes, [1, 100] for scores/classes var outputBoxes = List.filled(1 * 600 * 4, 0).reshape([1, 600, 4]); var outputScores = List.filled(1 * 600, 0).reshape([1, 600]); // Map the output indices to our buffers // NOTE: You must verify these indices match your model via interpreter.getOutputTensors() Map outputs = { 0: outputBoxes, 2: outputScores, }; // 5. Post-process (Matches your logic) final List rects = await Isolate.run(() async { final List extractedRects = []; // Initialize a new interpreter inside the isolate if necessary, // or just run the heavy math here. service.interpreter.runForMultipleInputs([input], outputs); print('XDXDDDDDDDDDDDDDDDDDDDDDDDDDDDD'); // result indices final List> boxes = outputBoxes[0]; final List scores = outputScores[0]; for (int i = 0; i < scores.length; i++) { // Class 1 and Score > 0.5 if (scores[i] > 0.5) { final List box = boxes[i]; // TFLite detection models usually return normalized coordinates [y1, x1, y2, x2] final double y1 = box[0]; final double x1 = box[1]; final double y2 = box[2]; final double x2 = box[3]; // If you need pixel coordinates, multiply by imageW and imageH here extractedRects.add(Rect.fromLTRB(x1, y1, x2, y2)); } } return extractedRects; }); print(rects); return rects; } ## 06-05-2026 De momento va todo relativamente bien. Sonido metrónomo: https://freesound.org/people/Druminfected/sounds/250552 Sonido acentuado hechos subiéndole una cuarta (Fa -> Do) ## 12-05-2026 Para los diagramas de clase y otros del Laravel: https://github.com/Mapping-Apping/laravel2doc https://rua.ua.es/server/api/core/bitstreams/12a0f59b-4068-4a48-92ed-914caff34faa/content ## Guión vídeo Buenas tardes... ### Inicio de aplicación - Partituras registradas - Menú desplegable para escanear o importar ### Escaneo - Escaneo de partitura ### Datos de partitura - Detección automática - Modificación manual - Nombre de obra y autor - Guardar partitura ### Importar fichero - Seleccionar fichero de ejemplo - Atrás (para no mostrar de nuevo todo) ### Práctica - Abrir partitura preparada en modo práctica - Seleccionar tempo - Comenzar a practicar (aquí tal vez se pueda poner un vídeo mío tocando a la vez que se reproduce) - Parar metrónomo y volver atrás ### Nube - Creación de cuenta nueva - Borrar datos - Volver a iniciar sesión ### Metrónomo - Enseñar metrónomo aparte