generated from freudenreichan/info2Praktikum-NeuronalesNetz
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7295f88914 | ||
|
|
6e50310a28 |
No files matched your search
+133
-5
@@ -6,17 +6,145 @@
|
||||
#define BUFFER_SIZE 100
|
||||
#define FILE_HEADER_STRING "__info2_image_file_format__"
|
||||
|
||||
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
|
||||
|
||||
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
|
||||
/*
|
||||
* Aufbau der mnist_test.info2
|
||||
*
|
||||
* Offset Inhalt Typ
|
||||
* ------ ---------------------------- ----------------------------------
|
||||
* 0 "__info2_image_file_format__" 26 ASCII-Zeichen
|
||||
* 26 Anzahl der Bilder unsigned short (2 Bytes) 10 27 -> 27 10 -> 10000
|
||||
* 28 Breite eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28
|
||||
* 30 Höhe eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28
|
||||
* 32 Bild 0: width*height Pixel unsigned char je Pixel (Graustufe 0-255)
|
||||
* direkt danach: Label 0 unsigned char (Klasse 0-9)
|
||||
*
|
||||
* usw...
|
||||
*/
|
||||
|
||||
|
||||
//prüft, ob die Datei mit dem erwarteten Dateitag beginnt
|
||||
static int checkFileTag(FILE *file)
|
||||
{
|
||||
int isValid = 0;
|
||||
size_t tagLength = strlen(FILE_HEADER_STRING);
|
||||
char buffer[BUFFER_SIZE] = {0};
|
||||
|
||||
if(tagLength < BUFFER_SIZE && fread(buffer, sizeof(char), tagLength, file) == tagLength)
|
||||
{
|
||||
isValid = strncmp(buffer, FILE_HEADER_STRING, tagLength) == 0;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
//liest Anzahl, Breite und Höhe der Bildserie; Erfolg nur, wenn alle Werte gelesen werden konnten und positiv sind
|
||||
static int readSeriesHeader(FILE *file, unsigned short *count, unsigned short *width, unsigned short *height)
|
||||
{
|
||||
return fread(count, sizeof(unsigned short), 1, file) == 1
|
||||
&& fread(width, sizeof(unsigned short), 1, file) == 1
|
||||
&& fread(height, sizeof(unsigned short), 1, file) == 1
|
||||
&& *count > 0 && *width > 0 && *height > 0;
|
||||
}
|
||||
|
||||
//liest die Pixelwerte eines einzelnen Bildes; buffer ist NULL im Fehlerfall
|
||||
static GrayScaleImage readImage(FILE *file, unsigned int width, unsigned int height)
|
||||
{
|
||||
GrayScaleImage image = {NULL, 0, 0};
|
||||
|
||||
GrayScalePixelType *buffer = (GrayScalePixelType *)calloc(width * height, sizeof(GrayScalePixelType));
|
||||
|
||||
if(buffer != NULL && fread(buffer, sizeof(GrayScalePixelType), width * height, file) == width * height)
|
||||
{
|
||||
image.buffer = buffer;
|
||||
image.width = width;
|
||||
image.height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
//liest die Klasse (Label) des zuletzt gelesenen Bildes
|
||||
static int readLabel(FILE *file, unsigned char *label)
|
||||
{
|
||||
return fread(label, sizeof(unsigned char), 1, file) == 1;
|
||||
}
|
||||
|
||||
static int isValidSeries(const GrayScaleImageSeries *series)
|
||||
{
|
||||
return series->images != NULL && series->labels != NULL && series->count > 0;
|
||||
}
|
||||
|
||||
GrayScaleImageSeries *readImages(const char *path)
|
||||
{
|
||||
GrayScaleImageSeries *series = NULL;
|
||||
|
||||
FILE *file = fopen(path, "rb"); //Binärdatei, daher "rb"
|
||||
|
||||
if(file != NULL)
|
||||
{
|
||||
unsigned short count = 0;
|
||||
unsigned short width = 0;
|
||||
unsigned short height = 0;
|
||||
|
||||
if(checkFileTag(file) && readSeriesHeader(file, &count, &width, &height))
|
||||
{
|
||||
series = (GrayScaleImageSeries *)malloc(sizeof(GrayScaleImageSeries)); //struct containing *images, *lables and count
|
||||
|
||||
if(series != NULL)
|
||||
{
|
||||
series->images = (GrayScaleImage *)calloc(count, sizeof(GrayScaleImage)); //10000 * 784bytes in our example
|
||||
series->labels = (unsigned char *)calloc(count, sizeof(unsigned char)); //10000bytes 1 for every picture in our example
|
||||
series->count = count;
|
||||
|
||||
if(isValidSeries(series))
|
||||
{
|
||||
int allRead = 1;
|
||||
|
||||
for(unsigned int i = 0; i < count && allRead; i++)
|
||||
{
|
||||
series->images[i] = readImage(file, width, height);
|
||||
allRead = series->images[i].buffer != NULL && readLabel(file, &series->labels[i]);
|
||||
}
|
||||
|
||||
if(!allRead)
|
||||
{
|
||||
clearSeries(series);
|
||||
series = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clearSeries(series);
|
||||
series = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
|
||||
void clearSeries(GrayScaleImageSeries *series)
|
||||
{
|
||||
}
|
||||
if(series != NULL)
|
||||
{
|
||||
if(series->images != NULL)
|
||||
{
|
||||
//erst die Pixelbuffer der einzelnen Bilder, dann das Array selbst
|
||||
for(unsigned int i = 0; i < series->count; i++)
|
||||
{
|
||||
free(series->images[i].buffer);
|
||||
}
|
||||
free(series->images);
|
||||
}
|
||||
|
||||
free(series->labels);
|
||||
free(series);
|
||||
}
|
||||
}
|
||||
+135
-8
@@ -2,34 +2,161 @@
|
||||
#include <string.h>
|
||||
#include "matrix.h"
|
||||
|
||||
// TODO Matrix-Funktionen implementieren
|
||||
|
||||
Matrix createMatrix(unsigned int rows, unsigned int cols)
|
||||
{
|
||||
|
||||
Matrix matrix = {NULL, 0, 0}; //Initialwerte, da unsicher ob allocierung funktioniert
|
||||
|
||||
if(rows > 0 && cols > 0)
|
||||
{
|
||||
MatrixType *buffer = (MatrixType *)calloc(rows * cols, sizeof(MatrixType));
|
||||
if(buffer != NULL)
|
||||
{
|
||||
matrix.buffer = buffer;
|
||||
matrix.rows = rows;
|
||||
matrix.cols = cols;
|
||||
}
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void clearMatrix(Matrix *matrix)
|
||||
{
|
||||
|
||||
if(matrix != NULL)
|
||||
{
|
||||
free(matrix->buffer);
|
||||
matrix->buffer = NULL;
|
||||
matrix->rows = 0;
|
||||
matrix->cols = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
|
||||
{
|
||||
|
||||
if(rowIdx < matrix.rows && colIdx < matrix.cols)
|
||||
{
|
||||
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
|
||||
{
|
||||
|
||||
MatrixType value = UNDEFINED_MATRIX_VALUE;
|
||||
|
||||
if(rowIdx < matrix.rows && colIdx < matrix.cols)
|
||||
{
|
||||
value = matrix.buffer[rowIdx * matrix.cols + colIdx];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int isValidMatrix(const Matrix matrix)
|
||||
{
|
||||
return matrix.buffer != NULL && matrix.rows > 0 && matrix.cols > 0;
|
||||
}
|
||||
|
||||
static int hasSameDimensions(const Matrix matrix1, const Matrix matrix2)
|
||||
{
|
||||
return matrix1.rows == matrix2.rows && matrix1.cols == matrix2.cols;
|
||||
}
|
||||
|
||||
static int isColumnVector(const Matrix matrix)
|
||||
{
|
||||
return matrix.cols == 1;
|
||||
}
|
||||
|
||||
static Matrix addElementWise(const Matrix matrix1, const Matrix matrix2)
|
||||
{
|
||||
Matrix result = createMatrix(matrix1.rows, matrix1.cols);
|
||||
|
||||
if(isValidMatrix(result))
|
||||
{
|
||||
for(unsigned int i = 0; i < matrix1.rows * matrix1.cols; i++)
|
||||
{
|
||||
result.buffer[i] = matrix1.buffer[i] + matrix2.buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Matrix addBroadcast(const Matrix matrix, const Matrix vector)
|
||||
{
|
||||
Matrix result = createMatrix(matrix.rows, matrix.cols);
|
||||
|
||||
if(isValidMatrix(result))
|
||||
{
|
||||
for(unsigned int rowIdx = 0; rowIdx < matrix.rows; rowIdx++)
|
||||
{
|
||||
for(unsigned int colIdx = 0; colIdx < matrix.cols; colIdx++)
|
||||
{
|
||||
unsigned int index = rowIdx * matrix.cols + colIdx;
|
||||
result.buffer[index] = matrix.buffer[index] + getMatrixAt(vector, rowIdx, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix add(const Matrix matrix1, const Matrix matrix2)
|
||||
{
|
||||
|
||||
Matrix result = {NULL, 0, 0}; //leere Matrix als Fehlerfall
|
||||
|
||||
if(isValidMatrix(matrix1) && isValidMatrix(matrix2))
|
||||
{
|
||||
//normal add
|
||||
if(hasSameDimensions(matrix1, matrix2))
|
||||
{
|
||||
result = addElementWise(matrix1, matrix2);
|
||||
}
|
||||
//add Broadcast matrix2 = vektor and matrix1 = matrix
|
||||
else if(isColumnVector(matrix2) && matrix1.rows == matrix2.rows)
|
||||
{
|
||||
result = addBroadcast(matrix1, matrix2);
|
||||
}
|
||||
//add Broadcast matrix1 = vektor and matrix2 = matrix
|
||||
else if(isColumnVector(matrix1) && matrix1.rows == matrix2.rows)
|
||||
{
|
||||
result = addBroadcast(matrix2, matrix1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (Bedingung: matrix1.cols == matrix2.rows)
|
||||
* | 1 2 3 | | 7 8 | | 1*7+2*9+3*11 1*8+2*10+3*12 | | 58 64 |
|
||||
* | 4 5 6 | * | 9 10 | = | 4*7+5*9+6*11 4*8+5*10+6*12 | = | 139 154 |
|
||||
* | 11 12 |
|
||||
*/
|
||||
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
|
||||
{
|
||||
|
||||
Matrix result = {NULL, 0, 0}; //leere Matrix als Fehlerfall
|
||||
|
||||
if(isValidMatrix(matrix1) && isValidMatrix(matrix2) && matrix1.cols == matrix2.rows)
|
||||
{
|
||||
result = createMatrix(matrix1.rows, matrix2.cols);
|
||||
|
||||
if(isValidMatrix(result))
|
||||
{
|
||||
for(unsigned int rowIdx = 0; rowIdx < matrix1.rows; rowIdx++)
|
||||
{
|
||||
for(unsigned int colIdx = 0; colIdx < matrix2.cols; colIdx++)
|
||||
{
|
||||
MatrixType sum = 0;
|
||||
|
||||
for(unsigned int k = 0; k < matrix1.cols; k++)
|
||||
{
|
||||
sum += getMatrixAt(matrix1, rowIdx, k) * getMatrixAt(matrix2, k, colIdx);
|
||||
}
|
||||
|
||||
setMatrixAt(sum, result, rowIdx, colIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+7
-2
@@ -3,9 +3,14 @@
|
||||
|
||||
#define UNDEFINED_MATRIX_VALUE 0
|
||||
|
||||
typedef float MatrixType;
|
||||
typedef float MatrixType; //sets the datatype of the matrix
|
||||
|
||||
// TODO Matrixtyp definieren
|
||||
typedef struct
|
||||
{
|
||||
MatrixType *buffer;
|
||||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
} Matrix;
|
||||
|
||||
|
||||
Matrix createMatrix(unsigned int rows, unsigned int cols);
|
||||
|
||||
Reference in new issue
Block a user