C/C++ 圖像二進制存儲與讀取



本系列文章由 @yhl_leo 出品,轉載請注明出處。
文章鏈接: http://blog.csdn.net/yhl_leo/article/details/50782792


在深度學習時,制作樣本數據集時,須要產生和讀取一些二進制圖像的數據集,如MNISTCIFAR-10等都提供了適合C語言的二進制版本號。

以CIFAR-10的數據集為例。官網上有兩段關鍵的介紹:

二進制版本號數據集格式為(圖像大小為32x32):

<1 x label><3072 x pixel>
...
<1 x label><3072 x pixel>

In other words, the first byte is the label of the first image, which is a number in the range 0-9. The next 3072 bytes are the values of the pixels of the image. The first 1024 bytes are the red channel values, the next 1024 the green, and the final 1024 the blue. The values are stored in row-major order, so the first 32 bytes are the red channel values of the first row of the image.

由此,繪制一個簡圖:

memory

依據圖像大小32x32 = 1024,不難知道。每一個顏色值存儲為1 byte,因此,對於單個圖像的二進制存儲與讀取(先無論RGB顏色存儲順序)。找了一張32x32的彩色lena圖像。例如以下實現:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#include "cv.h"
#include "highgui.h"

using namespace cv;
using namespace std;

void main()
{
    FILE *fpw = fopen( "E:\\patch.bin", "wb" );
    if ( fpw == NULL )
    {
        cout << "Open error!" << endl;
        fclose(fpw);
        return;
    }

    Mat image = imread("E:\\lena32.jpg");
    if ( !image.data || image.channels() != 3 )
    {
        cout << "Image read failed or image channels isn't equal to 3."
            << endl;
        return;
    }

    // write image to binary format file
    int labelw = 1;
    int rows = image.rows;
    int cols = image.cols;

    fwrite( &labelw, sizeof(char), 1, fpw );

    char* dp = (char*)image.data;
    for ( int i=0; i<rows*cols; i++ )
    {
        fwrite( &dp[i*3],   sizeof(char), 1, fpw );
        fwrite( &dp[i*3+1], sizeof(char), 1, fpw );
        fwrite( &dp[i*3+2], sizeof(char), 1, fpw );
    }
    fclose(fpw);

    // read image from binary format file
    FILE *fpr = fopen( "E:\\patch.bin", "rb" );
    if ( fpr == NULL )
    {
        cout << "Open error!" << endl;
        fclose(fpr);
        return;
    }

    int labelr(0);
    fread( &labelr, sizeof(char), 1, fpr );

    cout << "label: " << labelr << endl;

    Mat image2( rows, cols, CV_8UC3, Scalar::all(0) );

    char* pData = (char*)image2.data;
    for ( int i=0; i<rows*cols; i++ )
    {
        fread( &pData[i*3],   sizeof(char), 1, fpr );
        fread( &pData[i*3+1], sizeof(char), 1, fpr );
        fread( &pData[i*3+2], sizeof(char), 1, fpr );
    }
    fclose(fpr);

    imshow("1", image2);
    waitKey(0); 
}

執行結果例如以下:

results

再看圖片屬性:

attribute

與官網上的大小3073一致,那么這么存取應該沒問題。

嚴格依照官網的RGB通道分別存儲,略作改動就能夠實現:

/* for ( int i=0; i<rows*cols; i++ ) { fwrite(&dp[i*3], sizeof(char), 1, fpw); fwrite(&dp[i*3+1], sizeof(char), 1, fpw); fwrite(&dp[i*3+2], sizeof(char), 1, fpw); } */

    for ( int i=0; i<rows*cols; i++ )
        fwrite(&dp[i*3+2],   sizeof(char), 1, fpw); // R

    for ( int i=0; i<rows*cols; i++ )
        fwrite(&dp[i*3+1],   sizeof(char), 1, fpw); // G

    for ( int i=0; i<rows*cols; i++ )
        fwrite(&dp[i*3],   sizeof(char), 1, fpw);  // B

存儲和讀取多張圖片方法相似,這里就不做介紹。

本文已同步於GitHub:yhlleo/image2binarytest


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM