Файл MNIST с прямым порядком байтов. Номера вне допустимого диапазона

Пытаюсь прочитать формат убайт. Я подтвердил, что нахожусь на машине с прямым порядком байтов, и перевернул биты на маленький порядок байтов. Однако проблема в том, что числа, которые я вижу в моем файле после преобразования, намного превышают 255.

Любые идеи? Я получил код из Как читать данные MNIST на C ++? и внес в него несколько изменений, но вот мой код

if (fin.is_open())
{
    int magic_number=0;
    int number_of_images=0;
    int n_rows=0;
    int n_cols=0;
    fin.read((char*)&magic_number,sizeof(magic_number));
    magic_number= flipBytes(magic_number);
    fin.read((char*)&number_of_images,sizeof(number_of_images));
    number_of_images= flipBytes(number_of_images);
    fin.read((char*)&n_rows,sizeof(n_rows));
    n_rows= flipBytes(n_rows);
    fin.read((char*)&n_cols,sizeof(n_cols));
    n_cols= flipBytes(n_cols);

    if(fin2.is_open())
    {
        int magic_number_label = 0;
        int number_of_items = 0;

        fin2.read((char*)&magic_number_label, sizeof(magic_number_label));
        magic_number_label = flipBytes(magic_number_label);
        fin2.read((char*)&number_of_items, sizeof(number_of_items));
        number_of_items = flipBytes(number_of_items);

        log << "Magic Number: " << magic_number << "\n";
        log << "Number of Images: " << number_of_images << "\n";
        log << "Number of Rows: " << n_rows << "\n";
        log << "Number of Cols: " << n_cols << "\n";
        log << "------------------------------\n";
        log << "Magic Number Label: " << magic_number_label << "\n";
        log << "Number of Items: " << number_of_items << "\n";

        for(int i=0;i<number_of_images;++i)
        {
            for(int r=0;r<n_rows;++r)
            {
                for(int c=0;c<n_cols;++c)
                {
                    unsigned int temp=0;
                    fin.read((char*)&temp,sizeof(temp));
                    temp = flipBytes(temp);

                    fout << temp << ", ";
                }
            }

            //ATTACH ANSWER
            unsigned int temp;
            fin2.read((char*)&temp, sizeof(temp));
            temp = flipBytes(temp);

            fout << temp << '\n';
        }
    }
}


int UbyteExtractor::flipBytes(int i)
{
    unsigned char c1, c2, c3, c4;

    c1 = i & 255;
    c2 = (i >> 8) & 255;
    c3 = (i >> 16) & 255;
    c4 = (i >> 24) & 255;

    return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}

Образец выходного фрагмента

0   0   0   0   0   0   303174147   447711358   2146959270  0   0   0   2589860894  4261281194  2900491773  1086583549  0   0   822083584   4261281262  4261281277  1381891069  2570322

person myselfesteem    schedule 23.04.2014    source источник
comment
Можете ли вы добавить ожидаемый результат?   -  person lethal-guitar    schedule 23.04.2014
comment
@ lethal-guitar Данные изображения из MNIST. Я знаю, что все числа представляют собой значения пикселей от 0 до 255, и каждое изображение имеет размер 28x28, но это все, что я могу сказать об ожидаемых результатах прямо сейчас.   -  person myselfesteem    schedule 23.04.2014
comment
Бегло взглянув на описание формата файла, можно предположить, что значения пикселей хранятся побайтно. Байт всегда один и тот же независимо от порядка байтов. Вы пробовали читать их побайтно, не переворачивая?   -  person lethal-guitar    schedule 24.04.2014
comment
Да, есть, и я получаю одинаково большие числа   -  person myselfesteem    schedule 24.04.2014


Ответы (1)


Вы читаете из файла 4 байта каждый, когда исходный ответ @mrgloom читает по 1 байту каждый. Это огромная разница.

mrgloom:

                unsigned char temp=0;
                file.read((char*)&temp,sizeof(temp));

Ты:

                unsigned int temp=0;
                fin.read((char*)&temp,sizeof(temp));
                temp = flipBytes(temp);

                fout << temp << ", ";

Возможно, вы хотели вывести на консоль числовое значение пикселей? Затем перед печатью приведите значение байта к (unsigned) int:

                unsigned char temp=0;
                fin.read((char*)&temp,sizeof(temp));

                fout << unsigned(temp) << ", ";

Кстати, к вашему сведению, есть стандартные библиотечные функции для замены порядка байтов:

Обновлять

Вот рабочее решение (по сути идентичное коду @ mrgloom)

#include <iostream>
#include <fstream>

using namespace std;

#include <arpa/inet.h>

#define ERROR() do {                                            \
    cout << "I/O error at " << __func__ << ": " << __LINE__ <<  \
        " (offset " << file.tellg() << ")" << endl;             \
    return;                                                     \
} while (0)

static void read_mnist(const string &full_path)
{
    ifstream file (full_path.c_str(), ios::binary);
    if ( ! file)
        ERROR();

    int magic_number=0;
    int number_of_images=0;
    int n_rows=0;
    int n_cols=0;
    if ( ! file.read((char*)&magic_number,sizeof(magic_number)))
        ERROR();
    magic_number= ntohl(magic_number);
    if ( ! file.read((char*)&number_of_images,sizeof(number_of_images)))
        ERROR();
    number_of_images= ntohl(number_of_images);
    if ( ! file.read((char*)&n_rows,sizeof(n_rows)))
        ERROR();
    n_rows= ntohl(n_rows);
    if ( ! file.read((char*)&n_cols,sizeof(n_cols)))
        ERROR();
    n_cols= ntohl(n_cols);

    cout << "Mgc==" << magic_number << "; NImg==" << number_of_images << "; "
        "NRow==" << n_rows << "; NCol==" << n_cols << endl;
    for(int i=0;i<number_of_images;++i)
    {
        cout << '[' << endl;
        for(int r=0;r<n_rows;++r)
        {
            cout << '\t' << '[' ;
            for(int c=0;c<n_cols;++c)
            {
                unsigned char temp=0;
                if ( ! file.read((char*)&temp,sizeof(temp)))
                    ERROR();
                cout << unsigned(temp) << ' ' ;
            }
            cout << ']' << endl;
        }
        cout << ']' << endl;
    }
}

int main(int argc, char *argv[]) {
    cout << "Process [" << argv[1] << "]" << endl;
    read_mnist(argv[1]);
}

Расшифровка:

$ wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
(snip)
$ gunzip t10k-images-idx3-ubyte.gz
$ ./mrgloom t10k-images-idx3-ubyte
Process [t10k-images-idx3-ubyte]
Mgc==2051; NImg==10000; NRow==28; NCol==28
[
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 84 185 159 151 60 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 222 254 254 254 254 241 198 198 198 198 198 198 198 198 170 52 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 67 114 72 114 163 227 254 225 254 254 254 250 229 254 254 140 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 17 66 14 67 67 67 59 21 236 254 106 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 83 253 209 18 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 233 255 83 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 129 254 238 44 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 249 254 62 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 133 254 187 5 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 205 248 58 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 126 254 182 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 75 251 240 57 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 19 221 254 166 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 3 203 254 219 35 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 38 254 254 77 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 31 224 254 115 1 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 133 254 254 52 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 61 242 254 254 52 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 121 254 254 219 40 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 121 254 207 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
        [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
]
[
(snip)
person nodakai    schedule 24.04.2014
comment
Верно, но когда я это делаю, каждый символ в моем файле равен 0 (с беззнаковым приведением). Я думаю, мне следует объявить unsigned char temp [4] для хранения целого числа, потому что целые числа имеют длину 4 байта. Я в правильном направлении? - person myselfesteem; 24.04.2014
comment
@myselfesteem нет, это звучит неправильно. Пиксели хранятся побайтно, целые числа не используются. Исходя из вашего примера вывода, вы обязательно должны увидеть некоторые ненулевые числа, если вы правильно прочитали их байт за байтом. - person lethal-guitar; 24.04.2014
comment
@myselfesteem Я добавил стенограмму - person nodakai; 24.04.2014