Author SHA1 Message Date
gloecknerma103472 5d5a51b805 Matrixpart 2026-11-11 10:17:57 +01:00
4 changed files with 46 additions and 256 deletions

No files matched your search

+3 -131
View File
@@ -6,145 +6,17 @@
#define BUFFER_SIZE 100 #define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__" #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 *readImages(const char *path)
{ {
GrayScaleImageSeries *series = NULL; 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; return series;
} }
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
void clearSeries(GrayScaleImageSeries *series) 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);
}
} }
+1 -1
View File
@@ -6,7 +6,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const unsigned int windowWidth = 800; const unsigned int windowWidth = 800; //Fenstergröße
const unsigned int windowHeight = 600; const unsigned int windowHeight = 600;
int exitCode = EXIT_FAILURE; int exitCode = EXIT_FAILURE;
+35 -118
View File
@@ -2,161 +2,78 @@
#include <string.h> #include <string.h>
#include "matrix.h" #include "matrix.h"
// TODO Matrix-Funktionen implementieren (done)
//Matrix Zeilen und Spaltenanzahl festlegen
Matrix createMatrix(unsigned int rows, unsigned int cols) Matrix createMatrix(unsigned int rows, unsigned int cols)
{ {
Matrix matrix = {NULL, 0, 0}; //Initialwerte, da unsicher ob allocierung funktioniert Matrix matrix;
if(rows > 0 && cols > 0)
{
MatrixType *buffer = (MatrixType *)calloc(rows * cols, sizeof(MatrixType));
if(buffer != NULL)
{
matrix.buffer = buffer;
matrix.rows = rows; matrix.rows = rows;
matrix.cols = cols; matrix.cols = cols;
} clearMatrix(&matrix);
}
return matrix; return matrix;
} }
//Matrix Speicher leeren
void clearMatrix(Matrix *matrix) void clearMatrix(Matrix *matrix)
{ {
if(matrix != NULL) for (int i=0; i < (*matrix).rows; i++)
{ {
free(matrix->buffer); for (int j = 0; j < (*matrix).cols; j++)
matrix->buffer = NULL; {
matrix->rows = 0; (*matrix).array[j][i] = 0;
matrix->cols = 0; }
} }
} }
//Matrix Werte setzen
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx) void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{ {
if(rowIdx < matrix.rows && colIdx < matrix.cols) if (rowIdx < 28 && colIdx < 28)
{ {
matrix.buffer[rowIdx * matrix.cols + colIdx] = value; matrix.array[rowIdx][colIdx] = value;
} }
} }
//Matrix Werte auslesen
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx) MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{ {
MatrixType value = UNDEFINED_MATRIX_VALUE; if (rowIdx < 28 && colIdx < 28)
if(rowIdx < matrix.rows && colIdx < matrix.cols)
{ {
value = matrix.buffer[rowIdx * matrix.cols + colIdx]; return matrix.array[rowIdx][colIdx];
} }
return 0;
return value;
} }
//Matrizen addieren
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 add(const Matrix matrix1, const Matrix matrix2)
{ {
Matrix result = {NULL, 0, 0}; //leere Matrix als Fehlerfall Matrix result = createMatrix(matrix1.rows, matrix1.cols);
if ((matrix1.rows != matrix2.rows) || (matrix1.cols != matrix2.cols)) //Überprüfung der Addierbarkeit zweier Matrizen
if(isValidMatrix(matrix1) && isValidMatrix(matrix2))
{ {
//normal add return result;
if(hasSameDimensions(matrix1, matrix2))
{
result = addElementWise(matrix1, matrix2);
} }
//add Broadcast matrix2 = vektor and matrix1 = matrix for (int i = 0; i < matrix1.rows; i++)
else if(isColumnVector(matrix2) && matrix1.rows == matrix2.rows)
{ {
result = addBroadcast(matrix1, matrix2); for (int j = 0; j < matrix1.cols; j++)
}
//add Broadcast matrix1 = vektor and matrix2 = matrix
else if(isColumnVector(matrix1) && matrix1.rows == matrix2.rows)
{ {
result = addBroadcast(matrix2, matrix1); result.array[i][j] = matrix1.array[i][j] + matrix2.array[i][j];
} }
} }
return result; return result;
} }
//Matrizen multiplizieren
/* (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 multiply(const Matrix matrix1, const Matrix matrix2)
{ {
Matrix result = {NULL, 0, 0}; //leere Matrix als Fehlerfall Matrix result = createMatrix(matrix1.rows, matrix2.cols);
if (matrix1.cols != matrix2.rows) //Überprüfung der Multiplizierbarkeit zweier Matrizen
if(isValidMatrix(matrix1) && isValidMatrix(matrix2) && matrix1.cols == matrix2.rows)
{ {
result = createMatrix(matrix1.rows, matrix2.cols); return result;
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);
} }
for (int i = 0; i < matrix1.rows; i++)
setMatrixAt(sum, result, rowIdx, colIdx); {
for (int j = 0; j < matrix2.cols; j++)
{
for (int k = 0; k < matrix1.cols; k++)
{
result.array[i][j] += (matrix1.array[i][k] * matrix2.array[k][j]);
} }
} }
} }
}
return result; return result;
} }
+7 -6
View File
@@ -3,16 +3,17 @@
#define UNDEFINED_MATRIX_VALUE 0 #define UNDEFINED_MATRIX_VALUE 0
typedef float MatrixType; //sets the datatype of the matrix typedef float MatrixType;
typedef struct // TODO Matrixtyp definieren (done)
typedef struct Matrix
{ {
MatrixType *buffer; int array[28][28]; //28 x 28 ist die Auflösung jedes Bildes
unsigned int rows; unsigned rows; //Zeilen
unsigned int cols; unsigned cols; //Spalten
short truenumber; //zwei Bite Länge am Ende jedes Bildes
} Matrix; } Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols); Matrix createMatrix(unsigned int rows, unsigned int cols);
void clearMatrix(Matrix *matrix); void clearMatrix(Matrix *matrix);
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx); void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx);