C++版加载MNIST图像集合

参考了一下两个链接:

Parsing MNIST data, save as bmp images · GitHub

(20条消息) C++读取MNIST数据集_N3verL4nd的博客-CSDN博客_c++读取mnist

 

大小端转换程序1:

void reverseInt(int& i)
{
    unsigned char ch1, ch2, ch3, ch4;
    ch1 = i & 255;
    ch2 = (i >> 8) & 255;
    ch3 = (i >> 16) & 255;
    ch4 = (i >> 24) & 255;
    i=((int)ch1 << 24) + ((int)ch2 << 16) + ((int)ch3 << 8) + ch4;
}

大小端转换程序2:

void swap_endian(uint32_t& val)
{
    val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
   val=(val << 16) | (val >> 16);
}

MNIST类:

class MNIST
{
public:

    Mat* m;//图库指针
    int* label;//标号指针。标号与图片一一对应。
    static int magic_num_l;//Label的魔数
    static int numOfImages_l;//Label与图片一一对应,该参数是图片数
    static int magic_num_i; //图库的魔数
    static int numOfImages_i;//图库的图片数,要与Label一一对应
};
int MNIST::magic_num_l=0;
int MNIST::numOfImages_l=0;
int MNIST:: magic_num_i=0; //图库的魔数
int MNIST::numOfImages_i=0;//图库的图片数,要与Label一一对应

 

 

加载图像集函数:

void readMnist(MNIST&mnist,string labelpath,string imgpath)
{
//    string filename="D:/Qt/MyImage/MNIST/train-labels.idx1-ubyte";

    ifstream file(labelpath, ios::binary);//打开Label文件的对象
    ifstream imgfile(imgpath, ios::binary);//打开图库的对象
    if(!file.is_open())
    {
        cerr<<"label open err!"<<endl;
        exit(1);
    }
    if(!file.is_open())
    {
        cerr<<"images set open err!"<<endl;
        exit(1);
    }
    int magic_num_l=0,numOfImages_l=0;//通过file读取Label的魔数和图片数,之后再赋值给MNIST成员变量
    int magic_num_i=0,numOfImages_i=0;//通过imgfile读取图库的魔数和图片数,之后再赋值给MNIST成员变量
    //读取图片label集的magic number和图片数量number of image.
    file.read((char*)&magic_num_l,sizeof(magic_num_l));
    file.read((char*)&numOfImages_l,sizeof(numOfImages_l));
    //读取image集合的magic number和图片数量number of image.
    imgfile.read((char*)&magic_num_i,sizeof(magic_num_i));
    imgfile.read((char*)&numOfImages_i,sizeof(numOfImages_i));
    //大小端转换
    reverseInt(magic_num_l);//label大小端转换
    reverseInt(numOfImages_l);//label大小端转换
    reverseInt(magic_num_i);//img magic number大小端转换
    reverseInt(numOfImages_i);//img number大小端转换
    cout<<"magic_num_l="<<magic_num_l<<" , numOfImages_l="<<numOfImages_l<<endl;
    cout<<"magic_num_i="<<magic_num_i<<" , numOfImages_i="<<numOfImages_i<<endl;
//     mnist=new MNIST[numOfImages_l];
     mnist.magic_num_l=magic_num_l;
     mnist.numOfImages_l=numOfImages_l;
     unsigned char * label=new unsigned char[numOfImages_l];
     mnist.label=new int[numOfImages_l];//为标号label分配内存
     mnist.m=new Mat[numOfImages_l];//为图像集分配内存
      file.read((char*)label,sizeof(char)*numOfImages_l);;//读取标号
//读取一副图片的行、列数
      uint img_rows,img_cols;
      imgfile.read((char*)&img_rows,sizeof(img_rows));
      imgfile.read((char*)&img_cols,sizeof(img_cols));
      swap_endian(img_rows);
      swap_endian(img_cols);
      cout<<"img_rows="<<img_rows<<" , img_cols="<<img_cols<<endl;
      //读取图像
      uchar *pixs=new uchar[img_rows*img_cols*numOfImages_i];
      imgfile.read((char*)pixs,img_rows*img_cols*numOfImages_i);


    for(int i=0;i<numOfImages_l;i++)
    {
       mnist.label[i]=label[i];
       uchar *p=pixs +i*img_cols*img_rows;
       mnist.m[i]=Mat(img_rows,img_cols,CV_8U,p);
    }

    file.close();
    imgfile.close();

}

 

 

 

演示程序:

int main()
{
    MNIST mnist;
    string labelpath="D:/Qt/MyImage/MNIST/train-labels.idx1-ubyte";
    string imgpath="D:/Qt/MyImage/MNIST/train-images.idx3-ubyte";
    readMnist(mnist,labelpath,imgpath);
    int blank=4;//图片之间间隔
    int width=(28+blank),height=(28+blank);
    Mat imgPlay(height*10,height*10,CV_8U,Scalar(255));
    for(int i=0;i<100;i++)
    {
        int y=i/10,x=i%10;
        Mat temp=imgPlay(Rect(x*width,y*height,width,height));
        Mat mi;
        copyMakeBorder(mnist.m[i],mi,0,blank,0,blank,BORDER_CONSTANT,Scalar(255));
        mi.copyTo(temp);
    }
    imshow("image demo",imgPlay);
    waitKey();
    return 0;
}

演示结果如下:

 

posted @ 2022-07-16 14:29  凤凰_1  阅读(229)  评论(0)    收藏  举报