Files
classificatore_immagini/mnist/mnist_manager.h

185 lines
5.5 KiB
C

/*
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 <stdlib.h>
#include <stdio.h>
#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);
}
} */