diff --git a/.gitignore b/.gitignore index 1dce118..42026b8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,10 @@ Data/ .idea/ .venv/ */spectogram_model.h5 +spectrogram_classifier.h5 +build/ +dist/ +installer_output/ +*.spec +hook_tensorflow.py +hook_runtime.py diff --git a/README.md b/README.md index ea72563..8148f1a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,23 @@ -## Instructions +## Running from Source -1. Install dependencies by running `pip install -r requirements.txt` -2. Then run the gui by using `python3 gui.py` +1. Install dependencies: `pip install -r requirements.txt` +2. Launch the app: `python gui.py` + +## Building the Executable + +Requires PyInstaller (`pip install pyinstaller`): + +```bash +.venv/Scripts/pyinstaller --name "MelodiProof-AI" --noconsole --collect-all onnxruntime --add-data "App_Spectrograms;App_Spectrograms" --add-data "App_Covers;App_Covers" --add-data "App_Audio;App_Audio" --add-data "spectrogram_classifier.onnx;." --hidden-import="PIL._tkinter_finder" --runtime-hook="hook_runtime.py" -y gui.py +``` + +The executable will be in `dist/MelodiProof-AI/`. + +## Building the Installer + +1. Install [Inno Setup](https://jrsoftware.org/isinfo.php) +2. Open `installer.iss` in Inno Setup and click **Compile** +3. The installer (`MelodiProof-AI-Setup.exe`) will be output to `installer_output/` ## Datasets diff --git a/gui.py b/gui.py index aebce84..9e7b390 100644 --- a/gui.py +++ b/gui.py @@ -1,21 +1,25 @@ import os +import sys import tkinter as tk import numpy as np from tkinter import ttk from PIL import Image, ImageTk -from tensorflow.keras.models import load_model -from tensorflow.keras.preprocessing.image import load_img, img_to_array +import onnxruntime as ort import pygame # For audio playback +# Resolve base path for bundled resources (PyInstaller) or source directory +BASE_DIR = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) + # Constants IMG_HEIGHT, IMG_WIDTH = 128, 128 -SPECTROGRAM_DIR = "App_Spectrograms" -COVERS_DIR = "App_Covers" -MP3_DIR = "App_Audio" -MODEL_PATH = "spectrogram_classifier.h5" +SPECTROGRAM_DIR = os.path.join(BASE_DIR, "App_Spectrograms") +COVERS_DIR = os.path.join(BASE_DIR, "App_Covers") +MP3_DIR = os.path.join(BASE_DIR, "App_Audio") +MODEL_PATH = os.path.join(BASE_DIR, "spectrogram_classifier.onnx") # Load the trained model -model = load_model(MODEL_PATH) +session = ort.InferenceSession(MODEL_PATH) +input_name = session.get_inputs()[0].name # Initialize pygame mixer for audio playback pygame.mixer.init() @@ -26,13 +30,10 @@ def predict_spectrogram(image_path): - """ - Predict whether a spectrogram belongs to AI-Generated or Not. - """ - img = load_img(image_path, target_size=(IMG_HEIGHT, IMG_WIDTH)) - img_array = img_to_array(img) / 255.0 - img_array = img_array[np.newaxis, ...] # Add batch dimension - prediction = model.predict(img_array) + img = Image.open(image_path).convert("RGB").resize((IMG_WIDTH, IMG_HEIGHT)) + img_array = np.array(img, dtype=np.float32) / 255.0 + img_array = img_array[np.newaxis, ...] + prediction = session.run(None, {input_name: img_array})[0] return "AI-Generated" if prediction[0] < 0.5 else "Not AI-Generated" @@ -44,7 +45,7 @@ def get_cover_image(song_name, size=(50, 50)): if os.path.exists(cover_path): cover_image = Image.open(cover_path).resize(size) else: - cover_image = Image.open("App_Covers/placeholder.jpeg").resize(size) + cover_image = Image.open(os.path.join(COVERS_DIR, "placeholder.jpeg")).resize(size) return ImageTk.PhotoImage(cover_image) diff --git a/installer.iss b/installer.iss new file mode 100644 index 0000000..d26479a --- /dev/null +++ b/installer.iss @@ -0,0 +1,28 @@ +[Setup] +AppName=MelodiProof AI +AppVersion=1.0 +AppPublisher=MelodiProof +DefaultDirName={autopf}\MelodiProof-AI +DefaultGroupName=MelodiProof AI +OutputDir=installer_output +OutputBaseFilename=MelodiProof-AI-Setup +Compression=lzma +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "dist\MelodiProof-AI\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +[Icons] +Name: "{group}\MelodiProof AI"; Filename: "{app}\MelodiProof-AI.exe" +Name: "{group}\{cm:UninstallProgram,MelodiProof AI}"; Filename: "{uninstallexe}" +Name: "{autodesktop}\MelodiProof AI"; Filename: "{app}\MelodiProof-AI.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\MelodiProof-AI.exe"; Description: "{cm:LaunchProgram,MelodiProof AI}"; Flags: nowait postinstall skipifsilent diff --git a/requirements.txt b/requirements.txt index 2aa02b3..325f2bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,7 @@ pydub~=0.25.1 numpy~=1.26.4 matplotlib~=3.9.2 scipy~=1.14.1 -tensorflow~=2.18.0 -scikit-learn~=1.5.1 pillow~=10.4.0 librosa~=0.10.2.post1 -pygame~=2.6.1 \ No newline at end of file +pygame~=2.6.1 +onnxruntime~=1.25.0 \ No newline at end of file diff --git a/spectrogram_classifier.onnx b/spectrogram_classifier.onnx new file mode 100644 index 0000000..aa4e9d0 Binary files /dev/null and b/spectrogram_classifier.onnx differ