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 매트릭스
0 |
0 |
8 |
1 |
0 |
0 |
234 |
96 |
시작! |
시작! |
앞의 (unsigned char) 8칸이 헤더이며, 그 이후부터는 데이터가 시작된다. 데이터의 내용은 다음과 같다.
28 x 28 매트릭스인 것을 감안하여 약간 비슷하게 출력 해보았는데 실제로 제일 위의 글씨와 동일한 순서로 나오는 것을 확인 할 수 있다.
소스에 의하면, arr[i][j] : i는 몇번째 숫자 혹은 알파벳 인지? j는 해당 숫자 혹은 알파벳의 픽셀값 이다.
train-labels.idx1-ubyte 파일 구조는 다음과 같다.
0 | 0 | 8 | 1 | 0 | 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(10000, 784, 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 |
---|