MNIST-3LNN  1.0
A simple 3-layer neural network to recognize handwritten single digit numbers from the MNIST image files.
mnist-utils.c
Go to the documentation of this file.
1 /**
2  * @file mnist-utils.c
3  * @brief Utitlies for handling the MNIST files
4  * @see http://yann.lecun.com/exdb/mnist/
5  * @author Matt Lind
6  * @date July 2015
7  */
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "mnist-utils.h"
13 
14 
15 
16 /**
17  * @details Reverse byte order in 32bit numbers
18  * MNIST files contain all numbers in reversed byte order,
19  * and hence must be reversed before using
20  */
21 
22 uint32_t flipBytes(uint32_t n){
23 
24  uint32_t b0,b1,b2,b3;
25 
26  b0 = (n & 0x000000ff) << 24u;
27  b1 = (n & 0x0000ff00) << 8u;
28  b2 = (n & 0x00ff0000) >> 8u;
29  b3 = (n & 0xff000000) >> 24u;
30 
31  return (b0 | b1 | b2 | b3);
32 
33 }
34 
35 
36 
37 
38 /**
39  * @details Read MNIST image file header
40  * @see http://yann.lecun.com/exdb/mnist/ for definition details
41  */
42 
43 void readImageFileHeader(FILE *imageFile, MNIST_ImageFileHeader *ifh){
44 
45  ifh->magicNumber =0;
46  ifh->maxImages =0;
47  ifh->imgWidth =0;
48  ifh->imgHeight =0;
49 
50  fread(&ifh->magicNumber, 4, 1, imageFile);
51  ifh->magicNumber = flipBytes(ifh->magicNumber);
52 
53  fread(&ifh->maxImages, 4, 1, imageFile);
54  ifh->maxImages = flipBytes(ifh->maxImages);
55 
56  fread(&ifh->imgWidth, 4, 1, imageFile);
57  ifh->imgWidth = flipBytes(ifh->imgWidth);
58 
59  fread(&ifh->imgHeight, 4, 1, imageFile);
60  ifh->imgHeight = flipBytes(ifh->imgHeight);
61 }
62 
63 
64 
65 
66 /**
67  * @details Read MNIST label file header
68  * @see http://yann.lecun.com/exdb/mnist/ for definition details
69  */
70 
71 void readLabelFileHeader(FILE *imageFile, MNIST_LabelFileHeader *lfh){
72 
73  lfh->magicNumber =0;
74  lfh->maxImages =0;
75 
76  fread(&lfh->magicNumber, 4, 1, imageFile);
77  lfh->magicNumber = flipBytes(lfh->magicNumber);
78 
79  fread(&lfh->maxImages, 4, 1, imageFile);
80  lfh->maxImages = flipBytes(lfh->maxImages);
81 
82 }
83 
84 
85 
86 
87 /**
88  * @details Open MNIST image file and read header info
89  * by reading the header info, the read pointer
90  * is moved to the position of the 1st IMAGE
91  */
92 
93 FILE *openMNISTImageFile(char *fileName){
94 
95  FILE *imageFile;
96  imageFile = fopen (fileName, "rb");
97  if (imageFile == NULL) {
98  printf("Abort! Could not fine MNIST IMAGE file: %s\n",fileName);
99  exit(0);
100  }
101 
102  MNIST_ImageFileHeader imageFileHeader;
103  readImageFileHeader(imageFile, &imageFileHeader);
104 
105  return imageFile;
106 }
107 
108 
109 
110 
111 /**
112  * @details Open MNIST label file and read header info
113  * by reading the header info, the read pointer
114  * is moved to the position of the 1st LABEL
115  */
116 
117 FILE *openMNISTLabelFile(char *fileName){
118 
119  FILE *labelFile;
120  labelFile = fopen (fileName, "rb");
121  if (labelFile == NULL) {
122  printf("Abort! Could not find MNIST LABEL file: %s\n",fileName);
123  exit(0);
124  }
125 
126  MNIST_LabelFileHeader labelFileHeader;
127  readLabelFileHeader(labelFile, &labelFileHeader);
128 
129  return labelFile;
130 }
131 
132 
133 
134 
135 /**
136  * @details Returns the next image in the given MNIST image file
137  */
138 
139 MNIST_Image getImage(FILE *imageFile){
140 
141  MNIST_Image img;
142  size_t result;
143  result = fread(&img, sizeof(img), 1, imageFile);
144  if (result!=1) {
145  printf("\nError when reading IMAGE file! Abort!\n");
146  exit(1);
147  }
148 
149  return img;
150 }
151 
152 
153 
154 
155 /**
156  * @details Returns the next label in the given MNIST label file
157  */
158 
159 MNIST_Label getLabel(FILE *labelFile){
160 
161  MNIST_Label lbl;
162  size_t result;
163  result = fread(&lbl, sizeof(lbl), 1, labelFile);
164  if (result!=1) {
165  printf("\nError when reading LABEL file! Abort!\n");
166  exit(1);
167  }
168 
169  return lbl;
170 }
171 
172 
173 
174 
175 
176 
177 
178 int getStandardDigitPixel(int num, int pixelId){
179 
180  char numStr[(28*28)+1];
181 
182  switch (num) {
183 
184  case 1:
185  strcpy(numStr,"............................");
186  strcat(numStr,"............................");
187  strcat(numStr,"............................");
188  strcat(numStr,"............................");
189  strcat(numStr,"............XXXX............");
190  strcat(numStr,"............XXXX............");
191  strcat(numStr,"............XXXX............");
192  strcat(numStr,"............XXXX............");
193  strcat(numStr,"............XXXX............");
194  strcat(numStr,"............XXXX............");
195  strcat(numStr,"............XXXX............");
196  strcat(numStr,"............XXXX............");
197  strcat(numStr,"............XXXX............");
198  strcat(numStr,"............XXXX............");
199  strcat(numStr,"............XXXX............");
200  strcat(numStr,"............XXXX............");
201  strcat(numStr,"............XXXX............");
202  strcat(numStr,"............XXXX............");
203  strcat(numStr,"............XXXX............");
204  strcat(numStr,"............XXXX............");
205  strcat(numStr,"............XXXX............");
206  strcat(numStr,"............XXXX............");
207  strcat(numStr,"............XXXX............");
208  strcat(numStr,"............XXXX............");
209  strcat(numStr,"............................");
210  strcat(numStr,"............................");
211  strcat(numStr,"............................");
212  strcat(numStr,"............................");
213  break;
214 
215  case 2:
216  strcpy(numStr,"............................");
217  strcat(numStr,"............................");
218  strcat(numStr,"............................");
219  strcat(numStr,"............................");
220  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
221  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
222  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
223  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
224  strcat(numStr,"...................XXXXX....");
225  strcat(numStr,"....................XXXX....");
226  strcat(numStr,"....................XXXX....");
227  strcat(numStr,"...................XXXXX....");
228  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
229  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
230  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
231  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
232  strcat(numStr,"....XXXXX...................");
233  strcat(numStr,"....XXXX....................");
234  strcat(numStr,"....XXXX....................");
235  strcat(numStr,"....XXXXX...................");
236  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
237  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
238  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
239  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
240  strcat(numStr,"............................");
241  strcat(numStr,"............................");
242  strcat(numStr,"............................");
243  strcat(numStr,"............................");
244  break;
245 
246  case 3:
247  strcpy(numStr,"............................");
248  strcat(numStr,"............................");
249  strcat(numStr,"............................");
250  strcat(numStr,"............................");
251  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
252  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
253  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
254  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
255  strcat(numStr,"...................XXXXX....");
256  strcat(numStr,"....................XXXX....");
257  strcat(numStr,"....................XXXX....");
258  strcat(numStr,"...................XXXXX....");
259  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
260  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
261  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
262  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
263  strcat(numStr,"...................XXXXX....");
264  strcat(numStr,"....................XXXX....");
265  strcat(numStr,"....................XXXX....");
266  strcat(numStr,"...................XXXXX....");
267  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
268  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
269  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
270  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
271  strcat(numStr,"............................");
272  strcat(numStr,"............................");
273  strcat(numStr,"............................");
274  strcat(numStr,"............................");
275  break;
276 
277  case 4:
278  strcpy(numStr,"............................");
279  strcat(numStr,"............................");
280  strcat(numStr,"............................");
281  strcat(numStr,"............................");
282  strcat(numStr,"....XXXX....................");
283  strcat(numStr,"....XXXX....................");
284  strcat(numStr,"....XXXX....................");
285  strcat(numStr,"....XXXX....................");
286  strcat(numStr,"....XXXX.......XXXX.........");
287  strcat(numStr,"....XXXX.......XXXX.........");
288  strcat(numStr,"....XXXX.......XXXX.........");
289  strcat(numStr,"....XXXXX......XXXX.........");
290  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
291  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
292  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
293  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
294  strcat(numStr,"...............XXXX.........");
295  strcat(numStr,"...............XXXX.........");
296  strcat(numStr,"...............XXXX.........");
297  strcat(numStr,"...............XXXX.........");
298  strcat(numStr,"...............XXXX.........");
299  strcat(numStr,"...............XXXX.........");
300  strcat(numStr,"...............XXXX.........");
301  strcat(numStr,"...............XXXX.........");
302  strcat(numStr,"............................");
303  strcat(numStr,"............................");
304  strcat(numStr,"............................");
305  strcat(numStr,"............................");
306  break;
307 
308  case 5:
309  strcpy(numStr,"............................");
310  strcat(numStr,"............................");
311  strcat(numStr,"............................");
312  strcat(numStr,"............................");
313  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
314  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
315  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
316  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
317  strcat(numStr,"....XXXX....................");
318  strcat(numStr,"....XXXX....................");
319  strcat(numStr,"....XXXX....................");
320  strcat(numStr,"....XXXX....................");
321  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
322  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
323  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
324  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
325  strcat(numStr,"...................XXXXX....");
326  strcat(numStr,"....................XXXX....");
327  strcat(numStr,"....................XXXX....");
328  strcat(numStr,"...................XXXXX....");
329  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
330  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
331  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
332  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
333  strcat(numStr,"............................");
334  strcat(numStr,"............................");
335  strcat(numStr,"............................");
336  strcat(numStr,"............................");
337  break;
338 
339  case 6:
340  strcpy(numStr,"............................");
341  strcat(numStr,"............................");
342  strcat(numStr,"............................");
343  strcat(numStr,"............................");
344  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
345  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
346  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
347  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
348  strcat(numStr,"....XXXXX...................");
349  strcat(numStr,"....XXXX....................");
350  strcat(numStr,"....XXXX....................");
351  strcat(numStr,"....XXXXX...................");
352  strcat(numStr,"....XXXXXXXXXXXXXXXXXXX.....");
353  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
354  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
355  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
356  strcat(numStr,"....XXXXX..........XXXXX....");
357  strcat(numStr,"....XXXX............XXXX....");
358  strcat(numStr,"....XXXX............XXXX....");
359  strcat(numStr,"....XXXXX..........XXXXX....");
360  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
361  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
362  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
363  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
364  strcat(numStr,"............................");
365  strcat(numStr,"............................");
366  strcat(numStr,"............................");
367  strcat(numStr,"............................");
368  break;
369 
370  case 7:
371  strcpy(numStr,"............................");
372  strcat(numStr,"............................");
373  strcat(numStr,"............................");
374  strcat(numStr,"............................");
375  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
376  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
377  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
378  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
379  strcat(numStr,"...................XXXXX....");
380  strcat(numStr,"....................XXXX....");
381  strcat(numStr,"....................XXXX....");
382  strcat(numStr,"....................XXXX....");
383  strcat(numStr,"....................XXXX....");
384  strcat(numStr,"....................XXXX....");
385  strcat(numStr,"....................XXXX....");
386  strcat(numStr,"....................XXXX....");
387  strcat(numStr,"....................XXXX....");
388  strcat(numStr,"....................XXXX....");
389  strcat(numStr,"....................XXXX....");
390  strcat(numStr,"....................XXXX....");
391  strcat(numStr,"....................XXXX....");
392  strcat(numStr,"....................XXXX....");
393  strcat(numStr,"....................XXXX....");
394  strcat(numStr,"....................XXXX....");
395  strcat(numStr,"............................");
396  strcat(numStr,"............................");
397  strcat(numStr,"............................");
398  strcat(numStr,"............................");
399  break;
400 
401  case 8:
402  strcpy(numStr,"............................");
403  strcat(numStr,"............................");
404  strcat(numStr,"............................");
405  strcat(numStr,"............................");
406  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
407  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
408  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
409  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
410  strcat(numStr,"....XXXXX..........XXXXX....");
411  strcat(numStr,"....XXXX............XXXX....");
412  strcat(numStr,"....XXXX............XXXX....");
413  strcat(numStr,"....XXXXX..........XXXXX....");
414  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
415  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
416  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
417  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
418  strcat(numStr,"....XXXXX..........XXXXX....");
419  strcat(numStr,"....XXXX............XXXX....");
420  strcat(numStr,"....XXXX............XXXX....");
421  strcat(numStr,"....XXXXX..........XXXXX....");
422  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
423  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
424  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
425  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
426  strcat(numStr,"............................");
427  strcat(numStr,"............................");
428  strcat(numStr,"............................");
429  strcat(numStr,"............................");
430  break;
431 
432  case 9:
433  strcpy(numStr,"............................");
434  strcat(numStr,"............................");
435  strcat(numStr,"............................");
436  strcat(numStr,"............................");
437  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
438  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
439  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
440  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
441  strcat(numStr,"....XXXXX..........XXXXX....");
442  strcat(numStr,"....XXXX............XXXX....");
443  strcat(numStr,"....XXXX............XXXX....");
444  strcat(numStr,"....XXXXX..........XXXXX....");
445  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
446  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
447  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
448  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
449  strcat(numStr,"...................XXXXX....");
450  strcat(numStr,"....................XXXX....");
451  strcat(numStr,"....................XXXX....");
452  strcat(numStr,"...................XXXXX....");
453  strcat(numStr,".....XXXXXXXXXXXXXXXXXXX....");
454  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
455  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
456  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
457  strcat(numStr,"............................");
458  strcat(numStr,"............................");
459  strcat(numStr,"............................");
460  strcat(numStr,"............................");
461  break;
462 
463 
464  default:
465  strcpy(numStr,"............................");
466  strcat(numStr,"............................");
467  strcat(numStr,"............................");
468  strcat(numStr,"............................");
469  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
470  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
471  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
472  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
473  strcat(numStr,"....XXXXX..........XXXXX....");
474  strcat(numStr,"....XXXX............XXXX....");
475  strcat(numStr,"....XXXX............XXXX....");
476  strcat(numStr,"....XXXX............XXXX....");
477  strcat(numStr,"....XXXX............XXXX....");
478  strcat(numStr,"....XXXX............XXXX....");
479  strcat(numStr,"....XXXX............XXXX....");
480  strcat(numStr,"....XXXX............XXXX....");
481  strcat(numStr,"....XXXX............XXXX....");
482  strcat(numStr,"....XXXX............XXXX....");
483  strcat(numStr,"....XXXX............XXXX....");
484  strcat(numStr,"....XXXXX..........XXXXX....");
485  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
486  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
487  strcat(numStr,"....XXXXXXXXXXXXXXXXXXXX....");
488  strcat(numStr,".....XXXXXXXXXXXXXXXXXX.....");
489  strcat(numStr,"............................");
490  strcat(numStr,"............................");
491  strcat(numStr,"............................");
492  strcat(numStr,"............................");
493 
494  break;
495  }
496 
497  return (numStr[pixelId]=='X')?1:0;
498 
499 }
500 
501 
FILE * openMNISTImageFile(char *fileName)
Read MNIST IMAGE file header.
Definition: mnist-utils.c:93
FILE * openMNISTLabelFile(char *fileName)
Read MNIST label file header.
Definition: mnist-utils.c:117
MNIST_Label getLabel(FILE *labelFile)
Returns the next label in given MNIST label file.
Definition: mnist-utils.c:159
uint32_t flipBytes(uint32_t n)
Definition: mnist-utils.c:22
Data block defining a MNIST image file header.
Definition: mnist-utils.h:55
Data block defining a MNIST label file header.
Definition: mnist-utils.h:73
void readImageFileHeader(FILE *imageFile, MNIST_ImageFileHeader *ifh)
Definition: mnist-utils.c:43
Utitlies for handling the MNIST files.
MNIST_Image getImage(FILE *imageFile)
Returns the next image in given MNIST image file.
Definition: mnist-utils.c:139
int getStandardDigitPixel(int num, int pixelId)
Definition: mnist-utils.c:178
Data block defining a MNIST image.
Definition: mnist-utils.h:40
void readLabelFileHeader(FILE *imageFile, MNIST_LabelFileHeader *lfh)
Definition: mnist-utils.c:71
uint8_t MNIST_Label
Definition: mnist-utils.h:32