Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bb015fb56 | ||
|
|
cdc4a68824 | ||
|
|
d9bb6fd600 | ||
|
|
1f08837b74 | ||
|
|
19d6219998 | ||
|
|
70a7e6d20d | ||
|
|
d2065df23a | ||
|
|
833a4c3c79 | ||
|
|
edd9fc70e3 | ||
|
|
7c5a0c012f | ||
|
|
67f7325068 | ||
|
|
b755e9caf0 | ||
|
|
229c4c8b65 |
No files matched your search
@@ -37,6 +37,7 @@
|
||||
*.hex
|
||||
Startcode/mnist
|
||||
Startcode/runTests
|
||||
Startcode/run*Tests
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
|
||||
+194
-5
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user