Mnist 시작하기 (1)

 C++과 OpenCV를 활용하여 Mnist를 하려고 하니, 자료 찾기가 너무 힘들어서 공유하고자 만들었다.

우선, Mnist의 데이터 셋은 Yann LeCun 사이트에 있다. 

해당 사이트에서 트레이닝할 이미지인 train-images.idx3-ubyte 파일과 해당 레이블인 train-labels.idx1-ubyte 파일을 받을 수 있다. 

테스트 파일도 있지만 그건 나중에 하기로 하자.


train-images.idx3-ubyte 파일의 구조는 다음과 같다.

: Unsigned char, 28 x 28 매트릭스

 8

 1

 0

 234

96 

시작!

시작! 

앞의 (unsigned char) 8칸이 헤더이며, 그 이후부터는 데이터가 시작된다. 데이터의 내용은 다음과 같다. 

 28 x 28 매트릭스인 것을 감안하여 약간 비슷하게 출력 해보았는데 실제로 제일 위의 글씨와 동일한 순서로 나오는 것을 확인 할 수 있다. 

 소스에 의하면, arr[i][j] : i는 몇번째 숫자 혹은 알파벳 인지? j는 해당 숫자 혹은 알파벳의 픽셀값 이다.

  

train-labels.idx1-ubyte 파일 구조는 다음과 같다.

 8

 1

 0

 234

96 

5

0

 사실 위의 이미지의 파일 구조와 동일하고, 시작 되는 부분부터, 5, 0, 4, 1, 9 와 같은 해당 이미지에 대한 레이블이 등장한다.


 이를 가지고 특징 추출 후에 서로 매칭시켜서 나중에 CNN이나, SVM을 통해 학습 시키면 될 것 같다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
 
using namespace std;
int ReverseInt(int i);
void ReadMNIST(int NumberOfImages, int DataOfAnImage, vector<vector<double>> &arr);
void ReadMNISTLabel(vector<unsigned char> &arr);
 
int main()
{
    vector<vector<double>> ai;
    vector<unsigned char> al;
    ReadMNIST(10000784, ai);                // 훈련데이터를 불러옴
    ReadMNISTLabel(al);                        // 레이블을 읽어 옴
 
    return 0;
}
 
 
int ReverseInt(int i)
{
    unsigned char ch1, ch2, ch3, ch4;
    ch1 = i & 255;
    ch2 = (i >> 8) & 255;
    ch3 = (i >> 16) & 255;
    ch4 = (i >> 24) & 255;
    return((int)ch1 << 24+ ((int)ch2 << 16+ ((int)ch3 << 8+ ch4;
}
void ReadMNIST(int NumberOfImages, int DataOfAnImage, vector<vector<double>> &arr)   // MNIST데이터를 읽어온다.
{
    arr.resize(NumberOfImages, vector<double>(DataOfAnImage));
    ifstream file("train-images.idx3-ubyte", ios::binary);
    if (file.is_open())
    {
        int magic_number = 0;
        int number_of_images = 0;
        int n_rows = 0;
        int n_cols = 0;
 
        file.read((char*)&magic_number, sizeof(magic_number));
        magic_number = ReverseInt(magic_number);
        file.read((char*)&number_of_images, sizeof(number_of_images));
        number_of_images = ReverseInt(number_of_images);
        file.read((char*)&n_rows, sizeof(n_rows));
        n_rows = ReverseInt(n_rows);
        file.read((char*)&n_cols, sizeof(n_cols));
        n_cols = ReverseInt(n_cols);
 
        char inputstring[1000];
        for (int i = 0; i<10000++i)
        {
            for (int r = 0; r<n_rows; ++r)
            {
                for (int c = 0; c<n_cols; ++c)
                {
                    unsigned char temp = 0;
                    file.read((char*)&temp, sizeof(temp));
                    arr[i][(n_rows*r) + c] = (double)temp;
                }
            }
        }
    }
}
 
void ReadMNISTLabel(vector<unsigned char> &arr){                // 레이블을 읽어온다.
    ifstream file("train-labels.idx1-ubyte");
    for (int i = 0; i<10000++i)
    {
        unsigned char temp = 0;
        file.read((char*)&temp, sizeof(temp));
        if (i > 7)
            arr.push_back((unsigned char)temp);
 
    }
}
 
cs



참고 논문 및 사이트

1. Handwritten digits recognition using OpenCV, Vincent Neiger (2015)

2. https://compvisionlab.wordpress.com/2014/01/01/c-code-for-reading-mnist-data-set/ 

'프로그래밍 > OpenCV' 카테고리의 다른 글

Mnist with OpenCV (2)  (0) 2016.04.30

+ Recent posts