/* Il file MNIST in formato IDX ha questa struttura: Byte 0-3: Numero magico (4 byte). Byte 4-7: Numero di immagini (4 byte). Byte 8-11: Numero di righe per immagine (4 byte). Byte 12-15: Numero di colonne per immagine (4 byte). Byte 16 in poi: Dati delle immagini (ogni immagine è composta da 28x28 = 784 byte). Le immagini sono 28x28 pixel. I dati sono byte non firmati (valori da 0 a 255). Il file contiene 60.000 immagini (per il training set), Label Byte 0-3: Numero magico (0x00000801). Byte 4-7: Numero di label (60.000). Byte 8 in poi: 60.000 byte, ognuno dei quali rappresenta l'etichetta di un'immagine. */ #include #include #define N_INPUTS 784 // Immagine 28x28 // Siccome il char è un byte che rappresenta il valore tra 0 e 255. Per evitare confusioni definisco il tipo "byte" come in Java typedef unsigned char byte; // Singola istanza del dataset. typedef struct { int size; byte classificazione; byte dati[N_INPUTS]; } Istanza; // Questo tipo fornisce il vettore delle istanze e il size (dimensione) del vettore typedef struct { int size; Istanza *istanze; } Dataset; Dataset *get_dataset(char *, char *); void salva_dataset(const char*, Dataset*); Dataset *carica_dataset(const char*); // Questo metodo legge il file in questione e restituisce un puntatore a Dataset se il file esiste, altrimenti NULL // Ritorna un puntatore perchè in questo caso posso gestire il ritorno NULL. Dataset *get_dataset(char *path_mnist, char *path_categoria) { Dataset *set = (Dataset *)malloc(sizeof(Dataset)); FILE *file; FILE *categorie; Istanza *istanze = (Istanza *)malloc(sizeof(Istanza)); file = fopen(path_mnist, "rb"); if (file == NULL) { printf("Errore nella funzione fopen() nelle immagini\n"); return NULL; } categorie = fopen(path_categoria, "rb"); if (file == NULL) { printf("Errore nella funzione fopen() nelle categorie\n"); return NULL; } int numero_righe = 0; //Leggo male il file, cambiare in base alle dichiarazioni sopra if(fread(istanze[numero_righe].dati, sizeof(byte), 16, file) == 16 && fread(&istanze[numero_righe].classificazione, sizeof(byte), 8, categorie) == 8) { while (fread(istanze[numero_righe].dati, sizeof(byte), N_INPUTS, file) == N_INPUTS) { if(fread(&istanze[numero_righe].classificazione, sizeof(byte), 1, categorie) == 1) { numero_righe++; istanze = (Istanza *)realloc(istanze, sizeof(Istanza) * (numero_righe + 1)); istanze[numero_righe].size = N_INPUTS; } } } // Dataset set; (*set).size = numero_righe; (*set).istanze = istanze; fclose(file); //Trasformo tutto in 0 e 1 for(int indice_immagine = 0; indice_immagine < set->size; indice_immagine++) { for(int indice_byte = 0; indice_byte < N_INPUTS; indice_byte++) { if(set->istanze[indice_immagine].dati[indice_byte] >= 128) set->istanze[indice_immagine].dati[indice_byte] = 1; else set->istanze[indice_immagine].dati[indice_byte] = 0; } } return set; } void salva_dataset(const char *filename, Dataset *set) { FILE *file = fopen(filename, "wb"); if (!file) { perror("Errore nell'apertura del file"); exit(EXIT_FAILURE); } for (int indice_istanze = 0; indice_istanze < set->size; indice_istanze++) { if(set->istanze[indice_istanze].classificazione == 7) { fwrite(&set->istanze[indice_istanze].classificazione, sizeof(byte), 1, file); fwrite(&set->istanze[indice_istanze].dati, sizeof(byte), N_INPUTS, file); } } fclose(file); } Dataset *carica_dataset(const char *filename) { FILE *file = fopen(filename, "rb"); if (!file) { perror("Errore nell'apertura del file"); exit(EXIT_FAILURE); } // Creazione di un dataset vuoto Dataset *set = (Dataset *)malloc(sizeof(Dataset)); if (!set) { perror("Errore nell'allocazione del dataset"); fclose(file); exit(EXIT_FAILURE); } set->size = 0; set->istanze = NULL; // Variabile temporanea per leggere ogni istanza Istanza temp; // Leggi il file fino alla fine while (1) { // Prova a leggere la classificazione size_t letti_classificazione = fread(&temp.classificazione, sizeof(byte), 1, file); // Prova a leggere i dati size_t letti_dati = fread(&temp.dati, sizeof(byte), N_INPUTS, file); // Se non riesci a leggere un'intera istanza, esci dal ciclo if (letti_classificazione != 1 || letti_dati != N_INPUTS) { break; } // Aumenta la dimensione del dataset set->size++; // Rialloca la memoria per le istanze set->istanze = (Istanza *)realloc(set->istanze, set->size * sizeof(Istanza)); if (!set->istanze) { perror("Errore nella riallocazione della memoria"); fclose(file); free(set); exit(EXIT_FAILURE); } // Aggiungi l'istanza letta al dataset set->istanze[set->size - 1] = temp; } fclose(file); return set; } /* void main() { Dataset *set = get_dataset(file_immagini, file_label); if(set == NULL) { printf("Nullo esco\n"); return; } salva_dataset("dataset_sette.bin", set); for(int i = 0; i < set->size; i++) { printf("immagine %d - valore rappresentato: %d\n", i, set->istanze[i].classificazione); } } */