Compare commits

...
13 Commits
7 changed files with 334 additions and 14 deletions

No files matched your search

+1
View File
@@ -37,6 +37,7 @@
*.hex
Startcode/mnist
Startcode/runTests
Startcode/run*Tests
# Debug files
*.dSYM/
+194 -5
View File
@@ -6,17 +6,206 @@
#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: Fehlerfälle prüfen, prüfen auf 0-werten etc.
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path)
static int openAndCheck(FILE **fd, const char *path)
{
GrayScaleImageSeries *series = NULL;
int status = 0;
const size_t headerLen = sizeof(FILE_HEADER_STRING);
char *headerRead = calloc(1, headerLen);
if (headerRead == NULL) {
fprintf(stderr, "Error: could not allocate Memory for Header check\n");
return 1;
}
if (!(*fd = fopen(path, "rb")))
{
fprintf(stderr, "Error: could not open file %s\n", path);
status = 2;
goto ending_openAndCheck;
}
// size_t buf = 0;
if (!fread(headerRead, headerLen-1, 1, *fd))
{
fprintf(stderr, "Error: could not read file %s\n", path);
status = 1;
goto ending_openAndCheck;
}
if (strcmp(headerRead, FILE_HEADER_STRING)) // 0 = Keine Abweichung!
{
fprintf(stderr, "Error: %s header mismatch\n", path);
status = 1;
goto ending_openAndCheck;
}
ending_openAndCheck:
free(headerRead);
return status;
}
static int getUShort(FILE **fd, unsigned short *bilderAnzahl)
{
size_t bytes = 0;
if (!(bytes = fread(bilderAnzahl, (size_t)sizeof(unsigned short), 1, *fd)) || bytes != 1)
return 1;
return 0;
}
static int getUChar(FILE **fd, unsigned char *dest)
{
size_t bytes = 0;
if (!(bytes = fread(dest, sizeof(*dest), 1, *fd)) || bytes != 1)
return 1;
// printf("Read Label: %d\n", *dest);
return 0;
}
static int getPixelData(FILE **fd, const size_t bufSize, GrayScalePixelType *pixelData)
{
size_t readLen = 0;
if (!(readLen = fread((char *)pixelData, bufSize, 1, *fd)) || readLen != 1)
return 1;
return 0;
}
static GrayScaleImageSeries *getImageReihe(const char *path, int *status)
{
FILE *fd = NULL;
// printf("Opening %s\n", path);
*status = openAndCheck(&fd, path);
if (*status)
{
if (*status != 2)
fclose(fd);
;
return NULL;
}
// fd is at head of file, read dimensions:
unsigned short bilderAnzahl;
unsigned short width;
unsigned short height;
if (getUShort(&fd, &bilderAnzahl))
{
*status = 1;
fclose(fd);
return NULL;
}
if (getUShort(&fd, &width))
{
*status = 1;
fclose(fd);
return NULL;
}
if (getUShort(&fd, &height))
{
*status = 1;
fclose(fd);
return NULL;
}
// fd is at head of data, read calculated size:
// fprintf(stderr, "Anzahl: %d, Width: %d, Height: %d\n", bilderAnzahl, width, height);
GrayScaleImageSeries *series = (GrayScaleImageSeries *)calloc(bilderAnzahl, sizeof(GrayScaleImageSeries));
if (series == NULL) {
fprintf(stderr, "Error allocating Memory for Image Series\n");
fclose(fd);
return NULL;
}
GrayScaleImage *images = (GrayScaleImage *)calloc(bilderAnzahl, sizeof(GrayScaleImage));
if (images == NULL) {
fprintf(stderr, "Error allocating Memory for images\n");
free(series);
fclose(fd);
return NULL;
}
unsigned char *imageLabels = (unsigned char *)calloc(bilderAnzahl, sizeof(unsigned char));
if (imageLabels == NULL) {
fprintf(stderr, "Error allocating Memory for labels\n");
free(images);
free(series);
fclose(fd);
return NULL;
}
// read each image - pixelWerte dann Klasse
for (unsigned short i = 0; i < bilderAnzahl; ++i)
{
images[i].height = height;
images[i].width = width;
size_t bufSize = sizeof(GrayScalePixelType) * (width * height);
images[i].buffer = (GrayScalePixelType *)calloc(1, bufSize);
if (images[i].buffer == NULL) {
*status = 1;
free(imageLabels);
free(images);
free(series);
fclose(fd);
fprintf(stderr, "Error allocating pixel buffer\n");
return NULL;
}
// fprintf(stderr, "Reading %lu Bytes\n", bufSize);
if (getPixelData(&fd, bufSize, images[i].buffer))
{
*status = 1;
free(images[i].buffer);
free(imageLabels);
free(images);
free(series);
fclose(fd);
fprintf(stderr, "Error reading pixel data\n");
return NULL;
}
if (getUChar(&fd, &imageLabels[i]))
{
*status = 1;
free(images[i].buffer);
free(imageLabels);
free(images);
free(series);
fclose(fd);
fprintf(stderr, "Error reading image label\n");
return NULL;
}
}
series->images = images;
series->count = bilderAnzahl;
series->labels = imageLabels;
fclose(fd);
return series;
}
GrayScaleImageSeries *readImages(const char *path)
{
GrayScaleImageSeries *series = NULL;
int status = 0;
series = getImageReihe(path, &status);
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) return;
for (unsigned short i = 0; i < series->count; ++i)
{
free(series->images[i].buffer);
}
free(series->images);
free(series->labels);
free(series);
}
+39 -1
View File
@@ -35,7 +35,6 @@ static void prepareImageFile(const char *path, unsigned short int width, unsigne
}
}
void test_readImagesReturnsCorrectNumberOfImages(void)
{
GrayScaleImageSeries *series = NULL;
@@ -119,6 +118,43 @@ void test_readImagesFailsOnWrongFileTag(void)
remove(path);
}
int editSize(const char* path, const unsigned short w, const unsigned short h) {
FILE *fd = fopen(path, "rb+");
if (fd == NULL) return 1;
long x = 0;
// skip over header and image number
x += strlen("__info2_image_file_format__");
x += sizeof(unsigned short);
fseek(fd, x, SEEK_SET);
// set width & height
if (!fwrite(&w, sizeof(w), 1, fd)) return 1;
if (!fwrite(&h, sizeof(h), 1, fd)) return 1;
if (fclose(fd)) return 1;
return 0;
}
// Test if the sizes specify buffers which are larger than can be read from the file
// Errors as it runs into the end of the file
void test_sizes_wrong(void)
{
const unsigned char expectedLabel = 15;
const char *path = "testFile.info2";
prepareImageFile(path, 8, 8, 2, expectedLabel);
TEST_ASSERT_EQUAL_INT(0, editSize(path, 8, 9));
TEST_ASSERT_NULL(readImages(path));
remove(path);
}
void setUp(void) {
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
@@ -138,6 +174,8 @@ int main()
RUN_TEST(test_readImagesReturnsCorrectLabels);
RUN_TEST(test_readImagesReturnsNullOnNotExistingPath);
RUN_TEST(test_readImagesFailsOnWrongFileTag);
RUN_TEST(test_sizes_wrong);
return UNITY_END();
}
+75 -5
View File
@@ -6,30 +6,100 @@
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
if(rows == 0 || cols == 0){
return (Matrix) {0, 0, NULL}; // Compound struct, kann für c99 verwendet werden
}
MatrixType *arr = malloc(rows * cols * sizeof(MatrixType));
Matrix new_matrix = {rows, cols, arr};
return new_matrix;
}
void clearMatrix(Matrix *matrix)
{
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)
{
if(rowIdx >= matrix.rows || colIdx >= matrix.cols){
return 0;
}
return *(matrix.buffer + rowIdx * matrix.cols + colIdx);
}
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
int n1 = matrix1.cols;
int m1 = matrix1.rows;
int n2 = matrix2.cols;
int m2 = matrix2.rows;
if(n1 == 1 && m1 == m2){
Matrix new_mat = createMatrix(m2, n2);
for(int i = 0; i < m2; i++){
for(int j = 0; j < n2; j++){
*(new_mat.buffer + i * n2 + j) = *(matrix2.buffer + i * n2 + j) + *(matrix1.buffer + i);
}
}
return new_mat;
}
if(n2 == 1 && m1 == m2){
Matrix new_mat = createMatrix(m1, n1);
for(int i = 0; i < m1; i++){
for(int j = 0; j < n1; j++){
*(new_mat.buffer + i * n1 + j) = *(matrix1.buffer + i * n1 + j) + *(matrix2.buffer + i);
}
}
return new_mat;
}
if(n1 != n2 || m1 != m2){
return (Matrix) {0, 0, NULL};
}
Matrix new_mat = createMatrix(m1, n1);
for(int i = 0; i < m1; i++){
for(int j = 0; j < n1; j++){
*(new_mat.buffer + i * n1 + j) = *(matrix1.buffer + i * n1 + j) + *(matrix2.buffer + i * n1 + j);
}
}
return new_mat;
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
int m = matrix1.rows;
int q = matrix1.cols;
int l = matrix2.cols;
if(q != matrix2.rows){
return (Matrix) {0, 0, NULL};
}
Matrix new_matrix = createMatrix(m, l);
MatrixType *new_mat_arr = new_matrix.buffer;
for(int i = 0; i < m; i++){
for(int j = 0; j < l; j++){
int sum = 0;
for(int k = 0; k < q; k++){
sum += *(matrix1.buffer + i * q + k) * *(matrix2.buffer + k * l + j);
}
*(new_mat_arr + i * l + j) = sum;
}
}
return new_matrix;
}
+6
View File
@@ -7,6 +7,12 @@ typedef float MatrixType;
// TODO Matrixtyp definieren
typedef struct {
int rows;
int cols;
MatrixType *buffer;
} Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols);
void clearMatrix(Matrix *matrix);
+1 -1
View File
@@ -170,7 +170,7 @@ NeuralNetwork loadModel(const char *path)
static Matrix imageBatchToMatrixOfImageVectors(const GrayScaleImage images[], unsigned int count)
{
Matrix matrix = {NULL, 0, 0};
Matrix matrix = {0, 0, NULL};
if(count > 0 && images != NULL)
{
+18 -2
View File
@@ -4,11 +4,27 @@
#include <math.h>
#include "unity.h"
#include "neuralNetwork.h"
#define FILE_HEADER_STRING "__info2_neural_network_file_format__"
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{
// TODO
FILE *fd = fopen(path, "wb");
if (fd == NULL)
return;
fwrite(FILE_HEADER_STRING, strlen(FILE_HEADER_STRING), 1, fd);
// fwrite(&nn, sizeof(nn), 1, fd);
fwrite(&(nn.layers[0].weights.cols), sizeof(nn.layers[0].weights.cols), 1, fd);
for (int i = 0; i < nn.numberOfLayers; ++i)
{
fwrite(&(nn.layers[i].weights.rows), sizeof(nn.layers[i].weights.rows), 1, fd);
fwrite(nn.layers[i].weights.buffer, sizeof(MatrixType), nn.layers[i].weights.rows * nn.layers[i].weights.cols, fd);
fwrite(nn.layers[i].biases.buffer, sizeof(MatrixType), nn.layers[i].biases.rows, fd);
}
const int zeroooooo = 0;
fwrite(&zeroooooo, sizeof(int), 1, fd);
fclose(fd);
}
void test_loadModelReturnsCorrectNumberOfLayers(void)