【问题标题】:How to read pixels from MNIST digit database and create the iplimage如何从 MNIST 数字数据库中读取像素并创建 iplimage
【发布时间】:2013-06-01 10:05:38
【问题描述】:

抱歉,这可能有些重复,但我无法修复它。我参与了手写 OCR 应用程序。我在这里使用 MNIST 数字数据库进行训练。我使用以下代码here 从数据库中读取像素并重新创建图像。程序没有给出任何错误,但它给出了毫无意义的图像(全黑和不清晰的像素模式)作为输出。有人可以解释原因吗?请帮忙

这是我的代码

int reverseInt(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;
}

void create_image(CvSize size, int channels, unsigned char* data[28][28], int imagenumber) {
string imgname; ostringstream imgstrm;string fullpath;
imgstrm << imagenumber;
imgname=imgstrm.str();
fullpath="D:\\"+imgname+".jpg";

IplImage *imghead=cvCreateImageHeader(size, IPL_DEPTH_16S, channels);
imghead->imageData=(char *)data;
cvSaveImage(fullpath.c_str(),imghead);  
}
int main(){
ifstream file ("D:\\train-images.idx3-ubyte",ios::binary);
if (file.is_open())
{
    int magic_number=0; int number_of_images=0;int r; int c;
    int n_rows=0; int n_cols=0;CvSize size;unsigned char temp=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);
    unsigned char *arr[28][28];


    for(int i=0;i<number_of_images;++i)
    {
        for(r=0;r<n_rows;++r)
        {
            for(c=0;c<n_cols;++c)
            {                 
                file.read((char*)&temp,sizeof(temp));
                arr[r][c]= &temp;
            }           
        }
        size.height=r;size.width=c;
        create_image(size,1, arr, i);
    }
}
return 0;
}

【问题讨论】:

    标签: c++ opencv ocr


    【解决方案1】:

    你有:

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

    这样您就可以将一个字节读入单个字符,并用文件中的每个后续字节覆盖它。 当你这样做时:

    create_image(size,3, &temp, i);
    

    temp 只有一个字符长,并且只包含文件中的最后一个字节,因此您的图像最终只是临时后内存中发生的任何内容。 您需要分配一个数组来保存图像数据,并在向其中填充数据时增加一个指针。

    另外,您正在创建一个 3 通道图像,但 MNIST 数据只有单通道,对吧?

    还有,

    imghead->imageData=(char *)data;
    

    应该是

    cvSetData(imghead, data, size.width)
    

    unsigned char *arr[28][28];
    

    应该是

    unsigned char arr[28][28];
    

    【讨论】:

    • 非常感谢您考虑我的问题。它工作正常。非常感谢。
    【解决方案2】:

    我还想将 MNIST 与 OpenCV 一起使用,这个问题是我得到的最接近的问题。

    我以为我发布了基于cv::Mat 而不是iplimage 的“复制和粘贴->快乐”版本,因为这样更容易使用。此外,从 OpenCV 2.x 开始,首选 cv::Mat。 此方法为您提供一对cv::Mat 图像和标签作为ints 的向量。玩得开心。

    std::vector<std::pair<cv::Mat,int>> loadBinary(const std::string &datapath, const std::string &labelpath){
        std::vector<std::pair<cv::Mat,int>> dataset;
        std::ifstream datas(datapath,std::ios::binary);
        std::ifstream labels(labelpath,std::ios::binary);
    
        if (!datas.is_open() || !labels.is_open())
            throw std::runtime_error("binary files could not be loaded");
    
        int magic_number=0; int number_of_images=0;int r; int c;
        int n_rows=0; int n_cols=0; unsigned char temp=0;
    
        // parse data header
        datas.read((char*)&magic_number,sizeof(magic_number));
        magic_number=reverseInt(magic_number);
        datas.read((char*)&number_of_images,sizeof(number_of_images));
        number_of_images=reverseInt(number_of_images);
        datas.read((char*)&n_rows,sizeof(n_rows));
        n_rows=reverseInt(n_rows);
        datas.read((char*)&n_cols,sizeof(n_cols));
        n_cols=reverseInt(n_cols);
    
        // parse label header - ignore
        int dummy;
        labels.read((char*)&dummy,sizeof(dummy));
        labels.read((char*)&dummy,sizeof(dummy));
    
        for(int i=0;i<number_of_images;++i){
            cv::Mat img(n_rows,n_cols,CV_32FC1);
    
            for(r=0;r<n_rows;++r){
                for(c=0;c<n_cols;++c){
                    datas.read((char*)&temp,sizeof(temp));
                    img.at<float>(r,c) = 1.0-((float)temp)/255.0; // inverse 0.255 values
                }
            }
            labels.read((char*)&temp,sizeof(temp));
            dataset.push_back(std::make_pair(img,(int)temp));
        }
        return dataset;
    }
    

    同上:

    int reverseInt(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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多